OSDN Git Service

merge from open-source master
[android-x86/frameworks-base.git] / services / java / com / android / server / WindowManagerService.java
1 /*
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
17 package com.android.server;
18
19 import static android.os.LocalPowerManager.CHEEK_EVENT;
20 import static android.os.LocalPowerManager.OTHER_EVENT;
21 import static android.os.LocalPowerManager.TOUCH_EVENT;
22 import static android.os.LocalPowerManager.LONG_TOUCH_EVENT;
23 import static android.os.LocalPowerManager.TOUCH_UP_EVENT;
24 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
25 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
26 import static android.view.WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
27 import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
28 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
29 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
30 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
31 import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
32 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
33 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
34 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
35 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
36 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
37 import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_PUSH_BUFFERS;
38 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
39 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
40 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
41 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
42 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
43
44 import com.android.internal.app.IBatteryStats;
45 import com.android.internal.policy.PolicyManager;
46 import com.android.internal.policy.impl.PhoneWindowManager;
47 import com.android.internal.view.IInputContext;
48 import com.android.internal.view.IInputMethodClient;
49 import com.android.internal.view.IInputMethodManager;
50 import com.android.internal.view.WindowManagerPolicyThread;
51 import com.android.server.KeyInputQueue.QueuedEvent;
52 import com.android.server.am.BatteryStatsService;
53
54 import android.Manifest;
55 import android.app.ActivityManagerNative;
56 import android.app.IActivityManager;
57 import android.app.admin.DevicePolicyManager;
58 import android.content.BroadcastReceiver;
59 import android.content.Context;
60 import android.content.Intent;
61 import android.content.IntentFilter;
62 import android.content.pm.ActivityInfo;
63 import android.content.pm.PackageManager;
64 import android.content.res.CompatibilityInfo;
65 import android.content.res.Configuration;
66 import android.graphics.Matrix;
67 import android.graphics.PixelFormat;
68 import android.graphics.Rect;
69 import android.graphics.Region;
70 import android.os.BatteryStats;
71 import android.os.Binder;
72 import android.os.Bundle;
73 import android.os.Debug;
74 import android.os.Handler;
75 import android.os.IBinder;
76 import android.os.LatencyTimer;
77 import android.os.LocalPowerManager;
78 import android.os.Looper;
79 import android.os.Message;
80 import android.os.Parcel;
81 import android.os.ParcelFileDescriptor;
82 import android.os.Power;
83 import android.os.PowerManager;
84 import android.os.Process;
85 import android.os.RemoteException;
86 import android.os.ServiceManager;
87 import android.os.SystemClock;
88 import android.os.SystemProperties;
89 import android.os.TokenWatcher;
90 import android.provider.Settings;
91 import android.util.DisplayMetrics;
92 import android.util.EventLog;
93 import android.util.Log;
94 import android.util.Slog;
95 import android.util.SparseIntArray;
96 import android.view.Display;
97 import android.view.Gravity;
98 import android.view.IApplicationToken;
99 import android.view.IOnKeyguardExitResult;
100 import android.view.IRotationWatcher;
101 import android.view.IWindow;
102 import android.view.IWindowManager;
103 import android.view.IWindowSession;
104 import android.view.KeyEvent;
105 import android.view.MotionEvent;
106 import android.view.RawInputEvent;
107 import android.view.Surface;
108 import android.view.SurfaceSession;
109 import android.view.View;
110 import android.view.ViewConfiguration;
111 import android.view.ViewTreeObserver;
112 import android.view.WindowManager;
113 import android.view.WindowManagerImpl;
114 import android.view.WindowManagerPolicy;
115 import android.view.WindowManager.LayoutParams;
116 import android.view.animation.AccelerateInterpolator;
117 import android.view.animation.Animation;
118 import android.view.animation.AnimationUtils;
119 import android.view.animation.Transformation;
120
121 import java.io.BufferedWriter;
122 import java.io.File;
123 import java.io.FileDescriptor;
124 import java.io.IOException;
125 import java.io.OutputStream;
126 import java.io.OutputStreamWriter;
127 import java.io.PrintWriter;
128 import java.io.StringWriter;
129 import java.net.Socket;
130 import java.util.ArrayList;
131 import java.util.HashMap;
132 import java.util.HashSet;
133 import java.util.Iterator;
134 import java.util.List;
135
136 /** {@hide} */
137 public class WindowManagerService extends IWindowManager.Stub
138         implements Watchdog.Monitor, KeyInputQueue.HapticFeedbackCallback {
139     static final String TAG = "WindowManager";
140     static final boolean DEBUG = false;
141     static final boolean DEBUG_FOCUS = false;
142     static final boolean DEBUG_ANIM = false;
143     static final boolean DEBUG_LAYOUT = false;
144     static final boolean DEBUG_RESIZE = false;
145     static final boolean DEBUG_LAYERS = false;
146     static final boolean DEBUG_INPUT = false;
147     static final boolean DEBUG_INPUT_METHOD = false;
148     static final boolean DEBUG_VISIBILITY = false;
149     static final boolean DEBUG_WINDOW_MOVEMENT = false;
150     static final boolean DEBUG_ORIENTATION = false;
151     static final boolean DEBUG_CONFIGURATION = false;
152     static final boolean DEBUG_APP_TRANSITIONS = false;
153     static final boolean DEBUG_STARTING_WINDOW = false;
154     static final boolean DEBUG_REORDER = false;
155     static final boolean DEBUG_WALLPAPER = false;
156     static final boolean DEBUG_FREEZE = false;
157     static final boolean SHOW_TRANSACTIONS = false;
158     static final boolean HIDE_STACK_CRAWLS = true;
159     static final boolean MEASURE_LATENCY = false;
160     static private LatencyTimer lt;
161
162     static final boolean PROFILE_ORIENTATION = false;
163     static final boolean BLUR = true;
164     static final boolean localLOGV = DEBUG;
165
166     /** How long to wait for subsequent key repeats, in milliseconds */
167     static final int KEY_REPEAT_DELAY = 50;
168
169     /** How much to multiply the policy's type layer, to reserve room
170      * for multiple windows of the same type and Z-ordering adjustment
171      * with TYPE_LAYER_OFFSET. */
172     static final int TYPE_LAYER_MULTIPLIER = 10000;
173
174     /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
175      * or below others in the same layer. */
176     static final int TYPE_LAYER_OFFSET = 1000;
177
178     /** How much to increment the layer for each window, to reserve room
179      * for effect surfaces between them.
180      */
181     static final int WINDOW_LAYER_MULTIPLIER = 5;
182
183     /** The maximum length we will accept for a loaded animation duration:
184      * this is 10 seconds.
185      */
186     static final int MAX_ANIMATION_DURATION = 10*1000;
187
188     /** Amount of time (in milliseconds) to animate the dim surface from one
189      * value to another, when no window animation is driving it.
190      */
191     static final int DEFAULT_DIM_DURATION = 200;
192
193     /** Amount of time (in milliseconds) to animate the fade-in-out transition for
194      * compatible windows.
195      */
196     static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
197
198     /** Adjustment to time to perform a dim, to make it more dramatic.
199      */
200     static final int DIM_DURATION_MULTIPLIER = 6;
201
202     static final int INJECT_FAILED = 0;
203     static final int INJECT_SUCCEEDED = 1;
204     static final int INJECT_NO_PERMISSION = -1;
205
206     static final int UPDATE_FOCUS_NORMAL = 0;
207     static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
208     static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
209     static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
210
211     /** The minimum time between dispatching touch events. */
212     int mMinWaitTimeBetweenTouchEvents = 1000 / 35;
213
214     // Last touch event time
215     long mLastTouchEventTime = 0;
216
217     // Last touch event type
218     int mLastTouchEventType = OTHER_EVENT;
219
220     // Time to wait before calling useractivity again. This saves CPU usage
221     // when we get a flood of touch events.
222     static final int MIN_TIME_BETWEEN_USERACTIVITIES = 1000;
223
224     // Last time we call user activity
225     long mLastUserActivityCallTime = 0;
226
227     // Last time we updated battery stats
228     long mLastBatteryStatsCallTime = 0;
229
230     private static final String SYSTEM_SECURE = "ro.secure";
231     private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
232
233     /**
234      * Condition waited on by {@link #reenableKeyguard} to know the call to
235      * the window policy has finished.
236      * This is set to true only if mKeyguardTokenWatcher.acquired() has
237      * actually disabled the keyguard.
238      */
239     private boolean mKeyguardDisabled = false;
240
241     private static final int ALLOW_DISABLE_YES = 1;
242     private static final int ALLOW_DISABLE_NO = 0;
243     private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager
244     private int mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; // sync'd by mKeyguardTokenWatcher
245
246     final TokenWatcher mKeyguardTokenWatcher = new TokenWatcher(
247             new Handler(), "WindowManagerService.mKeyguardTokenWatcher") {
248         public void acquired() {
249             if (shouldAllowDisableKeyguard()) {
250                 mPolicy.enableKeyguard(false);
251                 mKeyguardDisabled = true;
252             } else {
253                 Log.v(TAG, "Not disabling keyguard since device policy is enforced");
254             }
255         }
256         public void released() {
257             mPolicy.enableKeyguard(true);
258             synchronized (mKeyguardTokenWatcher) {
259                 mKeyguardDisabled = false;
260                 mKeyguardTokenWatcher.notifyAll();
261             }
262         }
263     };
264
265     final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
266         @Override
267         public void onReceive(Context context, Intent intent) {
268             mPolicy.enableKeyguard(true);
269             synchronized(mKeyguardTokenWatcher) {
270                 // lazily evaluate this next time we're asked to disable keyguard
271                 mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
272                 mKeyguardDisabled = false;
273             }
274         }
275     };
276
277     final Context mContext;
278
279     final boolean mHaveInputMethods;
280
281     final boolean mLimitedAlphaCompositing;
282
283     final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
284
285     final IActivityManager mActivityManager;
286
287     final IBatteryStats mBatteryStats;
288
289     /**
290      * All currently active sessions with clients.
291      */
292     final HashSet<Session> mSessions = new HashSet<Session>();
293
294     /**
295      * Mapping from an IWindow IBinder to the server's Window object.
296      * This is also used as the lock for all of our state.
297      */
298     final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
299
300     /**
301      * Mapping from a token IBinder to a WindowToken object.
302      */
303     final HashMap<IBinder, WindowToken> mTokenMap =
304             new HashMap<IBinder, WindowToken>();
305
306     /**
307      * The same tokens as mTokenMap, stored in a list for efficient iteration
308      * over them.
309      */
310     final ArrayList<WindowToken> mTokenList = new ArrayList<WindowToken>();
311
312     /**
313      * Window tokens that are in the process of exiting, but still
314      * on screen for animations.
315      */
316     final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
317
318     /**
319      * Z-ordered (bottom-most first) list of all application tokens, for
320      * controlling the ordering of windows in different applications.  This
321      * contains WindowToken objects.
322      */
323     final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
324
325     /**
326      * Application tokens that are in the process of exiting, but still
327      * on screen for animations.
328      */
329     final ArrayList<AppWindowToken> mExitingAppTokens = new ArrayList<AppWindowToken>();
330
331     /**
332      * List of window tokens that have finished starting their application,
333      * and now need to have the policy remove their windows.
334      */
335     final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
336
337     /**
338      * This was the app token that was used to retrieve the last enter
339      * animation.  It will be used for the next exit animation.
340      */
341     AppWindowToken mLastEnterAnimToken;
342
343     /**
344      * These were the layout params used to retrieve the last enter animation.
345      * They will be used for the next exit animation.
346      */
347     LayoutParams mLastEnterAnimParams;
348
349     /**
350      * Z-ordered (bottom-most first) list of all Window objects.
351      */
352     final ArrayList mWindows = new ArrayList();
353
354     /**
355      * Windows that are being resized.  Used so we can tell the client about
356      * the resize after closing the transaction in which we resized the
357      * underlying surface.
358      */
359     final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
360
361     /**
362      * Windows whose animations have ended and now must be removed.
363      */
364     final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
365
366     /**
367      * Windows whose surface should be destroyed.
368      */
369     final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
370
371     /**
372      * Windows that have lost input focus and are waiting for the new
373      * focus window to be displayed before they are told about this.
374      */
375     ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
376
377     /**
378      * This is set when we have run out of memory, and will either be an empty
379      * list or contain windows that need to be force removed.
380      */
381     ArrayList<WindowState> mForceRemoves;
382
383     IInputMethodManager mInputMethodManager;
384
385     SurfaceSession mFxSession;
386     private DimAnimator mDimAnimator = null;
387     Surface mBlurSurface;
388     boolean mBlurShown;
389
390     int mTransactionSequence = 0;
391
392     final float[] mTmpFloats = new float[9];
393
394     boolean mSafeMode;
395     boolean mDisplayEnabled = false;
396     boolean mSystemBooted = false;
397     int mInitialDisplayWidth = 0;
398     int mInitialDisplayHeight = 0;
399     int mRotation = 0;
400     int mRequestedRotation = 0;
401     int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
402     int mLastRotationFlags;
403     ArrayList<IRotationWatcher> mRotationWatchers
404             = new ArrayList<IRotationWatcher>();
405
406     boolean mLayoutNeeded = true;
407     boolean mAnimationPending = false;
408     boolean mDisplayFrozen = false;
409     boolean mWaitingForConfig = false;
410     boolean mWindowsFreezingScreen = false;
411     long mFreezeGcPending = 0;
412     int mAppsFreezingScreen = 0;
413
414     int mLayoutSeq = 0;
415     
416     // State while inside of layoutAndPlaceSurfacesLocked().
417     boolean mFocusMayChange;
418     
419     Configuration mCurConfiguration = new Configuration();
420     
421     // This is held as long as we have the screen frozen, to give us time to
422     // perform a rotation animation when turning off shows the lock screen which
423     // changes the orientation.
424     PowerManager.WakeLock mScreenFrozenLock;
425
426     // State management of app transitions.  When we are preparing for a
427     // transition, mNextAppTransition will be the kind of transition to
428     // perform or TRANSIT_NONE if we are not waiting.  If we are waiting,
429     // mOpeningApps and mClosingApps are the lists of tokens that will be
430     // made visible or hidden at the next transition.
431     int mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
432     String mNextAppTransitionPackage;
433     int mNextAppTransitionEnter;
434     int mNextAppTransitionExit;
435     boolean mAppTransitionReady = false;
436     boolean mAppTransitionRunning = false;
437     boolean mAppTransitionTimeout = false;
438     boolean mStartingIconInTransition = false;
439     boolean mSkipAppTransitionAnimation = false;
440     final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
441     final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
442     final ArrayList<AppWindowToken> mToTopApps = new ArrayList<AppWindowToken>();
443     final ArrayList<AppWindowToken> mToBottomApps = new ArrayList<AppWindowToken>();
444
445     //flag to detect fat touch events
446     boolean mFatTouch = false;
447     Display mDisplay;
448
449     H mH = new H();
450
451     WindowState mCurrentFocus = null;
452     WindowState mLastFocus = null;
453
454     // This just indicates the window the input method is on top of, not
455     // necessarily the window its input is going to.
456     WindowState mInputMethodTarget = null;
457     WindowState mUpcomingInputMethodTarget = null;
458     boolean mInputMethodTargetWaitingAnim;
459     int mInputMethodAnimLayerAdjustment;
460
461     WindowState mInputMethodWindow = null;
462     final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
463
464     final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
465
466     // If non-null, this is the currently visible window that is associated
467     // with the wallpaper.
468     WindowState mWallpaperTarget = null;
469     // If non-null, we are in the middle of animating from one wallpaper target
470     // to another, and this is the lower one in Z-order.
471     WindowState mLowerWallpaperTarget = null;
472     // If non-null, we are in the middle of animating from one wallpaper target
473     // to another, and this is the higher one in Z-order.
474     WindowState mUpperWallpaperTarget = null;
475     int mWallpaperAnimLayerAdjustment;
476     float mLastWallpaperX = -1;
477     float mLastWallpaperY = -1;
478     float mLastWallpaperXStep = -1;
479     float mLastWallpaperYStep = -1;
480     boolean mSendingPointersToWallpaper = false;
481     // This is set when we are waiting for a wallpaper to tell us it is done
482     // changing its scroll position.
483     WindowState mWaitingOnWallpaper;
484     // The last time we had a timeout when waiting for a wallpaper.
485     long mLastWallpaperTimeoutTime;
486     // We give a wallpaper up to 150ms to finish scrolling.
487     static final long WALLPAPER_TIMEOUT = 150;
488     // Time we wait after a timeout before trying to wait again.
489     static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
490
491     AppWindowToken mFocusedApp = null;
492
493     PowerManagerService mPowerManager;
494
495     float mWindowAnimationScale = 1.0f;
496     float mTransitionAnimationScale = 1.0f;
497
498     final KeyWaiter mKeyWaiter = new KeyWaiter();
499     final KeyQ mQueue;
500     final InputDispatcherThread mInputThread;
501
502     // Who is holding the screen on.
503     Session mHoldingScreenOn;
504
505     boolean mTurnOnScreen;
506
507     /**
508      * Whether the UI is currently running in touch mode (not showing
509      * navigational focus because the user is directly pressing the screen).
510      */
511     boolean mInTouchMode = false;
512
513     private ViewServer mViewServer;
514
515     final Rect mTempRect = new Rect();
516
517     final Configuration mTempConfiguration = new Configuration();
518     int mScreenLayout = Configuration.SCREENLAYOUT_SIZE_UNDEFINED;
519
520     // The frame use to limit the size of the app running in compatibility mode.
521     Rect mCompatibleScreenFrame = new Rect();
522     // The surface used to fill the outer rim of the app running in compatibility mode.
523     Surface mBackgroundFillerSurface = null;
524     boolean mBackgroundFillerShown = false;
525
526     public static WindowManagerService main(Context context,
527             PowerManagerService pm, boolean haveInputMethods) {
528         WMThread thr = new WMThread(context, pm, haveInputMethods);
529         thr.start();
530
531         synchronized (thr) {
532             while (thr.mService == null) {
533                 try {
534                     thr.wait();
535                 } catch (InterruptedException e) {
536                 }
537             }
538         }
539
540         return thr.mService;
541     }
542
543     static class WMThread extends Thread {
544         WindowManagerService mService;
545
546         private final Context mContext;
547         private final PowerManagerService mPM;
548         private final boolean mHaveInputMethods;
549
550         public WMThread(Context context, PowerManagerService pm,
551                 boolean haveInputMethods) {
552             super("WindowManager");
553             mContext = context;
554             mPM = pm;
555             mHaveInputMethods = haveInputMethods;
556         }
557
558         public void run() {
559             Looper.prepare();
560             WindowManagerService s = new WindowManagerService(mContext, mPM,
561                     mHaveInputMethods);
562             android.os.Process.setThreadPriority(
563                     android.os.Process.THREAD_PRIORITY_DISPLAY);
564
565             synchronized (this) {
566                 mService = s;
567                 notifyAll();
568             }
569
570             Looper.loop();
571         }
572     }
573
574     static class PolicyThread extends Thread {
575         private final WindowManagerPolicy mPolicy;
576         private final WindowManagerService mService;
577         private final Context mContext;
578         private final PowerManagerService mPM;
579         boolean mRunning = false;
580
581         public PolicyThread(WindowManagerPolicy policy,
582                 WindowManagerService service, Context context,
583                 PowerManagerService pm) {
584             super("WindowManagerPolicy");
585             mPolicy = policy;
586             mService = service;
587             mContext = context;
588             mPM = pm;
589         }
590
591         public void run() {
592             Looper.prepare();
593             WindowManagerPolicyThread.set(this, Looper.myLooper());
594             
595             //Looper.myLooper().setMessageLogging(new LogPrinter(
596             //        Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
597             android.os.Process.setThreadPriority(
598                     android.os.Process.THREAD_PRIORITY_FOREGROUND);
599             mPolicy.init(mContext, mService, mPM);
600
601             synchronized (this) {
602                 mRunning = true;
603                 notifyAll();
604             }
605
606             Looper.loop();
607         }
608     }
609
610     private WindowManagerService(Context context, PowerManagerService pm,
611             boolean haveInputMethods) {
612         if (MEASURE_LATENCY) {
613             lt = new LatencyTimer(100, 1000);
614         }
615
616         mContext = context;
617         mHaveInputMethods = haveInputMethods;
618         mLimitedAlphaCompositing = context.getResources().getBoolean(
619                 com.android.internal.R.bool.config_sf_limitedAlpha);
620
621         mPowerManager = pm;
622         mPowerManager.setPolicy(mPolicy);
623         PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
624         mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
625                 "SCREEN_FROZEN");
626         mScreenFrozenLock.setReferenceCounted(false);
627
628         mActivityManager = ActivityManagerNative.getDefault();
629         mBatteryStats = BatteryStatsService.getService();
630
631         // Get persisted window scale setting
632         mWindowAnimationScale = Settings.System.getFloat(context.getContentResolver(),
633                 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
634         mTransitionAnimationScale = Settings.System.getFloat(context.getContentResolver(),
635                 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
636
637         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
638         IntentFilter filter = new IntentFilter();
639         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
640         mContext.registerReceiver(mBroadcastReceiver, filter);
641
642         int max_events_per_sec = 35;
643         try {
644             max_events_per_sec = Integer.parseInt(SystemProperties
645                     .get("windowsmgr.max_events_per_sec"));
646             if (max_events_per_sec < 1) {
647                 max_events_per_sec = 35;
648             }
649         } catch (NumberFormatException e) {
650         }
651         mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
652
653         mQueue = new KeyQ();
654
655         mInputThread = new InputDispatcherThread();
656
657         PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
658         thr.start();
659
660         synchronized (thr) {
661             while (!thr.mRunning) {
662                 try {
663                     thr.wait();
664                 } catch (InterruptedException e) {
665                 }
666             }
667         }
668
669         mInputThread.start();
670         mQueue.start();
671
672         // Add ourself to the Watchdog monitors.
673         Watchdog.getInstance().addMonitor(this);
674     }
675
676     @Override
677     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
678             throws RemoteException {
679         try {
680             return super.onTransact(code, data, reply, flags);
681         } catch (RuntimeException e) {
682             // The window manager only throws security exceptions, so let's
683             // log all others.
684             if (!(e instanceof SecurityException)) {
685                 Slog.e(TAG, "Window Manager Crash", e);
686             }
687             throw e;
688         }
689     }
690
691     private void placeWindowAfter(Object pos, WindowState window) {
692         final int i = mWindows.indexOf(pos);
693         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
694             TAG, "Adding window " + window + " at "
695             + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
696         mWindows.add(i+1, window);
697     }
698
699     private void placeWindowBefore(Object pos, WindowState window) {
700         final int i = mWindows.indexOf(pos);
701         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
702             TAG, "Adding window " + window + " at "
703             + i + " of " + mWindows.size() + " (before " + pos + ")");
704         mWindows.add(i, window);
705     }
706
707     //This method finds out the index of a window that has the same app token as
708     //win. used for z ordering the windows in mWindows
709     private int findIdxBasedOnAppTokens(WindowState win) {
710         //use a local variable to cache mWindows
711         ArrayList localmWindows = mWindows;
712         int jmax = localmWindows.size();
713         if(jmax == 0) {
714             return -1;
715         }
716         for(int j = (jmax-1); j >= 0; j--) {
717             WindowState wentry = (WindowState)localmWindows.get(j);
718             if(wentry.mAppToken == win.mAppToken) {
719                 return j;
720             }
721         }
722         return -1;
723     }
724
725     private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
726         final IWindow client = win.mClient;
727         final WindowToken token = win.mToken;
728         final ArrayList localmWindows = mWindows;
729
730         final int N = localmWindows.size();
731         final WindowState attached = win.mAttachedWindow;
732         int i;
733         if (attached == null) {
734             int tokenWindowsPos = token.windows.size();
735             if (token.appWindowToken != null) {
736                 int index = tokenWindowsPos-1;
737                 if (index >= 0) {
738                     // If this application has existing windows, we
739                     // simply place the new window on top of them... but
740                     // keep the starting window on top.
741                     if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
742                         // Base windows go behind everything else.
743                         placeWindowBefore(token.windows.get(0), win);
744                         tokenWindowsPos = 0;
745                     } else {
746                         AppWindowToken atoken = win.mAppToken;
747                         if (atoken != null &&
748                                 token.windows.get(index) == atoken.startingWindow) {
749                             placeWindowBefore(token.windows.get(index), win);
750                             tokenWindowsPos--;
751                         } else {
752                             int newIdx =  findIdxBasedOnAppTokens(win);
753                             if(newIdx != -1) {
754                                 //there is a window above this one associated with the same
755                                 //apptoken note that the window could be a floating window
756                                 //that was created later or a window at the top of the list of
757                                 //windows associated with this token.
758                                 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
759                                         TAG, "Adding window " + win + " at "
760                                         + (newIdx+1) + " of " + N);
761                                 localmWindows.add(newIdx+1, win);
762                             }
763                         }
764                     }
765                 } else {
766                     if (localLOGV) Slog.v(
767                         TAG, "Figuring out where to add app window "
768                         + client.asBinder() + " (token=" + token + ")");
769                     // Figure out where the window should go, based on the
770                     // order of applications.
771                     final int NA = mAppTokens.size();
772                     Object pos = null;
773                     for (i=NA-1; i>=0; i--) {
774                         AppWindowToken t = mAppTokens.get(i);
775                         if (t == token) {
776                             i--;
777                             break;
778                         }
779
780                         // We haven't reached the token yet; if this token
781                         // is not going to the bottom and has windows, we can
782                         // use it as an anchor for when we do reach the token.
783                         if (!t.sendingToBottom && t.windows.size() > 0) {
784                             pos = t.windows.get(0);
785                         }
786                     }
787                     // We now know the index into the apps.  If we found
788                     // an app window above, that gives us the position; else
789                     // we need to look some more.
790                     if (pos != null) {
791                         // Move behind any windows attached to this one.
792                         WindowToken atoken =
793                             mTokenMap.get(((WindowState)pos).mClient.asBinder());
794                         if (atoken != null) {
795                             final int NC = atoken.windows.size();
796                             if (NC > 0) {
797                                 WindowState bottom = atoken.windows.get(0);
798                                 if (bottom.mSubLayer < 0) {
799                                     pos = bottom;
800                                 }
801                             }
802                         }
803                         placeWindowBefore(pos, win);
804                     } else {
805                         // Continue looking down until we find the first
806                         // token that has windows.
807                         while (i >= 0) {
808                             AppWindowToken t = mAppTokens.get(i);
809                             final int NW = t.windows.size();
810                             if (NW > 0) {
811                                 pos = t.windows.get(NW-1);
812                                 break;
813                             }
814                             i--;
815                         }
816                         if (pos != null) {
817                             // Move in front of any windows attached to this
818                             // one.
819                             WindowToken atoken =
820                                 mTokenMap.get(((WindowState)pos).mClient.asBinder());
821                             if (atoken != null) {
822                                 final int NC = atoken.windows.size();
823                                 if (NC > 0) {
824                                     WindowState top = atoken.windows.get(NC-1);
825                                     if (top.mSubLayer >= 0) {
826                                         pos = top;
827                                     }
828                                 }
829                             }
830                             placeWindowAfter(pos, win);
831                         } else {
832                             // Just search for the start of this layer.
833                             final int myLayer = win.mBaseLayer;
834                             for (i=0; i<N; i++) {
835                                 WindowState w = (WindowState)localmWindows.get(i);
836                                 if (w.mBaseLayer > myLayer) {
837                                     break;
838                                 }
839                             }
840                             if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
841                                     TAG, "Adding window " + win + " at "
842                                     + i + " of " + N);
843                             localmWindows.add(i, win);
844                         }
845                     }
846                 }
847             } else {
848                 // Figure out where window should go, based on layer.
849                 final int myLayer = win.mBaseLayer;
850                 for (i=N-1; i>=0; i--) {
851                     if (((WindowState)localmWindows.get(i)).mBaseLayer <= myLayer) {
852                         i++;
853                         break;
854                     }
855                 }
856                 if (i < 0) i = 0;
857                 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
858                         TAG, "Adding window " + win + " at "
859                         + i + " of " + N);
860                 localmWindows.add(i, win);
861             }
862             if (addToToken) {
863                 token.windows.add(tokenWindowsPos, win);
864             }
865
866         } else {
867             // Figure out this window's ordering relative to the window
868             // it is attached to.
869             final int NA = token.windows.size();
870             final int sublayer = win.mSubLayer;
871             int largestSublayer = Integer.MIN_VALUE;
872             WindowState windowWithLargestSublayer = null;
873             for (i=0; i<NA; i++) {
874                 WindowState w = token.windows.get(i);
875                 final int wSublayer = w.mSubLayer;
876                 if (wSublayer >= largestSublayer) {
877                     largestSublayer = wSublayer;
878                     windowWithLargestSublayer = w;
879                 }
880                 if (sublayer < 0) {
881                     // For negative sublayers, we go below all windows
882                     // in the same sublayer.
883                     if (wSublayer >= sublayer) {
884                         if (addToToken) {
885                             token.windows.add(i, win);
886                         }
887                         placeWindowBefore(
888                             wSublayer >= 0 ? attached : w, win);
889                         break;
890                     }
891                 } else {
892                     // For positive sublayers, we go above all windows
893                     // in the same sublayer.
894                     if (wSublayer > sublayer) {
895                         if (addToToken) {
896                             token.windows.add(i, win);
897                         }
898                         placeWindowBefore(w, win);
899                         break;
900                     }
901                 }
902             }
903             if (i >= NA) {
904                 if (addToToken) {
905                     token.windows.add(win);
906                 }
907                 if (sublayer < 0) {
908                     placeWindowBefore(attached, win);
909                 } else {
910                     placeWindowAfter(largestSublayer >= 0
911                                      ? windowWithLargestSublayer
912                                      : attached,
913                                      win);
914                 }
915             }
916         }
917
918         if (win.mAppToken != null && addToToken) {
919             win.mAppToken.allAppWindows.add(win);
920         }
921     }
922
923     static boolean canBeImeTarget(WindowState w) {
924         final int fl = w.mAttrs.flags
925                 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
926         if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) {
927             return w.isVisibleOrAdding();
928         }
929         return false;
930     }
931
932     int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
933         final ArrayList localmWindows = mWindows;
934         final int N = localmWindows.size();
935         WindowState w = null;
936         int i = N;
937         while (i > 0) {
938             i--;
939             w = (WindowState)localmWindows.get(i);
940
941             //Slog.i(TAG, "Checking window @" + i + " " + w + " fl=0x"
942             //        + Integer.toHexString(w.mAttrs.flags));
943             if (canBeImeTarget(w)) {
944                 //Slog.i(TAG, "Putting input method here!");
945
946                 // Yet more tricksyness!  If this window is a "starting"
947                 // window, we do actually want to be on top of it, but
948                 // it is not -really- where input will go.  So if the caller
949                 // is not actually looking to move the IME, look down below
950                 // for a real window to target...
951                 if (!willMove
952                         && w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
953                         && i > 0) {
954                     WindowState wb = (WindowState)localmWindows.get(i-1);
955                     if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
956                         i--;
957                         w = wb;
958                     }
959                 }
960                 break;
961             }
962         }
963
964         mUpcomingInputMethodTarget = w;
965
966         if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
967                 + w + " willMove=" + willMove);
968
969         if (willMove && w != null) {
970             final WindowState curTarget = mInputMethodTarget;
971             if (curTarget != null && curTarget.mAppToken != null) {
972
973                 // Now some fun for dealing with window animations that
974                 // modify the Z order.  We need to look at all windows below
975                 // the current target that are in this app, finding the highest
976                 // visible one in layering.
977                 AppWindowToken token = curTarget.mAppToken;
978                 WindowState highestTarget = null;
979                 int highestPos = 0;
980                 if (token.animating || token.animation != null) {
981                     int pos = 0;
982                     pos = localmWindows.indexOf(curTarget);
983                     while (pos >= 0) {
984                         WindowState win = (WindowState)localmWindows.get(pos);
985                         if (win.mAppToken != token) {
986                             break;
987                         }
988                         if (!win.mRemoved) {
989                             if (highestTarget == null || win.mAnimLayer >
990                                     highestTarget.mAnimLayer) {
991                                 highestTarget = win;
992                                 highestPos = pos;
993                             }
994                         }
995                         pos--;
996                     }
997                 }
998
999                 if (highestTarget != null) {
1000                     if (DEBUG_INPUT_METHOD) Slog.v(TAG, "mNextAppTransition="
1001                             + mNextAppTransition + " " + highestTarget
1002                             + " animating=" + highestTarget.isAnimating()
1003                             + " layer=" + highestTarget.mAnimLayer
1004                             + " new layer=" + w.mAnimLayer);
1005
1006                     if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
1007                         // If we are currently setting up for an animation,
1008                         // hold everything until we can find out what will happen.
1009                         mInputMethodTargetWaitingAnim = true;
1010                         mInputMethodTarget = highestTarget;
1011                         return highestPos + 1;
1012                     } else if (highestTarget.isAnimating() &&
1013                             highestTarget.mAnimLayer > w.mAnimLayer) {
1014                         // If the window we are currently targeting is involved
1015                         // with an animation, and it is on top of the next target
1016                         // we will be over, then hold off on moving until
1017                         // that is done.
1018                         mInputMethodTarget = highestTarget;
1019                         return highestPos + 1;
1020                     }
1021                 }
1022             }
1023         }
1024
1025         //Slog.i(TAG, "Placing input method @" + (i+1));
1026         if (w != null) {
1027             if (willMove) {
1028                 if (DEBUG_INPUT_METHOD) {
1029                     RuntimeException e = null;
1030                     if (!HIDE_STACK_CRAWLS) {
1031                         e = new RuntimeException();
1032                         e.fillInStackTrace();
1033                     }
1034                     Slog.w(TAG, "Moving IM target from "
1035                             + mInputMethodTarget + " to " + w, e);
1036                 }
1037                 mInputMethodTarget = w;
1038                 if (w.mAppToken != null) {
1039                     setInputMethodAnimLayerAdjustment(w.mAppToken.animLayerAdjustment);
1040                 } else {
1041                     setInputMethodAnimLayerAdjustment(0);
1042                 }
1043             }
1044             return i+1;
1045         }
1046         if (willMove) {
1047             if (DEBUG_INPUT_METHOD) {
1048                 RuntimeException e = null;
1049                 if (!HIDE_STACK_CRAWLS) {
1050                     e = new RuntimeException();
1051                     e.fillInStackTrace();
1052                 }
1053                 Slog.w(TAG, "Moving IM target from "
1054                         + mInputMethodTarget + " to null", e);
1055             }
1056             mInputMethodTarget = null;
1057             setInputMethodAnimLayerAdjustment(0);
1058         }
1059         return -1;
1060     }
1061
1062     void addInputMethodWindowToListLocked(WindowState win) {
1063         int pos = findDesiredInputMethodWindowIndexLocked(true);
1064         if (pos >= 0) {
1065             win.mTargetAppToken = mInputMethodTarget.mAppToken;
1066             if (DEBUG_WINDOW_MOVEMENT) Slog.v(
1067                     TAG, "Adding input method window " + win + " at " + pos);
1068             mWindows.add(pos, win);
1069             moveInputMethodDialogsLocked(pos+1);
1070             return;
1071         }
1072         win.mTargetAppToken = null;
1073         addWindowToListInOrderLocked(win, true);
1074         moveInputMethodDialogsLocked(pos);
1075     }
1076
1077     void setInputMethodAnimLayerAdjustment(int adj) {
1078         if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj);
1079         mInputMethodAnimLayerAdjustment = adj;
1080         WindowState imw = mInputMethodWindow;
1081         if (imw != null) {
1082             imw.mAnimLayer = imw.mLayer + adj;
1083             if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
1084                     + " anim layer: " + imw.mAnimLayer);
1085             int wi = imw.mChildWindows.size();
1086             while (wi > 0) {
1087                 wi--;
1088                 WindowState cw = (WindowState)imw.mChildWindows.get(wi);
1089                 cw.mAnimLayer = cw.mLayer + adj;
1090                 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw
1091                         + " anim layer: " + cw.mAnimLayer);
1092             }
1093         }
1094         int di = mInputMethodDialogs.size();
1095         while (di > 0) {
1096             di --;
1097             imw = mInputMethodDialogs.get(di);
1098             imw.mAnimLayer = imw.mLayer + adj;
1099             if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
1100                     + " anim layer: " + imw.mAnimLayer);
1101         }
1102     }
1103
1104     private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1105         int wpos = mWindows.indexOf(win);
1106         if (wpos >= 0) {
1107             if (wpos < interestingPos) interestingPos--;
1108             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
1109             mWindows.remove(wpos);
1110             int NC = win.mChildWindows.size();
1111             while (NC > 0) {
1112                 NC--;
1113                 WindowState cw = (WindowState)win.mChildWindows.get(NC);
1114                 int cpos = mWindows.indexOf(cw);
1115                 if (cpos >= 0) {
1116                     if (cpos < interestingPos) interestingPos--;
1117                     if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
1118                             + cpos + ": " + cw);
1119                     mWindows.remove(cpos);
1120                 }
1121             }
1122         }
1123         return interestingPos;
1124     }
1125
1126     private void reAddWindowToListInOrderLocked(WindowState win) {
1127         addWindowToListInOrderLocked(win, false);
1128         // This is a hack to get all of the child windows added as well
1129         // at the right position.  Child windows should be rare and
1130         // this case should be rare, so it shouldn't be that big a deal.
1131         int wpos = mWindows.indexOf(win);
1132         if (wpos >= 0) {
1133             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos
1134                     + ": " + win);
1135             mWindows.remove(wpos);
1136             reAddWindowLocked(wpos, win);
1137         }
1138     }
1139
1140     void logWindowList(String prefix) {
1141         int N = mWindows.size();
1142         while (N > 0) {
1143             N--;
1144             Slog.v(TAG, prefix + "#" + N + ": " + mWindows.get(N));
1145         }
1146     }
1147
1148     void moveInputMethodDialogsLocked(int pos) {
1149         ArrayList<WindowState> dialogs = mInputMethodDialogs;
1150
1151         final int N = dialogs.size();
1152         if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
1153         for (int i=0; i<N; i++) {
1154             pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1155         }
1156         if (DEBUG_INPUT_METHOD) {
1157             Slog.v(TAG, "Window list w/pos=" + pos);
1158             logWindowList("  ");
1159         }
1160
1161         if (pos >= 0) {
1162             final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1163             if (pos < mWindows.size()) {
1164                 WindowState wp = (WindowState)mWindows.get(pos);
1165                 if (wp == mInputMethodWindow) {
1166                     pos++;
1167                 }
1168             }
1169             if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
1170             for (int i=0; i<N; i++) {
1171                 WindowState win = dialogs.get(i);
1172                 win.mTargetAppToken = targetAppToken;
1173                 pos = reAddWindowLocked(pos, win);
1174             }
1175             if (DEBUG_INPUT_METHOD) {
1176                 Slog.v(TAG, "Final window list:");
1177                 logWindowList("  ");
1178             }
1179             return;
1180         }
1181         for (int i=0; i<N; i++) {
1182             WindowState win = dialogs.get(i);
1183             win.mTargetAppToken = null;
1184             reAddWindowToListInOrderLocked(win);
1185             if (DEBUG_INPUT_METHOD) {
1186                 Slog.v(TAG, "No IM target, final list:");
1187                 logWindowList("  ");
1188             }
1189         }
1190     }
1191
1192     boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1193         final WindowState imWin = mInputMethodWindow;
1194         final int DN = mInputMethodDialogs.size();
1195         if (imWin == null && DN == 0) {
1196             return false;
1197         }
1198
1199         int imPos = findDesiredInputMethodWindowIndexLocked(true);
1200         if (imPos >= 0) {
1201             // In this case, the input method windows are to be placed
1202             // immediately above the window they are targeting.
1203
1204             // First check to see if the input method windows are already
1205             // located here, and contiguous.
1206             final int N = mWindows.size();
1207             WindowState firstImWin = imPos < N
1208                     ? (WindowState)mWindows.get(imPos) : null;
1209
1210             // Figure out the actual input method window that should be
1211             // at the bottom of their stack.
1212             WindowState baseImWin = imWin != null
1213                     ? imWin : mInputMethodDialogs.get(0);
1214             if (baseImWin.mChildWindows.size() > 0) {
1215                 WindowState cw = (WindowState)baseImWin.mChildWindows.get(0);
1216                 if (cw.mSubLayer < 0) baseImWin = cw;
1217             }
1218
1219             if (firstImWin == baseImWin) {
1220                 // The windows haven't moved...  but are they still contiguous?
1221                 // First find the top IM window.
1222                 int pos = imPos+1;
1223                 while (pos < N) {
1224                     if (!((WindowState)mWindows.get(pos)).mIsImWindow) {
1225                         break;
1226                     }
1227                     pos++;
1228                 }
1229                 pos++;
1230                 // Now there should be no more input method windows above.
1231                 while (pos < N) {
1232                     if (((WindowState)mWindows.get(pos)).mIsImWindow) {
1233                         break;
1234                     }
1235                     pos++;
1236                 }
1237                 if (pos >= N) {
1238                     // All is good!
1239                     return false;
1240                 }
1241             }
1242
1243             if (imWin != null) {
1244                 if (DEBUG_INPUT_METHOD) {
1245                     Slog.v(TAG, "Moving IM from " + imPos);
1246                     logWindowList("  ");
1247                 }
1248                 imPos = tmpRemoveWindowLocked(imPos, imWin);
1249                 if (DEBUG_INPUT_METHOD) {
1250                     Slog.v(TAG, "List after moving with new pos " + imPos + ":");
1251                     logWindowList("  ");
1252                 }
1253                 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1254                 reAddWindowLocked(imPos, imWin);
1255                 if (DEBUG_INPUT_METHOD) {
1256                     Slog.v(TAG, "List after moving IM to " + imPos + ":");
1257                     logWindowList("  ");
1258                 }
1259                 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1260             } else {
1261                 moveInputMethodDialogsLocked(imPos);
1262             }
1263
1264         } else {
1265             // In this case, the input method windows go in a fixed layer,
1266             // because they aren't currently associated with a focus window.
1267
1268             if (imWin != null) {
1269                 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos);
1270                 tmpRemoveWindowLocked(0, imWin);
1271                 imWin.mTargetAppToken = null;
1272                 reAddWindowToListInOrderLocked(imWin);
1273                 if (DEBUG_INPUT_METHOD) {
1274                     Slog.v(TAG, "List with no IM target:");
1275                     logWindowList("  ");
1276                 }
1277                 if (DN > 0) moveInputMethodDialogsLocked(-1);;
1278             } else {
1279                 moveInputMethodDialogsLocked(-1);;
1280             }
1281
1282         }
1283
1284         if (needAssignLayers) {
1285             assignLayersLocked();
1286         }
1287
1288         return true;
1289     }
1290
1291     void adjustInputMethodDialogsLocked() {
1292         moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
1293     }
1294
1295     final boolean isWallpaperVisible(WindowState wallpaperTarget) {
1296         if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target obscured="
1297                 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
1298                 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
1299                         ? wallpaperTarget.mAppToken.animation : null)
1300                 + " upper=" + mUpperWallpaperTarget
1301                 + " lower=" + mLowerWallpaperTarget);
1302         return (wallpaperTarget != null
1303                         && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
1304                                 && wallpaperTarget.mAppToken.animation != null)))
1305                 || mUpperWallpaperTarget != null
1306                 || mLowerWallpaperTarget != null;
1307     }
1308
1309     static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
1310     static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
1311
1312     int adjustWallpaperWindowsLocked() {
1313         int changed = 0;
1314
1315         final int dw = mDisplay.getWidth();
1316         final int dh = mDisplay.getHeight();
1317
1318         // First find top-most window that has asked to be on top of the
1319         // wallpaper; all wallpapers go behind it.
1320         final ArrayList localmWindows = mWindows;
1321         int N = localmWindows.size();
1322         WindowState w = null;
1323         WindowState foundW = null;
1324         int foundI = 0;
1325         WindowState topCurW = null;
1326         int topCurI = 0;
1327         int i = N;
1328         while (i > 0) {
1329             i--;
1330             w = (WindowState)localmWindows.get(i);
1331             if ((w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER)) {
1332                 if (topCurW == null) {
1333                     topCurW = w;
1334                     topCurI = i;
1335                 }
1336                 continue;
1337             }
1338             topCurW = null;
1339             if (w.mAppToken != null) {
1340                 // If this window's app token is hidden and not animating,
1341                 // it is of no interest to us.
1342                 if (w.mAppToken.hidden && w.mAppToken.animation == null) {
1343                     if (DEBUG_WALLPAPER) Slog.v(TAG,
1344                             "Skipping hidden or animating token: " + w);
1345                     topCurW = null;
1346                     continue;
1347                 }
1348             }
1349             if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w + ": readyfordisplay="
1350                     + w.isReadyForDisplay() + " drawpending=" + w.mDrawPending
1351                     + " commitdrawpending=" + w.mCommitDrawPending);
1352             if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()
1353                     && (mWallpaperTarget == w
1354                             || (!w.mDrawPending && !w.mCommitDrawPending))) {
1355                 if (DEBUG_WALLPAPER) Slog.v(TAG,
1356                         "Found wallpaper activity: #" + i + "=" + w);
1357                 foundW = w;
1358                 foundI = i;
1359                 if (w == mWallpaperTarget && ((w.mAppToken != null
1360                         && w.mAppToken.animation != null)
1361                         || w.mAnimation != null)) {
1362                     // The current wallpaper target is animating, so we'll
1363                     // look behind it for another possible target and figure
1364                     // out what is going on below.
1365                     if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
1366                             + ": token animating, looking behind.");
1367                     continue;
1368                 }
1369                 break;
1370             }
1371         }
1372
1373         if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
1374             // If we are currently waiting for an app transition, and either
1375             // the current target or the next target are involved with it,
1376             // then hold off on doing anything with the wallpaper.
1377             // Note that we are checking here for just whether the target
1378             // is part of an app token...  which is potentially overly aggressive
1379             // (the app token may not be involved in the transition), but good
1380             // enough (we'll just wait until whatever transition is pending
1381             // executes).
1382             if (mWallpaperTarget != null && mWallpaperTarget.mAppToken != null) {
1383                 if (DEBUG_WALLPAPER) Slog.v(TAG,
1384                         "Wallpaper not changing: waiting for app anim in current target");
1385                 return 0;
1386             }
1387             if (foundW != null && foundW.mAppToken != null) {
1388                 if (DEBUG_WALLPAPER) Slog.v(TAG,
1389                         "Wallpaper not changing: waiting for app anim in found target");
1390                 return 0;
1391             }
1392         }
1393
1394         if (mWallpaperTarget != foundW) {
1395             if (DEBUG_WALLPAPER) {
1396                 Slog.v(TAG, "New wallpaper target: " + foundW
1397                         + " oldTarget: " + mWallpaperTarget);
1398             }
1399
1400             mLowerWallpaperTarget = null;
1401             mUpperWallpaperTarget = null;
1402
1403             WindowState oldW = mWallpaperTarget;
1404             mWallpaperTarget = foundW;
1405
1406             // Now what is happening...  if the current and new targets are
1407             // animating, then we are in our super special mode!
1408             if (foundW != null && oldW != null) {
1409                 boolean oldAnim = oldW.mAnimation != null
1410                         || (oldW.mAppToken != null && oldW.mAppToken.animation != null);
1411                 boolean foundAnim = foundW.mAnimation != null
1412                         || (foundW.mAppToken != null && foundW.mAppToken.animation != null);
1413                 if (DEBUG_WALLPAPER) {
1414                     Slog.v(TAG, "New animation: " + foundAnim
1415                             + " old animation: " + oldAnim);
1416                 }
1417                 if (foundAnim && oldAnim) {
1418                     int oldI = localmWindows.indexOf(oldW);
1419                     if (DEBUG_WALLPAPER) {
1420                         Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
1421                     }
1422                     if (oldI >= 0) {
1423                         if (DEBUG_WALLPAPER) {
1424                             Slog.v(TAG, "Animating wallpapers: old#" + oldI
1425                                     + "=" + oldW + "; new#" + foundI
1426                                     + "=" + foundW);
1427                         }
1428
1429                         // Set the new target correctly.
1430                         if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
1431                             if (DEBUG_WALLPAPER) {
1432                                 Slog.v(TAG, "Old wallpaper still the target.");
1433                             }
1434                             mWallpaperTarget = oldW;
1435                         }
1436
1437                         // Now set the upper and lower wallpaper targets
1438                         // correctly, and make sure that we are positioning
1439                         // the wallpaper below the lower.
1440                         if (foundI > oldI) {
1441                             // The new target is on top of the old one.
1442                             if (DEBUG_WALLPAPER) {
1443                                 Slog.v(TAG, "Found target above old target.");
1444                             }
1445                             mUpperWallpaperTarget = foundW;
1446                             mLowerWallpaperTarget = oldW;
1447                             foundW = oldW;
1448                             foundI = oldI;
1449                         } else {
1450                             // The new target is below the old one.
1451                             if (DEBUG_WALLPAPER) {
1452                                 Slog.v(TAG, "Found target below old target.");
1453                             }
1454                             mUpperWallpaperTarget = oldW;
1455                             mLowerWallpaperTarget = foundW;
1456                         }
1457                     }
1458                 }
1459             }
1460
1461         } else if (mLowerWallpaperTarget != null) {
1462             // Is it time to stop animating?
1463             boolean lowerAnimating = mLowerWallpaperTarget.mAnimation != null
1464                     || (mLowerWallpaperTarget.mAppToken != null
1465                             && mLowerWallpaperTarget.mAppToken.animation != null);
1466             boolean upperAnimating = mUpperWallpaperTarget.mAnimation != null
1467                     || (mUpperWallpaperTarget.mAppToken != null
1468                             && mUpperWallpaperTarget.mAppToken.animation != null);
1469             if (!lowerAnimating || !upperAnimating) {
1470                 if (DEBUG_WALLPAPER) {
1471                     Slog.v(TAG, "No longer animating wallpaper targets!");
1472                 }
1473                 mLowerWallpaperTarget = null;
1474                 mUpperWallpaperTarget = null;
1475             }
1476         }
1477
1478         boolean visible = foundW != null;
1479         if (visible) {
1480             // The window is visible to the compositor...  but is it visible
1481             // to the user?  That is what the wallpaper cares about.
1482             visible = isWallpaperVisible(foundW);
1483             if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
1484
1485             // If the wallpaper target is animating, we may need to copy
1486             // its layer adjustment.  Only do this if we are not transfering
1487             // between two wallpaper targets.
1488             mWallpaperAnimLayerAdjustment =
1489                     (mLowerWallpaperTarget == null && foundW.mAppToken != null)
1490                     ? foundW.mAppToken.animLayerAdjustment : 0;
1491
1492             final int maxLayer = mPolicy.getMaxWallpaperLayer()
1493                     * TYPE_LAYER_MULTIPLIER
1494                     + TYPE_LAYER_OFFSET;
1495
1496             // Now w is the window we are supposed to be behind...  but we
1497             // need to be sure to also be behind any of its attached windows,
1498             // AND any starting window associated with it, AND below the
1499             // maximum layer the policy allows for wallpapers.
1500             while (foundI > 0) {
1501                 WindowState wb = (WindowState)localmWindows.get(foundI-1);
1502                 if (wb.mBaseLayer < maxLayer &&
1503                         wb.mAttachedWindow != foundW &&
1504                         (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
1505                                 wb.mToken != foundW.mToken)) {
1506                     // This window is not related to the previous one in any
1507                     // interesting way, so stop here.
1508                     break;
1509                 }
1510                 foundW = wb;
1511                 foundI--;
1512             }
1513         } else {
1514             if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
1515         }
1516
1517         if (foundW == null && topCurW != null) {
1518             // There is no wallpaper target, so it goes at the bottom.
1519             // We will assume it is the same place as last time, if known.
1520             foundW = topCurW;
1521             foundI = topCurI+1;
1522         } else {
1523             // Okay i is the position immediately above the wallpaper.  Look at
1524             // what is below it for later.
1525             foundW = foundI > 0 ? (WindowState)localmWindows.get(foundI-1) : null;
1526         }
1527
1528         if (visible) {
1529             if (mWallpaperTarget.mWallpaperX >= 0) {
1530                 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
1531                 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
1532             }
1533             if (mWallpaperTarget.mWallpaperY >= 0) {
1534                 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
1535                 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
1536             }
1537         }
1538
1539         // Start stepping backwards from here, ensuring that our wallpaper windows
1540         // are correctly placed.
1541         int curTokenIndex = mWallpaperTokens.size();
1542         while (curTokenIndex > 0) {
1543             curTokenIndex--;
1544             WindowToken token = mWallpaperTokens.get(curTokenIndex);
1545             if (token.hidden == visible) {
1546                 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
1547                 token.hidden = !visible;
1548                 // Need to do a layout to ensure the wallpaper now has the
1549                 // correct size.
1550                 mLayoutNeeded = true;
1551             }
1552
1553             int curWallpaperIndex = token.windows.size();
1554             while (curWallpaperIndex > 0) {
1555                 curWallpaperIndex--;
1556                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1557
1558                 if (visible) {
1559                     updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
1560                 }
1561
1562                 // First, make sure the client has the current visibility
1563                 // state.
1564                 if (wallpaper.mWallpaperVisible != visible) {
1565                     wallpaper.mWallpaperVisible = visible;
1566                     try {
1567                         if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
1568                                 "Setting visibility of wallpaper " + wallpaper
1569                                 + ": " + visible);
1570                         wallpaper.mClient.dispatchAppVisibility(visible);
1571                     } catch (RemoteException e) {
1572                     }
1573                 }
1574
1575                 wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
1576                 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win "
1577                         + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
1578
1579                 // First, if this window is at the current index, then all
1580                 // is well.
1581                 if (wallpaper == foundW) {
1582                     foundI--;
1583                     foundW = foundI > 0
1584                             ? (WindowState)localmWindows.get(foundI-1) : null;
1585                     continue;
1586                 }
1587
1588                 // The window didn't match...  the current wallpaper window,
1589                 // wherever it is, is in the wrong place, so make sure it is
1590                 // not in the list.
1591                 int oldIndex = localmWindows.indexOf(wallpaper);
1592                 if (oldIndex >= 0) {
1593                     if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
1594                             + oldIndex + ": " + wallpaper);
1595                     localmWindows.remove(oldIndex);
1596                     if (oldIndex < foundI) {
1597                         foundI--;
1598                     }
1599                 }
1600
1601                 // Now stick it in.
1602                 if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
1603                         "Moving wallpaper " + wallpaper
1604                         + " from " + oldIndex + " to " + foundI);
1605
1606                 localmWindows.add(foundI, wallpaper);
1607                 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
1608             }
1609         }
1610
1611         return changed;
1612     }
1613
1614     void setWallpaperAnimLayerAdjustmentLocked(int adj) {
1615         if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
1616                 "Setting wallpaper layer adj to " + adj);
1617         mWallpaperAnimLayerAdjustment = adj;
1618         int curTokenIndex = mWallpaperTokens.size();
1619         while (curTokenIndex > 0) {
1620             curTokenIndex--;
1621             WindowToken token = mWallpaperTokens.get(curTokenIndex);
1622             int curWallpaperIndex = token.windows.size();
1623             while (curWallpaperIndex > 0) {
1624                 curWallpaperIndex--;
1625                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1626                 wallpaper.mAnimLayer = wallpaper.mLayer + adj;
1627                 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win "
1628                         + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
1629             }
1630         }
1631     }
1632
1633     boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
1634             boolean sync) {
1635         boolean changed = false;
1636         boolean rawChanged = false;
1637         float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
1638         float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
1639         int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
1640         int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
1641         changed = wallpaperWin.mXOffset != offset;
1642         if (changed) {
1643             if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
1644                     + wallpaperWin + " x: " + offset);
1645             wallpaperWin.mXOffset = offset;
1646         }
1647         if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
1648             wallpaperWin.mWallpaperX = wpx;
1649             wallpaperWin.mWallpaperXStep = wpxs;
1650             rawChanged = true;
1651         }
1652
1653         float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
1654         float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
1655         int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
1656         offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
1657         if (wallpaperWin.mYOffset != offset) {
1658             if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
1659                     + wallpaperWin + " y: " + offset);
1660             changed = true;
1661             wallpaperWin.mYOffset = offset;
1662         }
1663         if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
1664             wallpaperWin.mWallpaperY = wpy;
1665             wallpaperWin.mWallpaperYStep = wpys;
1666             rawChanged = true;
1667         }
1668
1669         if (rawChanged) {
1670             try {
1671                 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
1672                         + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
1673                         + " y=" + wallpaperWin.mWallpaperY);
1674                 if (sync) {
1675                     mWaitingOnWallpaper = wallpaperWin;
1676                 }
1677                 wallpaperWin.mClient.dispatchWallpaperOffsets(
1678                         wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
1679                         wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
1680                 if (sync) {
1681                     if (mWaitingOnWallpaper != null) {
1682                         long start = SystemClock.uptimeMillis();
1683                         if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
1684                                 < start) {
1685                             try {
1686                                 if (DEBUG_WALLPAPER) Slog.v(TAG,
1687                                         "Waiting for offset complete...");
1688                                 mWindowMap.wait(WALLPAPER_TIMEOUT);
1689                             } catch (InterruptedException e) {
1690                             }
1691                             if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
1692                             if ((start+WALLPAPER_TIMEOUT)
1693                                     < SystemClock.uptimeMillis()) {
1694                                 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
1695                                         + wallpaperWin);
1696                                 mLastWallpaperTimeoutTime = start;
1697                             }
1698                         }
1699                         mWaitingOnWallpaper = null;
1700                     }
1701                 }
1702             } catch (RemoteException e) {
1703             }
1704         }
1705
1706         return changed;
1707     }
1708
1709     void wallpaperOffsetsComplete(IBinder window) {
1710         synchronized (mWindowMap) {
1711             if (mWaitingOnWallpaper != null &&
1712                     mWaitingOnWallpaper.mClient.asBinder() == window) {
1713                 mWaitingOnWallpaper = null;
1714                 mWindowMap.notifyAll();
1715             }
1716         }
1717     }
1718
1719     boolean updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
1720         final int dw = mDisplay.getWidth();
1721         final int dh = mDisplay.getHeight();
1722
1723         boolean changed = false;
1724
1725         WindowState target = mWallpaperTarget;
1726         if (target != null) {
1727             if (target.mWallpaperX >= 0) {
1728                 mLastWallpaperX = target.mWallpaperX;
1729             } else if (changingTarget.mWallpaperX >= 0) {
1730                 mLastWallpaperX = changingTarget.mWallpaperX;
1731             }
1732             if (target.mWallpaperY >= 0) {
1733                 mLastWallpaperY = target.mWallpaperY;
1734             } else if (changingTarget.mWallpaperY >= 0) {
1735                 mLastWallpaperY = changingTarget.mWallpaperY;
1736             }
1737         }
1738
1739         int curTokenIndex = mWallpaperTokens.size();
1740         while (curTokenIndex > 0) {
1741             curTokenIndex--;
1742             WindowToken token = mWallpaperTokens.get(curTokenIndex);
1743             int curWallpaperIndex = token.windows.size();
1744             while (curWallpaperIndex > 0) {
1745                 curWallpaperIndex--;
1746                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1747                 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
1748                     wallpaper.computeShownFrameLocked();
1749                     changed = true;
1750                     // We only want to be synchronous with one wallpaper.
1751                     sync = false;
1752                 }
1753             }
1754         }
1755
1756         return changed;
1757     }
1758
1759     void updateWallpaperVisibilityLocked() {
1760         final boolean visible = isWallpaperVisible(mWallpaperTarget);
1761         final int dw = mDisplay.getWidth();
1762         final int dh = mDisplay.getHeight();
1763
1764         int curTokenIndex = mWallpaperTokens.size();
1765         while (curTokenIndex > 0) {
1766             curTokenIndex--;
1767             WindowToken token = mWallpaperTokens.get(curTokenIndex);
1768             if (token.hidden == visible) {
1769                 token.hidden = !visible;
1770                 // Need to do a layout to ensure the wallpaper now has the
1771                 // correct size.
1772                 mLayoutNeeded = true;
1773             }
1774
1775             int curWallpaperIndex = token.windows.size();
1776             while (curWallpaperIndex > 0) {
1777                 curWallpaperIndex--;
1778                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1779                 if (visible) {
1780                     updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
1781                 }
1782
1783                 if (wallpaper.mWallpaperVisible != visible) {
1784                     wallpaper.mWallpaperVisible = visible;
1785                     try {
1786                         if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
1787                                 "Updating visibility of wallpaper " + wallpaper
1788                                 + ": " + visible);
1789                         wallpaper.mClient.dispatchAppVisibility(visible);
1790                     } catch (RemoteException e) {
1791                     }
1792                 }
1793             }
1794         }
1795     }
1796
1797     void sendPointerToWallpaperLocked(WindowState srcWin,
1798             MotionEvent pointer, long eventTime) {
1799         int curTokenIndex = mWallpaperTokens.size();
1800         while (curTokenIndex > 0) {
1801             curTokenIndex--;
1802             WindowToken token = mWallpaperTokens.get(curTokenIndex);
1803             int curWallpaperIndex = token.windows.size();
1804             while (curWallpaperIndex > 0) {
1805                 curWallpaperIndex--;
1806                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1807                 if ((wallpaper.mAttrs.flags &
1808                         WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
1809                     continue;
1810                 }
1811                 try {
1812                     MotionEvent ev = MotionEvent.obtainNoHistory(pointer);
1813                     if (srcWin != null) {
1814                         ev.offsetLocation(srcWin.mFrame.left-wallpaper.mFrame.left,
1815                                 srcWin.mFrame.top-wallpaper.mFrame.top);
1816                     } else {
1817                         ev.offsetLocation(-wallpaper.mFrame.left, -wallpaper.mFrame.top);
1818                     }
1819                     switch (pointer.getAction()) {
1820                         case MotionEvent.ACTION_DOWN:
1821                             mSendingPointersToWallpaper = true;
1822                             break;
1823                         case MotionEvent.ACTION_UP:
1824                             mSendingPointersToWallpaper = false;
1825                             break;
1826                     }
1827                     wallpaper.mClient.dispatchPointer(ev, eventTime, false);
1828                 } catch (RemoteException e) {
1829                     Slog.w(TAG, "Failure sending pointer to wallpaper", e);
1830                 }
1831             }
1832         }
1833     }
1834
1835     void dispatchPointerElsewhereLocked(WindowState srcWin, WindowState relWin,
1836             MotionEvent pointer, long eventTime, boolean skipped) {
1837         if (relWin != null) {
1838             mPolicy.dispatchedPointerEventLw(pointer, relWin.mFrame.left, relWin.mFrame.top);
1839         } else {
1840             mPolicy.dispatchedPointerEventLw(pointer, 0, 0);
1841         }
1842         
1843         // If we sent an initial down to the wallpaper, then continue
1844         // sending events until the final up.
1845         if (mSendingPointersToWallpaper) {
1846             if (skipped) {
1847                 Slog.i(TAG, "Sending skipped pointer to wallpaper!");
1848             }
1849             sendPointerToWallpaperLocked(relWin, pointer, eventTime);
1850             
1851         // If we are on top of the wallpaper, then the wallpaper also
1852         // gets to see this movement.
1853         } else if (srcWin != null
1854                 && pointer.getAction() == MotionEvent.ACTION_DOWN
1855                 && mWallpaperTarget == srcWin
1856                 && srcWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
1857             sendPointerToWallpaperLocked(relWin, pointer, eventTime);
1858         }
1859     }
1860     
1861     public int addWindow(Session session, IWindow client,
1862             WindowManager.LayoutParams attrs, int viewVisibility,
1863             Rect outContentInsets) {
1864         int res = mPolicy.checkAddPermission(attrs);
1865         if (res != WindowManagerImpl.ADD_OKAY) {
1866             return res;
1867         }
1868
1869         boolean reportNewConfig = false;
1870         WindowState attachedWindow = null;
1871         WindowState win = null;
1872
1873         synchronized(mWindowMap) {
1874             // Instantiating a Display requires talking with the simulator,
1875             // so don't do it until we know the system is mostly up and
1876             // running.
1877             if (mDisplay == null) {
1878                 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1879                 mDisplay = wm.getDefaultDisplay();
1880                 mInitialDisplayWidth = mDisplay.getWidth();
1881                 mInitialDisplayHeight = mDisplay.getHeight();
1882                 mQueue.setDisplay(mDisplay);
1883                 reportNewConfig = true;
1884             }
1885
1886             if (mWindowMap.containsKey(client.asBinder())) {
1887                 Slog.w(TAG, "Window " + client + " is already added");
1888                 return WindowManagerImpl.ADD_DUPLICATE_ADD;
1889             }
1890
1891             if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
1892                 attachedWindow = windowForClientLocked(null, attrs.token, false);
1893                 if (attachedWindow == null) {
1894                     Slog.w(TAG, "Attempted to add window with token that is not a window: "
1895                           + attrs.token + ".  Aborting.");
1896                     return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1897                 }
1898                 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
1899                         && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
1900                     Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
1901                             + attrs.token + ".  Aborting.");
1902                     return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1903                 }
1904             }
1905
1906             boolean addToken = false;
1907             WindowToken token = mTokenMap.get(attrs.token);
1908             if (token == null) {
1909                 if (attrs.type >= FIRST_APPLICATION_WINDOW
1910                         && attrs.type <= LAST_APPLICATION_WINDOW) {
1911                     Slog.w(TAG, "Attempted to add application window with unknown token "
1912                           + attrs.token + ".  Aborting.");
1913                     return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1914                 }
1915                 if (attrs.type == TYPE_INPUT_METHOD) {
1916                     Slog.w(TAG, "Attempted to add input method window with unknown token "
1917                           + attrs.token + ".  Aborting.");
1918                     return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1919                 }
1920                 if (attrs.type == TYPE_WALLPAPER) {
1921                     Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
1922                           + attrs.token + ".  Aborting.");
1923                     return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1924                 }
1925                 token = new WindowToken(attrs.token, -1, false);
1926                 addToken = true;
1927             } else if (attrs.type >= FIRST_APPLICATION_WINDOW
1928                     && attrs.type <= LAST_APPLICATION_WINDOW) {
1929                 AppWindowToken atoken = token.appWindowToken;
1930                 if (atoken == null) {
1931                     Slog.w(TAG, "Attempted to add window with non-application token "
1932                           + token + ".  Aborting.");
1933                     return WindowManagerImpl.ADD_NOT_APP_TOKEN;
1934                 } else if (atoken.removed) {
1935                     Slog.w(TAG, "Attempted to add window with exiting application token "
1936                           + token + ".  Aborting.");
1937                     return WindowManagerImpl.ADD_APP_EXITING;
1938                 }
1939                 if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
1940                     // No need for this guy!
1941                     if (localLOGV) Slog.v(
1942                             TAG, "**** NO NEED TO START: " + attrs.getTitle());
1943                     return WindowManagerImpl.ADD_STARTING_NOT_NEEDED;
1944                 }
1945             } else if (attrs.type == TYPE_INPUT_METHOD) {
1946                 if (token.windowType != TYPE_INPUT_METHOD) {
1947                     Slog.w(TAG, "Attempted to add input method window with bad token "
1948                             + attrs.token + ".  Aborting.");
1949                       return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1950                 }
1951             } else if (attrs.type == TYPE_WALLPAPER) {
1952                 if (token.windowType != TYPE_WALLPAPER) {
1953                     Slog.w(TAG, "Attempted to add wallpaper window with bad token "
1954                             + attrs.token + ".  Aborting.");
1955                       return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1956                 }
1957             }
1958
1959             win = new WindowState(session, client, token,
1960                     attachedWindow, attrs, viewVisibility);
1961             if (win.mDeathRecipient == null) {
1962                 // Client has apparently died, so there is no reason to
1963                 // continue.
1964                 Slog.w(TAG, "Adding window client " + client.asBinder()
1965                         + " that is dead, aborting.");
1966                 return WindowManagerImpl.ADD_APP_EXITING;
1967             }
1968
1969             mPolicy.adjustWindowParamsLw(win.mAttrs);
1970
1971             res = mPolicy.prepareAddWindowLw(win, attrs);
1972             if (res != WindowManagerImpl.ADD_OKAY) {
1973                 return res;
1974             }
1975
1976             // From now on, no exceptions or errors allowed!
1977
1978             res = WindowManagerImpl.ADD_OKAY;
1979
1980             final long origId = Binder.clearCallingIdentity();
1981
1982             if (addToken) {
1983                 mTokenMap.put(attrs.token, token);
1984                 mTokenList.add(token);
1985             }
1986             win.attach();
1987             mWindowMap.put(client.asBinder(), win);
1988
1989             if (attrs.type == TYPE_APPLICATION_STARTING &&
1990                     token.appWindowToken != null) {
1991                 token.appWindowToken.startingWindow = win;
1992             }
1993
1994             boolean imMayMove = true;
1995
1996             if (attrs.type == TYPE_INPUT_METHOD) {
1997                 mInputMethodWindow = win;
1998                 addInputMethodWindowToListLocked(win);
1999                 imMayMove = false;
2000             } else if (attrs.type == TYPE_INPUT_METHOD_DIALOG) {
2001                 mInputMethodDialogs.add(win);
2002                 addWindowToListInOrderLocked(win, true);
2003                 adjustInputMethodDialogsLocked();
2004                 imMayMove = false;
2005             } else {
2006                 addWindowToListInOrderLocked(win, true);
2007                 if (attrs.type == TYPE_WALLPAPER) {
2008                     mLastWallpaperTimeoutTime = 0;
2009                     adjustWallpaperWindowsLocked();
2010                 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2011                     adjustWallpaperWindowsLocked();
2012                 }
2013             }
2014
2015             win.mEnterAnimationPending = true;
2016
2017             mPolicy.getContentInsetHintLw(attrs, outContentInsets);
2018
2019             if (mInTouchMode) {
2020                 res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
2021             }
2022             if (win == null || win.mAppToken == null || !win.mAppToken.clientHidden) {
2023                 res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
2024             }
2025
2026             boolean focusChanged = false;
2027             if (win.canReceiveKeys()) {
2028                 if ((focusChanged=updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS))
2029                         == true) {
2030                     imMayMove = false;
2031                 }
2032             }
2033
2034             if (imMayMove) {
2035                 moveInputMethodWindowsIfNeededLocked(false);
2036             }
2037
2038             assignLayersLocked();
2039             // Don't do layout here, the window must call
2040             // relayout to be displayed, so we'll do it there.
2041
2042             //dump();
2043
2044             if (focusChanged) {
2045                 if (mCurrentFocus != null) {
2046                     mKeyWaiter.handleNewWindowLocked(mCurrentFocus);
2047                 }
2048             }
2049             if (localLOGV) Slog.v(
2050                 TAG, "New client " + client.asBinder()
2051                 + ": window=" + win);
2052             
2053             if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked()) {
2054                 reportNewConfig = true;
2055             }
2056         }
2057
2058         // sendNewConfiguration() checks caller permissions so we must call it with
2059         // privilege.  updateOrientationFromAppTokens() clears and resets the caller
2060         // identity anyway, so it's safe to just clear & restore around this whole
2061         // block.
2062         final long origId = Binder.clearCallingIdentity();
2063         if (reportNewConfig) {
2064             sendNewConfiguration();
2065         }
2066         Binder.restoreCallingIdentity(origId);
2067
2068         return res;
2069     }
2070
2071     public void removeWindow(Session session, IWindow client) {
2072         synchronized(mWindowMap) {
2073             WindowState win = windowForClientLocked(session, client, false);
2074             if (win == null) {
2075                 return;
2076             }
2077             removeWindowLocked(session, win);
2078         }
2079     }
2080
2081     public void removeWindowLocked(Session session, WindowState win) {
2082
2083         if (localLOGV || DEBUG_FOCUS) Slog.v(
2084             TAG, "Remove " + win + " client="
2085             + Integer.toHexString(System.identityHashCode(
2086                 win.mClient.asBinder()))
2087             + ", surface=" + win.mSurface);
2088
2089         final long origId = Binder.clearCallingIdentity();
2090
2091         if (DEBUG_APP_TRANSITIONS) Slog.v(
2092                 TAG, "Remove " + win + ": mSurface=" + win.mSurface
2093                 + " mExiting=" + win.mExiting
2094                 + " isAnimating=" + win.isAnimating()
2095                 + " app-animation="
2096                 + (win.mAppToken != null ? win.mAppToken.animation : null)
2097                 + " inPendingTransaction="
2098                 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
2099                 + " mDisplayFrozen=" + mDisplayFrozen);
2100         // Visibility of the removed window. Will be used later to update orientation later on.
2101         boolean wasVisible = false;
2102         // First, see if we need to run an animation.  If we do, we have
2103         // to hold off on removing the window until the animation is done.
2104         // If the display is frozen, just remove immediately, since the
2105         // animation wouldn't be seen.
2106         if (win.mSurface != null && !mDisplayFrozen && mPolicy.isScreenOn()) {
2107             // If we are not currently running the exit animation, we
2108             // need to see about starting one.
2109             if (wasVisible=win.isWinVisibleLw()) {
2110
2111                 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2112                 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2113                     transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2114                 }
2115                 // Try starting an animation.
2116                 if (applyAnimationLocked(win, transit, false)) {
2117                     win.mExiting = true;
2118                 }
2119             }
2120             if (win.mExiting || win.isAnimating()) {
2121                 // The exit animation is running... wait for it!
2122                 //Slog.i(TAG, "*** Running exit animation...");
2123                 win.mExiting = true;
2124                 win.mRemoveOnExit = true;
2125                 mLayoutNeeded = true;
2126                 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
2127                 performLayoutAndPlaceSurfacesLocked();
2128                 if (win.mAppToken != null) {
2129                     win.mAppToken.updateReportedVisibilityLocked();
2130                 }
2131                 //dump();
2132                 Binder.restoreCallingIdentity(origId);
2133                 return;
2134             }
2135         }
2136
2137         removeWindowInnerLocked(session, win);
2138         // Removing a visible window will effect the computed orientation
2139         // So just update orientation if needed.
2140         if (wasVisible && computeForcedAppOrientationLocked()
2141                 != mForcedAppOrientation
2142                 && updateOrientationFromAppTokensLocked()) {
2143             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
2144         }
2145         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2146         Binder.restoreCallingIdentity(origId);
2147     }
2148
2149     private void removeWindowInnerLocked(Session session, WindowState win) {
2150         mKeyWaiter.finishedKey(session, win.mClient, true,
2151                 KeyWaiter.RETURN_NOTHING);
2152         mKeyWaiter.releasePendingPointerLocked(win.mSession);
2153         mKeyWaiter.releasePendingTrackballLocked(win.mSession);
2154
2155         win.mRemoved = true;
2156
2157         if (mInputMethodTarget == win) {
2158             moveInputMethodWindowsIfNeededLocked(false);
2159         }
2160
2161         if (false) {
2162             RuntimeException e = new RuntimeException("here");
2163             e.fillInStackTrace();
2164             Slog.w(TAG, "Removing window " + win, e);
2165         }
2166
2167         mPolicy.removeWindowLw(win);
2168         win.removeLocked();
2169
2170         mWindowMap.remove(win.mClient.asBinder());
2171         mWindows.remove(win);
2172         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
2173
2174         if (mInputMethodWindow == win) {
2175             mInputMethodWindow = null;
2176         } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2177             mInputMethodDialogs.remove(win);
2178         }
2179
2180         final WindowToken token = win.mToken;
2181         final AppWindowToken atoken = win.mAppToken;
2182         token.windows.remove(win);
2183         if (atoken != null) {
2184             atoken.allAppWindows.remove(win);
2185         }
2186         if (localLOGV) Slog.v(
2187                 TAG, "**** Removing window " + win + ": count="
2188                 + token.windows.size());
2189         if (token.windows.size() == 0) {
2190             if (!token.explicit) {
2191                 mTokenMap.remove(token.token);
2192                 mTokenList.remove(token);
2193             } else if (atoken != null) {
2194                 atoken.firstWindowDrawn = false;
2195             }
2196         }
2197
2198         if (atoken != null) {
2199             if (atoken.startingWindow == win) {
2200                 atoken.startingWindow = null;
2201             } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2202                 // If this is the last window and we had requested a starting
2203                 // transition window, well there is no point now.
2204                 atoken.startingData = null;
2205             } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2206                 // If this is the last window except for a starting transition
2207                 // window, we need to get rid of the starting transition.
2208                 if (DEBUG_STARTING_WINDOW) {
2209                     Slog.v(TAG, "Schedule remove starting " + token
2210                             + ": no more real windows");
2211                 }
2212                 Message m = mH.obtainMessage(H.REMOVE_STARTING, atoken);
2213                 mH.sendMessage(m);
2214             }
2215         }
2216
2217         if (win.mAttrs.type == TYPE_WALLPAPER) {
2218             mLastWallpaperTimeoutTime = 0;
2219             adjustWallpaperWindowsLocked();
2220         } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2221             adjustWallpaperWindowsLocked();
2222         }
2223
2224         if (!mInLayout) {
2225             assignLayersLocked();
2226             mLayoutNeeded = true;
2227             performLayoutAndPlaceSurfacesLocked();
2228             if (win.mAppToken != null) {
2229                 win.mAppToken.updateReportedVisibilityLocked();
2230             }
2231         }
2232     }
2233
2234     private static void logSurface(WindowState w, String msg, RuntimeException where) {
2235         String str = "  SURFACE " + Integer.toHexString(w.hashCode())
2236                 + ": " + msg + " / " + w.mAttrs.getTitle();
2237         if (where != null) {
2238             Slog.i(TAG, str, where);
2239         } else {
2240             Slog.i(TAG, str);
2241         }
2242     }
2243     
2244     private void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2245         long origId = Binder.clearCallingIdentity();
2246         try {
2247             synchronized (mWindowMap) {
2248                 WindowState w = windowForClientLocked(session, client, false);
2249                 if ((w != null) && (w.mSurface != null)) {
2250                     if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
2251                     Surface.openTransaction();
2252                     try {
2253                         if (SHOW_TRANSACTIONS) logSurface(w,
2254                                 "transparentRegionHint=" + region, null);
2255                         w.mSurface.setTransparentRegionHint(region);
2256                     } finally {
2257                         if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
2258                         Surface.closeTransaction();
2259                     }
2260                 }
2261             }
2262         } finally {
2263             Binder.restoreCallingIdentity(origId);
2264         }
2265     }
2266
2267     void setInsetsWindow(Session session, IWindow client,
2268             int touchableInsets, Rect contentInsets,
2269             Rect visibleInsets) {
2270         long origId = Binder.clearCallingIdentity();
2271         try {
2272             synchronized (mWindowMap) {
2273                 WindowState w = windowForClientLocked(session, client, false);
2274                 if (w != null) {
2275                     w.mGivenInsetsPending = false;
2276                     w.mGivenContentInsets.set(contentInsets);
2277                     w.mGivenVisibleInsets.set(visibleInsets);
2278                     w.mTouchableInsets = touchableInsets;
2279                     mLayoutNeeded = true;
2280                     performLayoutAndPlaceSurfacesLocked();
2281                 }
2282             }
2283         } finally {
2284             Binder.restoreCallingIdentity(origId);
2285         }
2286     }
2287
2288     public void getWindowDisplayFrame(Session session, IWindow client,
2289             Rect outDisplayFrame) {
2290         synchronized(mWindowMap) {
2291             WindowState win = windowForClientLocked(session, client, false);
2292             if (win == null) {
2293                 outDisplayFrame.setEmpty();
2294                 return;
2295             }
2296             outDisplayFrame.set(win.mDisplayFrame);
2297         }
2298     }
2299
2300     public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
2301             float xStep, float yStep) {
2302         if (window.mWallpaperX != x || window.mWallpaperY != y)  {
2303             window.mWallpaperX = x;
2304             window.mWallpaperY = y;
2305             window.mWallpaperXStep = xStep;
2306             window.mWallpaperYStep = yStep;
2307             if (updateWallpaperOffsetLocked(window, true)) {
2308                 performLayoutAndPlaceSurfacesLocked();
2309             }
2310         }
2311     }
2312
2313     void wallpaperCommandComplete(IBinder window, Bundle result) {
2314         synchronized (mWindowMap) {
2315             if (mWaitingOnWallpaper != null &&
2316                     mWaitingOnWallpaper.mClient.asBinder() == window) {
2317                 mWaitingOnWallpaper = null;
2318                 mWindowMap.notifyAll();
2319             }
2320         }
2321     }
2322
2323     public Bundle sendWindowWallpaperCommandLocked(WindowState window,
2324             String action, int x, int y, int z, Bundle extras, boolean sync) {
2325         if (window == mWallpaperTarget || window == mLowerWallpaperTarget
2326                 || window == mUpperWallpaperTarget) {
2327             boolean doWait = sync;
2328             int curTokenIndex = mWallpaperTokens.size();
2329             while (curTokenIndex > 0) {
2330                 curTokenIndex--;
2331                 WindowToken token = mWallpaperTokens.get(curTokenIndex);
2332                 int curWallpaperIndex = token.windows.size();
2333                 while (curWallpaperIndex > 0) {
2334                     curWallpaperIndex--;
2335                     WindowState wallpaper = token.windows.get(curWallpaperIndex);
2336                     try {
2337                         wallpaper.mClient.dispatchWallpaperCommand(action,
2338                                 x, y, z, extras, sync);
2339                         // We only want to be synchronous with one wallpaper.
2340                         sync = false;
2341                     } catch (RemoteException e) {
2342                     }
2343                 }
2344             }
2345
2346             if (doWait) {
2347                 // XXX Need to wait for result.
2348             }
2349         }
2350
2351         return null;
2352     }
2353
2354     public int relayoutWindow(Session session, IWindow client,
2355             WindowManager.LayoutParams attrs, int requestedWidth,
2356             int requestedHeight, int viewVisibility, boolean insetsPending,
2357             Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
2358             Configuration outConfig, Surface outSurface) {
2359         boolean displayed = false;
2360         boolean inTouchMode;
2361         boolean configChanged;
2362         long origId = Binder.clearCallingIdentity();
2363
2364         synchronized(mWindowMap) {
2365             WindowState win = windowForClientLocked(session, client, false);
2366             if (win == null) {
2367                 return 0;
2368             }
2369             win.mRequestedWidth = requestedWidth;
2370             win.mRequestedHeight = requestedHeight;
2371
2372             if (attrs != null) {
2373                 mPolicy.adjustWindowParamsLw(attrs);
2374             }
2375
2376             int attrChanges = 0;
2377             int flagChanges = 0;
2378             if (attrs != null) {
2379                 flagChanges = win.mAttrs.flags ^= attrs.flags;
2380                 attrChanges = win.mAttrs.copyFrom(attrs);
2381             }
2382
2383             if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": " + win.mAttrs);
2384
2385             if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2386                 win.mAlpha = attrs.alpha;
2387             }
2388
2389             final boolean scaledWindow =
2390                 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
2391
2392             if (scaledWindow) {
2393                 // requested{Width|Height} Surface's physical size
2394                 // attrs.{width|height} Size on screen
2395                 win.mHScale = (attrs.width  != requestedWidth)  ?
2396                         (attrs.width  / (float)requestedWidth) : 1.0f;
2397                 win.mVScale = (attrs.height != requestedHeight) ?
2398                         (attrs.height / (float)requestedHeight) : 1.0f;
2399             } else {
2400                 win.mHScale = win.mVScale = 1;
2401             }
2402
2403             boolean imMayMove = (flagChanges&(
2404                     WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
2405                     WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)) != 0;
2406
2407             boolean focusMayChange = win.mViewVisibility != viewVisibility
2408                     || ((flagChanges&WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0)
2409                     || (!win.mRelayoutCalled);
2410
2411             boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2412                     && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
2413
2414             win.mRelayoutCalled = true;
2415             final int oldVisibility = win.mViewVisibility;
2416             win.mViewVisibility = viewVisibility;
2417             if (viewVisibility == View.VISIBLE &&
2418                     (win.mAppToken == null || !win.mAppToken.clientHidden)) {
2419                 displayed = !win.isVisibleLw();
2420                 if (win.mExiting) {
2421                     win.mExiting = false;
2422                     win.mAnimation = null;
2423                 }
2424                 if (win.mDestroying) {
2425                     win.mDestroying = false;
2426                     mDestroySurface.remove(win);
2427                 }
2428                 if (oldVisibility == View.GONE) {
2429                     win.mEnterAnimationPending = true;
2430                 }
2431                 if (displayed) {
2432                     if (win.mSurface != null && !win.mDrawPending
2433                             && !win.mCommitDrawPending && !mDisplayFrozen
2434                             && mPolicy.isScreenOn()) {
2435                         applyEnterAnimationLocked(win);
2436                     }
2437                     if ((win.mAttrs.flags
2438                             & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
2439                         if (DEBUG_VISIBILITY) Slog.v(TAG,
2440                                 "Relayout window turning screen on: " + win);
2441                         win.mTurnOnScreen = true;
2442                     }
2443                     int diff = 0;
2444                     if (win.mConfiguration != mCurConfiguration
2445                             && (win.mConfiguration == null
2446                                     || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0)) {
2447                         win.mConfiguration = mCurConfiguration;
2448                         if (DEBUG_CONFIGURATION) {
2449                             Slog.i(TAG, "Window " + win + " visible with new config: "
2450                                     + win.mConfiguration + " / 0x"
2451                                     + Integer.toHexString(diff));
2452                         }
2453                         outConfig.setTo(mCurConfiguration);
2454                     }
2455                 }
2456                 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
2457                     // To change the format, we need to re-build the surface.
2458                     win.destroySurfaceLocked();
2459                     displayed = true;
2460                 }
2461                 try {
2462                     Surface surface = win.createSurfaceLocked();
2463                     if (surface != null) {
2464                         outSurface.copyFrom(surface);
2465                         win.mReportDestroySurface = false;
2466                         win.mSurfacePendingDestroy = false;
2467                         if (SHOW_TRANSACTIONS) Slog.i(TAG,
2468                                 "  OUT SURFACE " + outSurface + ": copied");
2469                     } else {
2470                         // For some reason there isn't a surface.  Clear the
2471                         // caller's object so they see the same state.
2472                         outSurface.release();
2473                     }
2474                 } catch (Exception e) {
2475                     Slog.w(TAG, "Exception thrown when creating surface for client "
2476                              + client + " (" + win.mAttrs.getTitle() + ")",
2477                              e);
2478                     Binder.restoreCallingIdentity(origId);
2479                     return 0;
2480                 }
2481                 if (displayed) {
2482                     focusMayChange = true;
2483                 }
2484                 if (win.mAttrs.type == TYPE_INPUT_METHOD
2485                         && mInputMethodWindow == null) {
2486                     mInputMethodWindow = win;
2487                     imMayMove = true;
2488                 }
2489                 if (win.mAttrs.type == TYPE_BASE_APPLICATION
2490                         && win.mAppToken != null
2491                         && win.mAppToken.startingWindow != null) {
2492                     // Special handling of starting window over the base
2493                     // window of the app: propagate lock screen flags to it,
2494                     // to provide the correct semantics while starting.
2495                     final int mask =
2496                         WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
2497                         | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
2498                         | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
2499                     WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
2500                     sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
2501                 }
2502             } else {
2503                 win.mEnterAnimationPending = false;
2504                 if (win.mSurface != null) {
2505                     if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
2506                             + ": mExiting=" + win.mExiting
2507                             + " mSurfacePendingDestroy=" + win.mSurfacePendingDestroy);
2508                     // If we are not currently running the exit animation, we
2509                     // need to see about starting one.
2510                     if (!win.mExiting || win.mSurfacePendingDestroy) {
2511                         // Try starting an animation; if there isn't one, we
2512                         // can destroy the surface right away.
2513                         int transit = WindowManagerPolicy.TRANSIT_EXIT;
2514                         if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2515                             transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2516                         }
2517                         if (!win.mSurfacePendingDestroy && win.isWinVisibleLw() &&
2518                               applyAnimationLocked(win, transit, false)) {
2519                             focusMayChange = true;
2520                             win.mExiting = true;
2521                             mKeyWaiter.finishedKey(session, client, true,
2522                                     KeyWaiter.RETURN_NOTHING);
2523                         } else if (win.isAnimating()) {
2524                             // Currently in a hide animation... turn this into
2525                             // an exit.
2526                             win.mExiting = true;
2527                         } else if (win == mWallpaperTarget) {
2528                             // If the wallpaper is currently behind this
2529                             // window, we need to change both of them inside
2530                             // of a transaction to avoid artifacts.
2531                             win.mExiting = true;
2532                             win.mAnimating = true;
2533                         } else {
2534                             if (mInputMethodWindow == win) {
2535                                 mInputMethodWindow = null;
2536                             }
2537                             win.destroySurfaceLocked();
2538                         }
2539                     }
2540                 }
2541
2542                 if (win.mSurface == null || (win.getAttrs().flags
2543                         & WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING) == 0
2544                         || win.mSurfacePendingDestroy) {
2545                     // We are being called from a local process, which
2546                     // means outSurface holds its current surface.  Ensure the
2547                     // surface object is cleared, but we don't want it actually
2548                     // destroyed at this point.
2549                     win.mSurfacePendingDestroy = false;
2550                     outSurface.release();
2551                     if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
2552                 } else if (win.mSurface != null) {
2553                     if (DEBUG_VISIBILITY) Slog.i(TAG,
2554                             "Keeping surface, will report destroy: " + win);
2555                     win.mReportDestroySurface = true;
2556                     outSurface.copyFrom(win.mSurface);
2557                 }
2558             }
2559
2560             if (focusMayChange) {
2561                 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2562                 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
2563                     imMayMove = false;
2564                 }
2565                 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2566             }
2567
2568             // updateFocusedWindowLocked() already assigned layers so we only need to
2569             // reassign them at this point if the IM window state gets shuffled
2570             boolean assignLayers = false;
2571
2572             if (imMayMove) {
2573                 if (moveInputMethodWindowsIfNeededLocked(false) || displayed) {
2574                     // Little hack here -- we -should- be able to rely on the
2575                     // function to return true if the IME has moved and needs
2576                     // its layer recomputed.  However, if the IME was hidden
2577                     // and isn't actually moved in the list, its layer may be
2578                     // out of data so we make sure to recompute it.
2579                     assignLayers = true;
2580                 }
2581             }
2582             if (wallpaperMayMove) {
2583                 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
2584                     assignLayers = true;
2585                 }
2586             }
2587
2588             mLayoutNeeded = true;
2589             win.mGivenInsetsPending = insetsPending;
2590             if (assignLayers) {
2591                 assignLayersLocked();
2592             }
2593             configChanged = updateOrientationFromAppTokensLocked();
2594             performLayoutAndPlaceSurfacesLocked();
2595             if (displayed && win.mIsWallpaper) {
2596                 updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
2597                         mDisplay.getHeight(), false);
2598             }
2599             if (win.mAppToken != null) {
2600                 win.mAppToken.updateReportedVisibilityLocked();
2601             }
2602             outFrame.set(win.mFrame);
2603             outContentInsets.set(win.mContentInsets);
2604             outVisibleInsets.set(win.mVisibleInsets);
2605             if (localLOGV) Slog.v(
2606                 TAG, "Relayout given client " + client.asBinder()
2607                 + ", requestedWidth=" + requestedWidth
2608                 + ", requestedHeight=" + requestedHeight
2609                 + ", viewVisibility=" + viewVisibility
2610                 + "\nRelayout returning frame=" + outFrame
2611                 + ", surface=" + outSurface);
2612
2613             if (localLOGV || DEBUG_FOCUS) Slog.v(
2614                 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
2615
2616             inTouchMode = mInTouchMode;
2617         }
2618
2619         if (configChanged) {
2620             sendNewConfiguration();
2621         }
2622
2623         Binder.restoreCallingIdentity(origId);
2624
2625         return (inTouchMode ? WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE : 0)
2626                 | (displayed ? WindowManagerImpl.RELAYOUT_FIRST_TIME : 0);
2627     }
2628
2629     public void finishDrawingWindow(Session session, IWindow client) {
2630         final long origId = Binder.clearCallingIdentity();
2631         synchronized(mWindowMap) {
2632             WindowState win = windowForClientLocked(session, client, false);
2633             if (win != null && win.finishDrawingLocked()) {
2634                 if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2635                     adjustWallpaperWindowsLocked();
2636                 }
2637                 mLayoutNeeded = true;
2638                 performLayoutAndPlaceSurfacesLocked();
2639             }
2640         }
2641         Binder.restoreCallingIdentity(origId);
2642     }
2643
2644     private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
2645         if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: params package="
2646                 + (lp != null ? lp.packageName : null)
2647                 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
2648         if (lp != null && lp.windowAnimations != 0) {
2649             // If this is a system resource, don't try to load it from the
2650             // application resources.  It is nice to avoid loading application
2651             // resources if we can.
2652             String packageName = lp.packageName != null ? lp.packageName : "android";
2653             int resId = lp.windowAnimations;
2654             if ((resId&0xFF000000) == 0x01000000) {
2655                 packageName = "android";
2656             }
2657             if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
2658                     + packageName);
2659             return AttributeCache.instance().get(packageName, resId,
2660                     com.android.internal.R.styleable.WindowAnimation);
2661         }
2662         return null;
2663     }
2664
2665     private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
2666         if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: params package="
2667                 + packageName + " resId=0x" + Integer.toHexString(resId));
2668         if (packageName != null) {
2669             if ((resId&0xFF000000) == 0x01000000) {
2670                 packageName = "android";
2671             }
2672             if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
2673                     + packageName);
2674             return AttributeCache.instance().get(packageName, resId,
2675                     com.android.internal.R.styleable.WindowAnimation);
2676         }
2677         return null;
2678     }
2679
2680     private void applyEnterAnimationLocked(WindowState win) {
2681         int transit = WindowManagerPolicy.TRANSIT_SHOW;
2682         if (win.mEnterAnimationPending) {
2683             win.mEnterAnimationPending = false;
2684             transit = WindowManagerPolicy.TRANSIT_ENTER;
2685         }
2686
2687         applyAnimationLocked(win, transit, true);
2688     }
2689
2690     private boolean applyAnimationLocked(WindowState win,
2691             int transit, boolean isEntrance) {
2692         if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) {
2693             // If we are trying to apply an animation, but already running
2694             // an animation of the same type, then just leave that one alone.
2695             return true;
2696         }
2697
2698         // Only apply an animation if the display isn't frozen.  If it is
2699         // frozen, there is no reason to animate and it can cause strange
2700         // artifacts when we unfreeze the display if some different animation
2701         // is running.
2702         if (!mDisplayFrozen && mPolicy.isScreenOn()) {
2703             int anim = mPolicy.selectAnimationLw(win, transit);
2704             int attr = -1;
2705             Animation a = null;
2706             if (anim != 0) {
2707                 a = AnimationUtils.loadAnimation(mContext, anim);
2708             } else {
2709                 switch (transit) {
2710                     case WindowManagerPolicy.TRANSIT_ENTER:
2711                         attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
2712                         break;
2713                     case WindowManagerPolicy.TRANSIT_EXIT:
2714                         attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
2715                         break;
2716                     case WindowManagerPolicy.TRANSIT_SHOW:
2717                         attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
2718                         break;
2719                     case WindowManagerPolicy.TRANSIT_HIDE:
2720                         attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
2721                         break;
2722                 }
2723                 if (attr >= 0) {
2724                     a = loadAnimation(win.mAttrs, attr);
2725                 }
2726             }
2727             if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: win=" + win
2728                     + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
2729                     + " mAnimation=" + win.mAnimation
2730                     + " isEntrance=" + isEntrance);
2731             if (a != null) {
2732                 if (DEBUG_ANIM) {
2733                     RuntimeException e = null;
2734                     if (!HIDE_STACK_CRAWLS) {
2735                         e = new RuntimeException();
2736                         e.fillInStackTrace();
2737                     }
2738                     Slog.v(TAG, "Loaded animation " + a + " for " + win, e);
2739                 }
2740                 win.setAnimation(a);
2741                 win.mAnimationIsEntrance = isEntrance;
2742             }
2743         } else {
2744             win.clearAnimation();
2745         }
2746
2747         return win.mAnimation != null;
2748     }
2749
2750     private Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
2751         int anim = 0;
2752         Context context = mContext;
2753         if (animAttr >= 0) {
2754             AttributeCache.Entry ent = getCachedAnimations(lp);
2755             if (ent != null) {
2756                 context = ent.context;
2757                 anim = ent.array.getResourceId(animAttr, 0);
2758             }
2759         }
2760         if (anim != 0) {
2761             return AnimationUtils.loadAnimation(context, anim);
2762         }
2763         return null;
2764     }
2765
2766     private Animation loadAnimation(String packageName, int resId) {
2767         int anim = 0;
2768         Context context = mContext;
2769         if (resId >= 0) {
2770             AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
2771             if (ent != null) {
2772                 context = ent.context;
2773                 anim = resId;
2774             }
2775         }
2776         if (anim != 0) {
2777             return AnimationUtils.loadAnimation(context, anim);
2778         }
2779         return null;
2780     }
2781
2782     private boolean applyAnimationLocked(AppWindowToken wtoken,
2783             WindowManager.LayoutParams lp, int transit, boolean enter) {
2784         // Only apply an animation if the display isn't frozen.  If it is
2785         // frozen, there is no reason to animate and it can cause strange
2786         // artifacts when we unfreeze the display if some different animation
2787         // is running.
2788         if (!mDisplayFrozen && mPolicy.isScreenOn()) {
2789             Animation a;
2790             if (lp != null && (lp.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
2791                 a = new FadeInOutAnimation(enter);
2792                 if (DEBUG_ANIM) Slog.v(TAG,
2793                         "applying FadeInOutAnimation for a window in compatibility mode");
2794             } else if (mNextAppTransitionPackage != null) {
2795                 a = loadAnimation(mNextAppTransitionPackage, enter ?
2796                         mNextAppTransitionEnter : mNextAppTransitionExit);
2797             } else {
2798                 int animAttr = 0;
2799                 switch (transit) {
2800                     case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
2801                         animAttr = enter
2802                                 ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation
2803                                 : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
2804                         break;
2805                     case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
2806                         animAttr = enter
2807                                 ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation
2808                                 : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
2809                         break;
2810                     case WindowManagerPolicy.TRANSIT_TASK_OPEN:
2811                         animAttr = enter
2812                                 ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation
2813                                 : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
2814                         break;
2815                     case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
2816                         animAttr = enter
2817                                 ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation
2818                                 : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
2819                         break;
2820                     case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
2821                         animAttr = enter
2822                                 ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation
2823                                 : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
2824                         break;
2825                     case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
2826                         animAttr = enter
2827                                 ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation
2828                                 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
2829                         break;
2830                     case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN:
2831                         animAttr = enter
2832                                 ? com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation
2833                                 : com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
2834                         break;
2835                     case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE:
2836                         animAttr = enter
2837                                 ? com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation
2838                                 : com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
2839                         break;
2840                     case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN:
2841                         animAttr = enter
2842                                 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation
2843                                 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
2844                         break;
2845                     case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE:
2846                         animAttr = enter
2847                                 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation
2848                                 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
2849                         break;
2850                 }
2851                 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null;
2852                 if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
2853                         + " anim=" + a
2854                         + " animAttr=0x" + Integer.toHexString(animAttr)
2855                         + " transit=" + transit);
2856             }
2857             if (a != null) {
2858                 if (DEBUG_ANIM) {
2859                     RuntimeException e = null;
2860                     if (!HIDE_STACK_CRAWLS) {
2861                         e = new RuntimeException();
2862                         e.fillInStackTrace();
2863                     }
2864                     Slog.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
2865                 }
2866                 wtoken.setAnimation(a);
2867             }
2868         } else {
2869             wtoken.clearAnimation();
2870         }
2871
2872         return wtoken.animation != null;
2873     }
2874
2875     // -------------------------------------------------------------
2876     // Application Window Tokens
2877     // -------------------------------------------------------------
2878
2879     public void validateAppTokens(List tokens) {
2880         int v = tokens.size()-1;
2881         int m = mAppTokens.size()-1;
2882         while (v >= 0 && m >= 0) {
2883             AppWindowToken wtoken = mAppTokens.get(m);
2884             if (wtoken.removed) {
2885                 m--;
2886                 continue;
2887             }
2888             if (tokens.get(v) != wtoken.token) {
2889                 Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
2890                       + " @ " + v + ", internal is " + wtoken.token + " @ " + m);
2891             }
2892             v--;
2893             m--;
2894         }
2895         while (v >= 0) {
2896             Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
2897             v--;
2898         }
2899         while (m >= 0) {
2900             AppWindowToken wtoken = mAppTokens.get(m);
2901             if (!wtoken.removed) {
2902                 Slog.w(TAG, "Invalid internal token: " + wtoken.token + " @ " + m);
2903             }
2904             m--;
2905         }
2906     }
2907
2908     boolean checkCallingPermission(String permission, String func) {
2909         // Quick check: if the calling permission is me, it's all okay.
2910         if (Binder.getCallingPid() == Process.myPid()) {
2911             return true;
2912         }
2913
2914         if (mContext.checkCallingPermission(permission)
2915                 == PackageManager.PERMISSION_GRANTED) {
2916             return true;
2917         }
2918         String msg = "Permission Denial: " + func + " from pid="
2919                 + Binder.getCallingPid()
2920                 + ", uid=" + Binder.getCallingUid()
2921                 + " requires " + permission;
2922         Slog.w(TAG, msg);
2923         return false;
2924     }
2925
2926     AppWindowToken findAppWindowToken(IBinder token) {
2927         WindowToken wtoken = mTokenMap.get(token);
2928         if (wtoken == null) {
2929             return null;
2930         }
2931         return wtoken.appWindowToken;
2932     }
2933
2934     public void addWindowToken(IBinder token, int type) {
2935         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2936                 "addWindowToken()")) {
2937             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2938         }
2939
2940         synchronized(mWindowMap) {
2941             WindowToken wtoken = mTokenMap.get(token);
2942             if (wtoken != null) {
2943                 Slog.w(TAG, "Attempted to add existing input method token: " + token);
2944                 return;
2945             }
2946             wtoken = new WindowToken(token, type, true);
2947             mTokenMap.put(token, wtoken);
2948             mTokenList.add(wtoken);
2949             if (type == TYPE_WALLPAPER) {
2950                 mWallpaperTokens.add(wtoken);
2951             }
2952         }
2953     }
2954
2955     public void removeWindowToken(IBinder token) {
2956         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2957                 "removeWindowToken()")) {
2958             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2959         }
2960
2961         final long origId = Binder.clearCallingIdentity();
2962         synchronized(mWindowMap) {
2963             WindowToken wtoken = mTokenMap.remove(token);
2964             mTokenList.remove(wtoken);
2965             if (wtoken != null) {
2966                 boolean delayed = false;
2967                 if (!wtoken.hidden) {
2968                     wtoken.hidden = true;
2969
2970                     final int N = wtoken.windows.size();
2971                     boolean changed = false;
2972
2973                     for (int i=0; i<N; i++) {
2974                         WindowState win = wtoken.windows.get(i);
2975
2976                         if (win.isAnimating()) {
2977                             delayed = true;
2978                         }
2979
2980                         if (win.isVisibleNow()) {
2981                             applyAnimationLocked(win,
2982                                     WindowManagerPolicy.TRANSIT_EXIT, false);
2983                             mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
2984                                     KeyWaiter.RETURN_NOTHING);
2985                             changed = true;
2986                         }
2987                     }
2988
2989                     if (changed) {
2990                         mLayoutNeeded = true;
2991                         performLayoutAndPlaceSurfacesLocked();
2992                         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2993                     }
2994
2995                     if (delayed) {
2996                         mExitingTokens.add(wtoken);
2997                     } else if (wtoken.windowType == TYPE_WALLPAPER) {
2998                         mWallpaperTokens.remove(wtoken);
2999                     }
3000                 }
3001
3002             } else {
3003                 Slog.w(TAG, "Attempted to remove non-existing token: " + token);
3004             }
3005         }
3006         Binder.restoreCallingIdentity(origId);
3007     }
3008
3009     public void addAppToken(int addPos, IApplicationToken token,
3010             int groupId, int requestedOrientation, boolean fullscreen) {
3011         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3012                 "addAppToken()")) {
3013             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3014         }
3015
3016         synchronized(mWindowMap) {
3017             AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3018             if (wtoken != null) {
3019                 Slog.w(TAG, "Attempted to add existing app token: " + token);
3020                 return;
3021             }
3022             wtoken = new AppWindowToken(token);
3023             wtoken.groupId = groupId;
3024             wtoken.appFullscreen = fullscreen;
3025             wtoken.requestedOrientation = requestedOrientation;
3026             mAppTokens.add(addPos, wtoken);
3027             if (localLOGV) Slog.v(TAG, "Adding new app token: " + wtoken);
3028             mTokenMap.put(token.asBinder(), wtoken);
3029             mTokenList.add(wtoken);
3030
3031             // Application tokens start out hidden.
3032             wtoken.hidden = true;
3033             wtoken.hiddenRequested = true;
3034
3035             //dump();
3036         }
3037     }
3038
3039     public void setAppGroupId(IBinder token, int groupId) {
3040         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3041                 "setAppStartingIcon()")) {
3042             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3043         }
3044
3045         synchronized(mWindowMap) {
3046             AppWindowToken wtoken = findAppWindowToken(token);
3047             if (wtoken == null) {
3048                 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
3049                 return;
3050             }
3051             wtoken.groupId = groupId;
3052         }
3053     }
3054
3055     public int getOrientationFromWindowsLocked() {
3056         int pos = mWindows.size() - 1;
3057         while (pos >= 0) {
3058             WindowState wtoken = (WindowState) mWindows.get(pos);
3059             pos--;
3060             if (wtoken.mAppToken != null) {
3061                 // We hit an application window. so the orientation will be determined by the
3062                 // app window. No point in continuing further.
3063                 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3064             }
3065             if (!wtoken.isVisibleLw() || !wtoken.mPolicyVisibilityAfterAnim) {
3066                 continue;
3067             }
3068             int req = wtoken.mAttrs.screenOrientation;
3069             if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
3070                     (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
3071                 continue;
3072             } else {
3073                 return req;
3074             }
3075         }
3076         return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3077     }
3078
3079     public int getOrientationFromAppTokensLocked() {
3080         int pos = mAppTokens.size() - 1;
3081         int curGroup = 0;
3082         int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3083         boolean findingBehind = false;
3084         boolean haveGroup = false;
3085         boolean lastFullscreen = false;
3086         while (pos >= 0) {
3087             AppWindowToken wtoken = mAppTokens.get(pos);
3088             pos--;
3089             // if we're about to tear down this window and not seek for
3090             // the behind activity, don't use it for orientation
3091             if (!findingBehind
3092                     && (!wtoken.hidden && wtoken.hiddenRequested)) {
3093                 continue;
3094             }
3095
3096             if (!haveGroup) {
3097                 // We ignore any hidden applications on the top.
3098                 if (wtoken.hiddenRequested || wtoken.willBeHidden) {
3099                     continue;
3100                 }
3101                 haveGroup = true;
3102                 curGroup = wtoken.groupId;
3103                 lastOrientation = wtoken.requestedOrientation;
3104             } else if (curGroup != wtoken.groupId) {
3105                 // If we have hit a new application group, and the bottom
3106                 // of the previous group didn't explicitly say to use
3107                 // the orientation behind it, and the last app was
3108                 // full screen, then we'll stick with the
3109                 // user's orientation.
3110                 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
3111                         && lastFullscreen) {
3112                     return lastOrientation;
3113                 }
3114             }
3115             int or = wtoken.requestedOrientation;
3116             // If this application is fullscreen, and didn't explicitly say
3117             // to use the orientation behind it, then just take whatever
3118             // orientation it has and ignores whatever is under it.
3119             lastFullscreen = wtoken.appFullscreen;
3120             if (lastFullscreen
3121                     && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3122                 return or;
3123             }
3124             // If this application has requested an explicit orientation,
3125             // then use it.
3126             if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
3127                     or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
3128                     or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
3129                     or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
3130                     or == ActivityInfo.SCREEN_ORIENTATION_USER) {
3131                 return or;
3132             }
3133             findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
3134         }
3135         return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3136     }
3137
3138     public Configuration updateOrientationFromAppTokens(
3139             Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3140         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3141                 "updateOrientationFromAppTokens()")) {
3142             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3143         }
3144
3145         Configuration config = null;
3146         long ident = Binder.clearCallingIdentity();
3147         
3148         synchronized(mWindowMap) {
3149             if (updateOrientationFromAppTokensLocked()) {
3150                 if (freezeThisOneIfNeeded != null) {
3151                     AppWindowToken wtoken = findAppWindowToken(
3152                             freezeThisOneIfNeeded);
3153                     if (wtoken != null) {
3154                         startAppFreezingScreenLocked(wtoken,
3155                                 ActivityInfo.CONFIG_ORIENTATION);
3156                     }
3157                 }
3158                 config = computeNewConfigurationLocked();
3159                 
3160             } else if (currentConfig != null) {
3161                 // No obvious action we need to take, but if our current
3162                 // state mismatches the activity maanager's, update it
3163                 mTempConfiguration.setToDefaults();
3164                 if (computeNewConfigurationLocked(mTempConfiguration)) {
3165                     if (currentConfig.diff(mTempConfiguration) != 0) {
3166                         mWaitingForConfig = true;
3167                         mLayoutNeeded = true;
3168                         startFreezingDisplayLocked();
3169                         config = new Configuration(mTempConfiguration);
3170                     }
3171                 }
3172             }
3173         }
3174         
3175         Binder.restoreCallingIdentity(ident);
3176         return config;
3177     }
3178
3179     /*
3180      * Determine the new desired orientation of the display, returning
3181      * a non-null new Configuration if it has changed from the current
3182      * orientation.  IF TRUE IS RETURNED SOMEONE MUST CALL
3183      * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3184      * SCREEN.  This will typically be done for you if you call
3185      * sendNewConfiguration().
3186      * 
3187      * The orientation is computed from non-application windows first. If none of
3188      * the non-application windows specify orientation, the orientation is computed from
3189      * application tokens.
3190      * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3191      * android.os.IBinder)
3192      */
3193     boolean updateOrientationFromAppTokensLocked() {
3194         if (mDisplayFrozen) {
3195             // If the display is frozen, some activities may be in the middle
3196             // of restarting, and thus have removed their old window.  If the
3197             // window has the flag to hide the lock screen, then the lock screen
3198             // can re-appear and inflict its own orientation on us.  Keep the
3199             // orientation stable until this all settles down.
3200             return false;
3201         }
3202
3203         boolean changed = false;
3204         long ident = Binder.clearCallingIdentity();
3205         try {
3206             int req = computeForcedAppOrientationLocked();
3207
3208             if (req != mForcedAppOrientation) {
3209                 mForcedAppOrientation = req;
3210                 //send a message to Policy indicating orientation change to take
3211                 //action like disabling/enabling sensors etc.,
3212                 mPolicy.setCurrentOrientationLw(req);
3213                 if (setRotationUncheckedLocked(WindowManagerPolicy.USE_LAST_ROTATION,
3214                         mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE)) {
3215                     changed = true;
3216                 }
3217             }
3218
3219             return changed;
3220         } finally {
3221             Binder.restoreCallingIdentity(ident);
3222         }
3223     }
3224
3225     int computeForcedAppOrientationLocked() {
3226         int req = getOrientationFromWindowsLocked();
3227         if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
3228             req = getOrientationFromAppTokensLocked();
3229         }
3230         return req;
3231     }
3232
3233     public void setNewConfiguration(Configuration config) {
3234         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3235                 "setNewConfiguration()")) {
3236             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3237         }
3238
3239         synchronized(mWindowMap) {
3240             mCurConfiguration = new Configuration(config);
3241             mWaitingForConfig = false;
3242             performLayoutAndPlaceSurfacesLocked();
3243         }
3244     }
3245     
3246     public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3247         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3248                 "setAppOrientation()")) {
3249             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3250         }
3251
3252         synchronized(mWindowMap) {
3253             AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3254             if (wtoken == null) {
3255                 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
3256                 return;
3257             }
3258
3259             wtoken.requestedOrientation = requestedOrientation;
3260         }
3261     }
3262
3263     public int getAppOrientation(IApplicationToken token) {
3264         synchronized(mWindowMap) {
3265             AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3266             if (wtoken == null) {
3267                 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3268             }
3269
3270             return wtoken.requestedOrientation;
3271         }
3272     }
3273
3274     public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3275         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3276                 "setFocusedApp()")) {
3277             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3278         }
3279
3280         synchronized(mWindowMap) {
3281             boolean changed = false;
3282             if (token == null) {
3283                 if (DEBUG_FOCUS) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
3284                 changed = mFocusedApp != null;
3285                 mFocusedApp = null;
3286                 mKeyWaiter.tickle();
3287             } else {
3288                 AppWindowToken newFocus = findAppWindowToken(token);
3289                 if (newFocus == null) {
3290                     Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
3291                     return;
3292                 }
3293                 changed = mFocusedApp != newFocus;
3294                 mFocusedApp = newFocus;
3295                 if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp);
3296                 mKeyWaiter.tickle();
3297             }
3298
3299             if (moveFocusNow && changed) {
3300                 final long origId = Binder.clearCallingIdentity();
3301                 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3302                 Binder.restoreCallingIdentity(origId);
3303             }
3304         }
3305     }
3306
3307     public void prepareAppTransition(int transit) {
3308         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3309                 "prepareAppTransition()")) {
3310             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3311         }
3312
3313         synchronized(mWindowMap) {
3314             if (DEBUG_APP_TRANSITIONS) Slog.v(
3315                     TAG, "Prepare app transition: transit=" + transit
3316                     + " mNextAppTransition=" + mNextAppTransition);
3317             if (!mDisplayFrozen && mPolicy.isScreenOn()) {
3318                 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET
3319                         || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) {
3320                     mNextAppTransition = transit;
3321                 } else if (transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
3322                         && mNextAppTransition == WindowManagerPolicy.TRANSIT_TASK_CLOSE) {
3323                     // Opening a new task always supersedes a close for the anim.
3324                     mNextAppTransition = transit;
3325                 } else if (transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
3326                         && mNextAppTransition == WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE) {
3327                     // Opening a new activity always supersedes a close for the anim.
3328                     mNextAppTransition = transit;
3329                 }
3330                 mAppTransitionReady = false;
3331                 mAppTransitionTimeout = false;
3332                 mStartingIconInTransition = false;
3333                 mSkipAppTransitionAnimation = false;
3334                 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
3335                 mH.sendMessageDelayed(mH.obtainMessage(H.APP_TRANSITION_TIMEOUT),
3336                         5000);
3337             }
3338         }
3339     }
3340
3341     public int getPendingAppTransition() {
3342         return mNextAppTransition;
3343     }
3344
3345     public void overridePendingAppTransition(String packageName,
3346             int enterAnim, int exitAnim) {
3347         if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
3348             mNextAppTransitionPackage = packageName;
3349             mNextAppTransitionEnter = enterAnim;
3350             mNextAppTransitionExit = exitAnim;
3351         }
3352     }
3353
3354     public void executeAppTransition() {
3355         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3356                 "executeAppTransition()")) {
3357             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3358         }
3359
3360         synchronized(mWindowMap) {
3361             if (DEBUG_APP_TRANSITIONS) {
3362                 RuntimeException e = new RuntimeException("here");
3363                 e.fillInStackTrace();
3364                 Slog.w(TAG, "Execute app transition: mNextAppTransition="
3365                         + mNextAppTransition, e);
3366             }
3367             if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
3368                 mAppTransitionReady = true;
3369                 final long origId = Binder.clearCallingIdentity();
3370                 performLayoutAndPlaceSurfacesLocked();
3371                 Binder.restoreCallingIdentity(origId);
3372             }
3373         }
3374     }
3375
3376     public void setAppStartingWindow(IBinder token, String pkg,
3377             int theme, CharSequence nonLocalizedLabel, int labelRes, int icon,
3378             IBinder transferFrom, boolean createIfNeeded) {
3379         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3380                 "setAppStartingIcon()")) {
3381             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3382         }
3383
3384         synchronized(mWindowMap) {
3385             if (DEBUG_STARTING_WINDOW) Slog.v(
3386                     TAG, "setAppStartingIcon: token=" + token + " pkg=" + pkg
3387                     + " transferFrom=" + transferFrom);
3388
3389             AppWindowToken wtoken = findAppWindowToken(token);
3390             if (wtoken == null) {
3391                 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
3392                 return;
3393             }
3394
3395             // If the display is frozen, we won't do anything until the
3396             // actual window is displayed so there is no reason to put in
3397             // the starting window.
3398             if (mDisplayFrozen || !mPolicy.isScreenOn()) {
3399                 return;
3400             }
3401
3402             if (wtoken.startingData != null) {
3403                 return;
3404             }
3405
3406             if (transferFrom != null) {
3407                 AppWindowToken ttoken = findAppWindowToken(transferFrom);
3408                 if (ttoken != null) {
3409                     WindowState startingWindow = ttoken.startingWindow;
3410                     if (startingWindow != null) {
3411                         if (mStartingIconInTransition) {
3412                             // In this case, the starting icon has already
3413                             // been displayed, so start letting windows get
3414                             // shown immediately without any more transitions.
3415                             mSkipAppTransitionAnimation = true;
3416                         }
3417                         if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
3418                                 "Moving existing starting from " + ttoken
3419                                 + " to " + wtoken);
3420                         final long origId = Binder.clearCallingIdentity();
3421
3422                         // Transfer the starting window over to the new
3423                         // token.
3424                         wtoken.startingData = ttoken.startingData;
3425                         wtoken.startingView = ttoken.startingView;
3426                         wtoken.startingWindow = startingWindow;
3427                         ttoken.startingData = null;
3428                         ttoken.startingView = null;
3429                         ttoken.startingWindow = null;
3430                         ttoken.startingMoved = true;
3431                         startingWindow.mToken = wtoken;
3432                         startingWindow.mRootToken = wtoken;
3433                         startingWindow.mAppToken = wtoken;
3434                         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
3435                                 "Removing starting window: " + startingWindow);
3436                         mWindows.remove(startingWindow);
3437                         ttoken.windows.remove(startingWindow);
3438                         ttoken.allAppWindows.remove(startingWindow);
3439                         addWindowToListInOrderLocked(startingWindow, true);
3440
3441                         // Propagate other interesting state between the
3442                         // tokens.  If the old token is displayed, we should
3443                         // immediately force the new one to be displayed.  If
3444                         // it is animating, we need to move that animation to
3445                         // the new one.
3446                         if (ttoken.allDrawn) {
3447                             wtoken.allDrawn = true;
3448                         }
3449                         if (ttoken.firstWindowDrawn) {
3450                             wtoken.firstWindowDrawn = true;
3451                         }
3452                         if (!ttoken.hidden) {
3453                             wtoken.hidden = false;
3454                             wtoken.hiddenRequested = false;
3455                             wtoken.willBeHidden = false;
3456                         }
3457                         if (wtoken.clientHidden != ttoken.clientHidden) {
3458                             wtoken.clientHidden = ttoken.clientHidden;
3459                             wtoken.sendAppVisibilityToClients();
3460                         }
3461                         if (ttoken.animation != null) {
3462                             wtoken.animation = ttoken.animation;
3463                             wtoken.animating = ttoken.animating;
3464                             wtoken.animLayerAdjustment = ttoken.animLayerAdjustment;
3465                             ttoken.animation = null;
3466                             ttoken.animLayerAdjustment = 0;
3467                             wtoken.updateLayers();
3468                             ttoken.updateLayers();
3469                         }
3470
3471                         updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
3472                         mLayoutNeeded = true;
3473                         performLayoutAndPlaceSurfacesLocked();
3474                         Binder.restoreCallingIdentity(origId);
3475                         return;
3476                     } else if (ttoken.startingData != null) {
3477                         // The previous app was getting ready to show a
3478                         // starting window, but hasn't yet done so.  Steal it!
3479                         if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
3480                                 "Moving pending starting from " + ttoken
3481                                 + " to " + wtoken);
3482                         wtoken.startingData = ttoken.startingData;
3483                         ttoken.startingData = null;
3484                         ttoken.startingMoved = true;
3485                         Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3486                         // Note: we really want to do sendMessageAtFrontOfQueue() because we
3487                         // want to process the message ASAP, before any other queued
3488                         // messages.
3489                         mH.sendMessageAtFrontOfQueue(m);
3490                         return;
3491                     }
3492                 }
3493             }
3494
3495             // There is no existing starting window, and the caller doesn't
3496             // want us to create one, so that's it!
3497             if (!createIfNeeded) {
3498                 return;
3499             }
3500
3501             // If this is a translucent or wallpaper window, then don't
3502             // show a starting window -- the current effect (a full-screen
3503             // opaque starting window that fades away to the real contents
3504             // when it is ready) does not work for this.
3505             if (theme != 0) {
3506                 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
3507                         com.android.internal.R.styleable.Window);
3508                 if (ent.array.getBoolean(
3509                         com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
3510                     return;
3511                 }
3512                 if (ent.array.getBoolean(
3513                         com.android.internal.R.styleable.Window_windowIsFloating, false)) {
3514                     return;
3515                 }
3516                 if (ent.array.getBoolean(
3517                         com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
3518                     return;
3519                 }
3520             }
3521
3522             mStartingIconInTransition = true;
3523             wtoken.startingData = new StartingData(
3524                     pkg, theme, nonLocalizedLabel,
3525                     labelRes, icon);
3526             Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3527             // Note: we really want to do sendMessageAtFrontOfQueue() because we
3528             // want to process the message ASAP, before any other queued
3529             // messages.
3530             mH.sendMessageAtFrontOfQueue(m);
3531         }
3532     }
3533
3534     public void setAppWillBeHidden(IBinder token) {
3535         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3536                 "setAppWillBeHidden()")) {
3537             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3538         }
3539
3540         AppWindowToken wtoken;
3541
3542         synchronized(mWindowMap) {
3543             wtoken = findAppWindowToken(token);
3544             if (wtoken == null) {
3545                 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
3546                 return;
3547             }
3548             wtoken.willBeHidden = true;
3549         }
3550     }
3551
3552     boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
3553             boolean visible, int transit, boolean performLayout) {
3554         boolean delayed = false;
3555
3556         if (wtoken.clientHidden == visible) {
3557             wtoken.clientHidden = !visible;
3558             wtoken.sendAppVisibilityToClients();
3559         }
3560
3561         wtoken.willBeHidden = false;
3562         if (wtoken.hidden == visible) {
3563             final int N = wtoken.allAppWindows.size();
3564             boolean changed = false;
3565             if (DEBUG_APP_TRANSITIONS) Slog.v(
3566                 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
3567                 + " performLayout=" + performLayout);
3568
3569             boolean runningAppAnimation = false;
3570
3571             if (transit != WindowManagerPolicy.TRANSIT_UNSET) {
3572                 if (wtoken.animation == sDummyAnimation) {
3573                     wtoken.animation = null;
3574                 }
3575                 applyAnimationLocked(wtoken, lp, transit, visible);
3576                 changed = true;
3577                 if (wtoken.animation != null) {
3578                     delayed = runningAppAnimation = true;
3579                 }
3580             }
3581
3582             for (int i=0; i<N; i++) {
3583                 WindowState win = wtoken.allAppWindows.get(i);
3584                 if (win == wtoken.startingWindow) {
3585                     continue;
3586                 }
3587
3588                 if (win.isAnimating()) {
3589                     delayed = true;
3590                 }
3591
3592                 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
3593                 //win.dump("  ");
3594                 if (visible) {
3595                     if (!win.isVisibleNow()) {
3596                         if (!runningAppAnimation) {
3597                             applyAnimationLocked(win,
3598                                     WindowManagerPolicy.TRANSIT_ENTER, true);
3599                         }
3600                         changed = true;
3601                     }
3602                 } else if (win.isVisibleNow()) {
3603                     if (!runningAppAnimation) {
3604                         applyAnimationLocked(win,
3605                                 WindowManagerPolicy.TRANSIT_EXIT, false);
3606                     }
3607                     mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
3608                             KeyWaiter.RETURN_NOTHING);
3609                     changed = true;
3610                 }
3611             }
3612
3613             wtoken.hidden = wtoken.hiddenRequested = !visible;
3614             if (!visible) {
3615                 unsetAppFreezingScreenLocked(wtoken, true, true);
3616             } else {
3617                 // If we are being set visible, and the starting window is
3618                 // not yet displayed, then make sure it doesn't get displayed.
3619                 WindowState swin = wtoken.startingWindow;
3620                 if (swin != null && (swin.mDrawPending
3621                         || swin.mCommitDrawPending)) {
3622                     swin.mPolicyVisibility = false;
3623                     swin.mPolicyVisibilityAfterAnim = false;
3624                  }
3625             }
3626
3627             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
3628                       + ": hidden=" + wtoken.hidden + " hiddenRequested="
3629                       + wtoken.hiddenRequested);
3630
3631             if (changed) {
3632                 mLayoutNeeded = true;
3633                 if (performLayout) {
3634                     updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
3635                     performLayoutAndPlaceSurfacesLocked();
3636                 }
3637             }
3638         }
3639
3640         if (wtoken.animation != null) {
3641             delayed = true;
3642         }
3643
3644         return delayed;
3645     }
3646
3647     public void setAppVisibility(IBinder token, boolean visible) {
3648         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3649                 "setAppVisibility()")) {
3650             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3651         }
3652
3653         AppWindowToken wtoken;
3654
3655         synchronized(mWindowMap) {
3656             wtoken = findAppWindowToken(token);
3657             if (wtoken == null) {
3658                 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
3659                 return;
3660             }
3661
3662             if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
3663                 RuntimeException e = null;
3664                 if (!HIDE_STACK_CRAWLS) {
3665                     e = new RuntimeException();
3666                     e.fillInStackTrace();
3667                 }
3668                 Slog.v(TAG, "setAppVisibility(" + token + ", " + visible
3669                         + "): mNextAppTransition=" + mNextAppTransition
3670                         + " hidden=" + wtoken.hidden
3671                         + " hiddenRequested=" + wtoken.hiddenRequested, e);
3672             }
3673
3674             // If we are preparing an app transition, then delay changing
3675             // the visibility of this token until we execute that transition.
3676             if (!mDisplayFrozen && mPolicy.isScreenOn()
3677                     && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
3678                 // Already in requested state, don't do anything more.
3679                 if (wtoken.hiddenRequested != visible) {
3680                     return;
3681                 }
3682                 wtoken.hiddenRequested = !visible;
3683
3684                 if (DEBUG_APP_TRANSITIONS) Slog.v(
3685                         TAG, "Setting dummy animation on: " + wtoken);
3686                 wtoken.setDummyAnimation();
3687                 mOpeningApps.remove(wtoken);
3688                 mClosingApps.remove(wtoken);
3689                 wtoken.waitingToShow = wtoken.waitingToHide = false;
3690                 wtoken.inPendingTransaction = true;
3691                 if (visible) {
3692                     mOpeningApps.add(wtoken);
3693                     wtoken.startingDisplayed = false;
3694                     wtoken.startingMoved = false;
3695
3696                     // If the token is currently hidden (should be the
3697                     // common case), then we need to set up to wait for
3698                     // its windows to be ready.
3699                     if (wtoken.hidden) {
3700                         wtoken.allDrawn = false;
3701                         wtoken.waitingToShow = true;
3702
3703                         if (wtoken.clientHidden) {
3704                             // In the case where we are making an app visible
3705                             // but holding off for a transition, we still need
3706                             // to tell the client to make its windows visible so
3707                             // they get drawn.  Otherwise, we will wait on
3708                             // performing the transition until all windows have
3709                             // been drawn, they never will be, and we are sad.
3710                             wtoken.clientHidden = false;
3711                             wtoken.sendAppVisibilityToClients();
3712                         }
3713                     }
3714                 } else {
3715                     mClosingApps.add(wtoken);
3716
3717                     // If the token is currently visible (should be the
3718                     // common case), then set up to wait for it to be hidden.
3719                     if (!wtoken.hidden) {
3720                         wtoken.waitingToHide = true;
3721                     }
3722                 }
3723                 return;
3724             }
3725
3726             final long origId = Binder.clearCallingIdentity();
3727             setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_UNSET, true);
3728             wtoken.updateReportedVisibilityLocked();
3729             Binder.restoreCallingIdentity(origId);
3730         }
3731     }
3732
3733     void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
3734             boolean unfreezeSurfaceNow, boolean force) {
3735         if (wtoken.freezingScreen) {
3736             if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
3737                     + " force=" + force);
3738             final int N = wtoken.allAppWindows.size();
3739             boolean unfrozeWindows = false;
3740             for (int i=0; i<N; i++) {
3741                 WindowState w = wtoken.allAppWindows.get(i);
3742                 if (w.mAppFreezing) {
3743                     w.mAppFreezing = false;
3744                     if (w.mSurface != null && !w.mOrientationChanging) {
3745                         w.mOrientationChanging = true;
3746                     }
3747                     unfrozeWindows = true;
3748                 }
3749             }
3750             if (force || unfrozeWindows) {
3751                 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
3752                 wtoken.freezingScreen = false;
3753                 mAppsFreezingScreen--;
3754             }
3755             if (unfreezeSurfaceNow) {
3756                 if (unfrozeWindows) {
3757                     mLayoutNeeded = true;
3758                     performLayoutAndPlaceSurfacesLocked();
3759                 }
3760                 stopFreezingDisplayLocked();
3761             }
3762         }
3763     }
3764
3765     public void startAppFreezingScreenLocked(AppWindowToken wtoken,
3766             int configChanges) {
3767         if (DEBUG_ORIENTATION) {
3768             RuntimeException e = null;
3769             if (!HIDE_STACK_CRAWLS) {
3770                 e = new RuntimeException();
3771                 e.fillInStackTrace();
3772             }
3773             Slog.i(TAG, "Set freezing of " + wtoken.appToken
3774                     + ": hidden=" + wtoken.hidden + " freezing="
3775                     + wtoken.freezingScreen, e);
3776         }
3777         if (!wtoken.hiddenRequested) {
3778             if (!wtoken.freezingScreen) {
3779                 wtoken.freezingScreen = true;
3780                 mAppsFreezingScreen++;
3781                 if (mAppsFreezingScreen == 1) {
3782                     startFreezingDisplayLocked();
3783                     mH.removeMessages(H.APP_FREEZE_TIMEOUT);
3784                     mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT),
3785                             5000);
3786                 }
3787             }
3788             final int N = wtoken.allAppWindows.size();
3789             for (int i=0; i<N; i++) {
3790                 WindowState w = wtoken.allAppWindows.get(i);
3791                 w.mAppFreezing = true;
3792             }
3793         }
3794     }
3795
3796     public void startAppFreezingScreen(IBinder token, int configChanges) {
3797         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3798                 "setAppFreezingScreen()")) {
3799             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3800         }
3801
3802         synchronized(mWindowMap) {
3803             if (configChanges == 0 && !mDisplayFrozen && mPolicy.isScreenOn()) {
3804                 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
3805                 return;
3806             }
3807
3808             AppWindowToken wtoken = findAppWindowToken(token);
3809             if (wtoken == null || wtoken.appToken == null) {
3810                 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
3811                 return;
3812             }
3813             final long origId = Binder.clearCallingIdentity();
3814             startAppFreezingScreenLocked(wtoken, configChanges);
3815             Binder.restoreCallingIdentity(origId);
3816         }
3817     }
3818
3819     public void stopAppFreezingScreen(IBinder token, boolean force) {
3820         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3821                 "setAppFreezingScreen()")) {
3822             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3823         }
3824
3825         synchronized(mWindowMap) {
3826             AppWindowToken wtoken = findAppWindowToken(token);
3827             if (wtoken == null || wtoken.appToken == null) {
3828                 return;
3829             }
3830             final long origId = Binder.clearCallingIdentity();
3831             if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
3832                     + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.freezingScreen);
3833             unsetAppFreezingScreenLocked(wtoken, true, force);
3834             Binder.restoreCallingIdentity(origId);
3835         }
3836     }
3837
3838     public void removeAppToken(IBinder token) {
3839         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3840                 "removeAppToken()")) {
3841             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3842         }
3843
3844         AppWindowToken wtoken = null;
3845         AppWindowToken startingToken = null;
3846         boolean delayed = false;
3847
3848         final long origId = Binder.clearCallingIdentity();
3849         synchronized(mWindowMap) {
3850             WindowToken basewtoken = mTokenMap.remove(token);
3851             mTokenList.remove(basewtoken);
3852             if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
3853                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
3854                 delayed = setTokenVisibilityLocked(wtoken, null, false, WindowManagerPolicy.TRANSIT_UNSET, true);
3855                 wtoken.inPendingTransaction = false;
3856                 mOpeningApps.remove(wtoken);
3857                 wtoken.waitingToShow = false;
3858                 if (mClosingApps.contains(wtoken)) {
3859                     delayed = true;
3860                 } else if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
3861                     mClosingApps.add(wtoken);
3862                     wtoken.waitingToHide = true;
3863                     delayed = true;
3864                 }
3865                 if (DEBUG_APP_TRANSITIONS) Slog.v(
3866                         TAG, "Removing app " + wtoken + " delayed=" + delayed
3867                         + " animation=" + wtoken.animation
3868                         + " animating=" + wtoken.animating);
3869                 if (delayed) {
3870                     // set the token aside because it has an active animation to be finished
3871                     mExitingAppTokens.add(wtoken);
3872                 } else {
3873                     // Make sure there is no animation running on this token,
3874                     // so any windows associated with it will be removed as
3875                     // soon as their animations are complete
3876                     wtoken.animation = null;
3877                     wtoken.animating = false;
3878                 }
3879                 mAppTokens.remove(wtoken);
3880                 if (mLastEnterAnimToken == wtoken) {
3881                     mLastEnterAnimToken = null;
3882                     mLastEnterAnimParams = null;
3883                 }
3884                 wtoken.removed = true;
3885                 if (wtoken.startingData != null) {
3886                     startingToken = wtoken;
3887                 }
3888                 unsetAppFreezingScreenLocked(wtoken, true, true);
3889                 if (mFocusedApp == wtoken) {
3890                     if (DEBUG_FOCUS) Slog.v(TAG, "Removing focused app token:" + wtoken);
3891                     mFocusedApp = null;
3892                     updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3893                     mKeyWaiter.tickle();
3894                 }
3895             } else {
3896                 Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
3897             }
3898
3899             if (!delayed && wtoken != null) {
3900                 wtoken.updateReportedVisibilityLocked();
3901             }
3902         }
3903         Binder.restoreCallingIdentity(origId);
3904
3905         if (startingToken != null) {
3906             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Schedule remove starting "
3907                     + startingToken + ": app token removed");
3908             Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken);
3909             mH.sendMessage(m);
3910         }
3911     }
3912
3913     private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
3914         final int NW = token.windows.size();
3915         for (int i=0; i<NW; i++) {
3916             WindowState win = token.windows.get(i);
3917             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
3918             mWindows.remove(win);
3919             int j = win.mChildWindows.size();
3920             while (j > 0) {
3921                 j--;
3922                 WindowState cwin = (WindowState)win.mChildWindows.get(j);
3923                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
3924                         "Tmp removing child window " + cwin);
3925                 mWindows.remove(cwin);
3926             }
3927         }
3928         return NW > 0;
3929     }
3930
3931     void dumpAppTokensLocked() {
3932         for (int i=mAppTokens.size()-1; i>=0; i--) {
3933             Slog.v(TAG, "  #" + i + ": " + mAppTokens.get(i).token);
3934         }
3935     }
3936
3937     void dumpWindowsLocked() {
3938         for (int i=mWindows.size()-1; i>=0; i--) {
3939             Slog.v(TAG, "  #" + i + ": " + mWindows.get(i));
3940         }
3941     }
3942
3943     private int findWindowOffsetLocked(int tokenPos) {
3944         final int NW = mWindows.size();
3945
3946         if (tokenPos >= mAppTokens.size()) {
3947             int i = NW;
3948             while (i > 0) {
3949                 i--;
3950                 WindowState win = (WindowState)mWindows.get(i);
3951                 if (win.getAppToken() != null) {
3952                     return i+1;
3953                 }
3954             }
3955         }
3956
3957         while (tokenPos > 0) {
3958             // Find the first app token below the new position that has
3959             // a window displayed.
3960             final AppWindowToken wtoken = mAppTokens.get(tokenPos-1);
3961             if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ "
3962                     + tokenPos + " -- " + wtoken.token);
3963             if (wtoken.sendingToBottom) {
3964                 if (DEBUG_REORDER) Slog.v(TAG,
3965                         "Skipping token -- currently sending to bottom");
3966                 tokenPos--;
3967                 continue;
3968             }
3969             int i = wtoken.windows.size();
3970             while (i > 0) {
3971                 i--;
3972                 WindowState win = wtoken.windows.get(i);
3973                 int j = win.mChildWindows.size();
3974                 while (j > 0) {
3975                     j--;
3976                     WindowState cwin = (WindowState)win.mChildWindows.get(j);
3977                     if (cwin.mSubLayer >= 0) {
3978                         for (int pos=NW-1; pos>=0; pos--) {
3979                             if (mWindows.get(pos) == cwin) {
3980                                 if (DEBUG_REORDER) Slog.v(TAG,
3981                                         "Found child win @" + (pos+1));
3982                                 return pos+1;
3983                             }
3984                         }
3985                     }
3986                 }
3987                 for (int pos=NW-1; pos>=0; pos--) {
3988                     if (mWindows.get(pos) == win) {
3989                         if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos+1));
3990                         return pos+1;
3991                     }
3992                 }
3993             }
3994             tokenPos--;
3995         }
3996
3997         return 0;
3998     }
3999
4000     private final int reAddWindowLocked(int index, WindowState win) {
4001         final int NCW = win.mChildWindows.size();
4002         boolean added = false;
4003         for (int j=0; j<NCW; j++) {
4004             WindowState cwin = (WindowState)win.mChildWindows.get(j);
4005             if (!added && cwin.mSubLayer >= 0) {
4006                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
4007                         + index + ": " + cwin);
4008                 mWindows.add(index, win);
4009                 index++;
4010                 added = true;
4011             }
4012             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4013                     + index + ": " + cwin);
4014             mWindows.add(index, cwin);
4015             index++;
4016         }
4017         if (!added) {
4018             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4019                     + index + ": " + win);
4020             mWindows.add(index, win);
4021             index++;
4022         }
4023         return index;
4024     }
4025
4026     private final int reAddAppWindowsLocked(int index, WindowToken token) {
4027         final int NW = token.windows.size();
4028         for (int i=0; i<NW; i++) {
4029             index = reAddWindowLocked(index, token.windows.get(i));
4030         }
4031         return index;
4032     }
4033
4034     public void moveAppToken(int index, IBinder token) {
4035         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4036                 "moveAppToken()")) {
4037             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4038         }
4039
4040         synchronized(mWindowMap) {
4041             if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:");
4042             if (DEBUG_REORDER) dumpAppTokensLocked();
4043             final AppWindowToken wtoken = findAppWindowToken(token);
4044             if (wtoken == null || !mAppTokens.remove(wtoken)) {
4045                 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
4046                       + token + " (" + wtoken + ")");
4047                 return;
4048             }
4049             mAppTokens.add(index, wtoken);
4050             if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":");
4051             if (DEBUG_REORDER) dumpAppTokensLocked();
4052
4053             final long origId = Binder.clearCallingIdentity();
4054             if (DEBUG_REORDER) Slog.v(TAG, "Removing windows in " + token + ":");
4055             if (DEBUG_REORDER) dumpWindowsLocked();
4056             if (tmpRemoveAppWindowsLocked(wtoken)) {
4057                 if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:");
4058                 if (DEBUG_REORDER) dumpWindowsLocked();
4059                 reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken);
4060                 if (DEBUG_REORDER) Slog.v(TAG, "Final window list:");
4061                 if (DEBUG_REORDER) dumpWindowsLocked();
4062                 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
4063                 mLayoutNeeded = true;
4064                 performLayoutAndPlaceSurfacesLocked();
4065             }
4066             Binder.restoreCallingIdentity(origId);
4067         }
4068     }
4069
4070     private void removeAppTokensLocked(List<IBinder> tokens) {
4071         // XXX This should be done more efficiently!
4072         // (take advantage of the fact that both lists should be
4073         // ordered in the same way.)
4074         int N = tokens.size();
4075         for (int i=0; i<N; i++) {
4076             IBinder token = tokens.get(i);
4077             final AppWindowToken wtoken = findAppWindowToken(token);
4078             if (!mAppTokens.remove(wtoken)) {
4079                 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
4080                       + token + " (" + wtoken + ")");
4081                 i--;
4082                 N--;
4083             }
4084         }
4085     }
4086
4087     private void moveAppWindowsLocked(AppWindowToken wtoken, int tokenPos,
4088             boolean updateFocusAndLayout) {
4089         // First remove all of the windows from the list.
4090         tmpRemoveAppWindowsLocked(wtoken);
4091
4092         // Where to start adding?
4093         int pos = findWindowOffsetLocked(tokenPos);
4094
4095         // And now add them back at the correct place.
4096         pos = reAddAppWindowsLocked(pos, wtoken);
4097
4098         if (updateFocusAndLayout) {
4099             if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
4100                 assignLayersLocked();
4101             }
4102             mLayoutNeeded = true;
4103             performLayoutAndPlaceSurfacesLocked();
4104         }
4105     }
4106
4107     private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) {
4108         // First remove all of the windows from the list.
4109         final int N = tokens.size();
4110         int i;
4111         for (i=0; i<N; i++) {
4112             WindowToken token = mTokenMap.get(tokens.get(i));
4113             if (token != null) {
4114                 tmpRemoveAppWindowsLocked(token);
4115             }
4116         }
4117
4118         // Where to start adding?
4119         int pos = findWindowOffsetLocked(tokenPos);
4120
4121         // And now add them back at the correct place.
4122         for (i=0; i<N; i++) {
4123             WindowToken token = mTokenMap.get(tokens.get(i));
4124             if (token != null) {
4125                 pos = reAddAppWindowsLocked(pos, token);
4126             }
4127         }
4128
4129         if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
4130             assignLayersLocked();
4131         }
4132         mLayoutNeeded = true;
4133         performLayoutAndPlaceSurfacesLocked();
4134
4135         //dump();
4136     }
4137
4138     public void moveAppTokensToTop(List<IBinder> tokens) {
4139         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4140                 "moveAppTokensToTop()")) {
4141             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4142         }
4143
4144         final long origId = Binder.clearCallingIdentity();
4145         synchronized(mWindowMap) {
4146             removeAppTokensLocked(tokens);
4147             final int N = tokens.size();
4148             for (int i=0; i<N; i++) {
4149                 AppWindowToken wt = findAppWindowToken(tokens.get(i));
4150                 if (wt != null) {
4151                     mAppTokens.add(wt);
4152                     if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
4153                         mToTopApps.remove(wt);
4154                         mToBottomApps.remove(wt);
4155                         mToTopApps.add(wt);
4156                         wt.sendingToBottom = false;
4157                         wt.sendingToTop = true;
4158                     }
4159                 }
4160             }
4161
4162             if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
4163                 moveAppWindowsLocked(tokens, mAppTokens.size());
4164             }
4165         }
4166         Binder.restoreCallingIdentity(origId);
4167     }
4168
4169     public void moveAppTokensToBottom(List<IBinder> tokens) {
4170         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4171                 "moveAppTokensToBottom()")) {
4172             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4173         }
4174
4175         final long origId = Binder.clearCallingIdentity();
4176         synchronized(mWindowMap) {
4177             removeAppTokensLocked(tokens);
4178             final int N = tokens.size();
4179             int pos = 0;
4180             for (int i=0; i<N; i++) {
4181                 AppWindowToken wt = findAppWindowToken(tokens.get(i));
4182                 if (wt != null) {
4183                     mAppTokens.add(pos, wt);
4184                     if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
4185                         mToTopApps.remove(wt);
4186                         mToBottomApps.remove(wt);
4187                         mToBottomApps.add(i, wt);
4188                         wt.sendingToTop = false;
4189                         wt.sendingToBottom = true;
4190                     }
4191                     pos++;
4192                 }
4193             }
4194
4195             if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
4196                 moveAppWindowsLocked(tokens, 0);
4197             }
4198         }
4199         Binder.restoreCallingIdentity(origId);
4200     }
4201
4202     // -------------------------------------------------------------
4203     // Misc IWindowSession methods
4204     // -------------------------------------------------------------
4205
4206     private boolean shouldAllowDisableKeyguard()
4207     {
4208         // We fail safe and prevent disabling keyguard in the unlikely event this gets 
4209         // called before DevicePolicyManagerService has started.
4210         if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) {
4211             DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
4212                     Context.DEVICE_POLICY_SERVICE);
4213             if (dpm != null) {
4214                 mAllowDisableKeyguard = dpm.getPasswordQuality(null)
4215                         == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
4216                                 ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
4217             }
4218         }
4219         return mAllowDisableKeyguard == ALLOW_DISABLE_YES;
4220     }
4221
4222     public void disableKeyguard(IBinder token, String tag) {
4223         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
4224             != PackageManager.PERMISSION_GRANTED) {
4225             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4226         }
4227
4228         synchronized (mKeyguardTokenWatcher) {
4229             mKeyguardTokenWatcher.acquire(token, tag);
4230         }
4231     }
4232
4233     public void reenableKeyguard(IBinder token) {
4234         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
4235             != PackageManager.PERMISSION_GRANTED) {
4236             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4237         }
4238
4239         synchronized (mKeyguardTokenWatcher) {
4240             mKeyguardTokenWatcher.release(token);
4241
4242             if (!mKeyguardTokenWatcher.isAcquired()) {
4243                 // If we are the last one to reenable the keyguard wait until
4244                 // we have actually finished reenabling until returning.
4245                 // It is possible that reenableKeyguard() can be called before
4246                 // the previous disableKeyguard() is handled, in which case
4247                 // neither mKeyguardTokenWatcher.acquired() or released() would
4248                 // be called. In that case mKeyguardDisabled will be false here
4249                 // and we have nothing to wait for.
4250                 while (mKeyguardDisabled) {
4251                     try {
4252                         mKeyguardTokenWatcher.wait();
4253                     } catch (InterruptedException e) {
4254                         Thread.currentThread().interrupt();
4255                     }
4256                 }
4257             }
4258         }
4259     }
4260
4261     /**
4262      * @see android.app.KeyguardManager#exitKeyguardSecurely
4263      */
4264     public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
4265         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
4266             != PackageManager.PERMISSION_GRANTED) {
4267             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4268         }
4269         mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
4270             public void onKeyguardExitResult(boolean success) {
4271                 try {
4272                     callback.onKeyguardExitResult(success);
4273                 } catch (RemoteException e) {
4274                     // Client has died, we don't care.
4275                 }
4276             }
4277         });
4278     }
4279
4280     public boolean inKeyguardRestrictedInputMode() {
4281         return mPolicy.inKeyguardRestrictedKeyInputMode();
4282     }
4283
4284     public void closeSystemDialogs(String reason) {
4285         synchronized(mWindowMap) {
4286             for (int i=mWindows.size()-1; i>=0; i--) {
4287                 WindowState w = (WindowState)mWindows.get(i);
4288                 if (w.mSurface != null) {
4289                     try {
4290                         w.mClient.closeSystemDialogs(reason);
4291                     } catch (RemoteException e) {
4292                     }
4293                 }
4294             }
4295         }
4296     }
4297
4298     static float fixScale(float scale) {
4299         if (scale < 0) scale = 0;
4300         else if (scale > 20) scale = 20;
4301         return Math.abs(scale);
4302     }
4303
4304     public void setAnimationScale(int which, float scale) {
4305         if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4306                 "setAnimationScale()")) {
4307             throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
4308         }
4309
4310         if (scale < 0) scale = 0;
4311         else if (scale > 20) scale = 20;
4312         scale = Math.abs(scale);
4313         switch (which) {
4314             case 0: mWindowAnimationScale = fixScale(scale); break;
4315             case 1: mTransitionAnimationScale = fixScale(scale); break;
4316         }
4317
4318         // Persist setting
4319         mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
4320     }
4321
4322     public void setAnimationScales(float[] scales) {
4323         if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4324                 "setAnimationScale()")) {
4325             throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
4326         }
4327
4328         if (scales != null) {
4329             if (scales.length >= 1) {
4330                 mWindowAnimationScale = fixScale(scales[0]);
4331             }
4332             if (scales.length >= 2) {
4333                 mTransitionAnimationScale = fixScale(scales[1]);
4334             }
4335         }
4336
4337         // Persist setting
4338         mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
4339     }
4340
4341     public float getAnimationScale(int which) {
4342         switch (which) {
4343             case 0: return mWindowAnimationScale;
4344             case 1: return mTransitionAnimationScale;
4345         }
4346         return 0;
4347     }
4348
4349     public float[] getAnimationScales() {
4350         return new float[] { mWindowAnimationScale, mTransitionAnimationScale };
4351     }
4352
4353     public int getSwitchState(int sw) {
4354         if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4355                 "getSwitchState()")) {
4356             throw new SecurityException("Requires READ_INPUT_STATE permission");
4357         }
4358         return KeyInputQueue.getSwitchState(sw);
4359     }
4360
4361     public int getSwitchStateForDevice(int devid, int sw) {
4362         if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4363                 "getSwitchStateForDevice()")) {
4364             throw new SecurityException("Requires READ_INPUT_STATE permission");
4365         }
4366         return KeyInputQueue.getSwitchState(devid, sw);
4367     }
4368
4369     public int getScancodeState(int sw) {
4370         if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4371                 "getScancodeState()")) {
4372             throw new SecurityException("Requires READ_INPUT_STATE permission");
4373         }
4374         return mQueue.getScancodeState(sw);
4375     }
4376
4377     public int getScancodeStateForDevice(int devid, int sw) {
4378         if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4379                 "getScancodeStateForDevice()")) {
4380             throw new SecurityException("Requires READ_INPUT_STATE permission");
4381         }
4382         return mQueue.getScancodeState(devid, sw);
4383     }
4384
4385     public int getTrackballScancodeState(int sw) {
4386         if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4387                 "getTrackballScancodeState()")) {
4388             throw new SecurityException("Requires READ_INPUT_STATE permission");
4389         }
4390         return mQueue.getTrackballScancodeState(sw);
4391     }
4392
4393     public int getDPadScancodeState(int sw) {
4394         if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4395                 "getDPadScancodeState()")) {
4396             throw new SecurityException("Requires READ_INPUT_STATE permission");
4397         }
4398         return mQueue.getDPadScancodeState(sw);
4399     }
4400
4401     public int getKeycodeState(int sw) {
4402         if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4403                 "getKeycodeState()")) {
4404             throw new SecurityException("Requires READ_INPUT_STATE permission");
4405         }
4406         return mQueue.getKeycodeState(sw);
4407     }
4408
4409     public int getKeycodeStateForDevice(int devid, int sw) {
4410         if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4411                 "getKeycodeStateForDevice()")) {
4412             throw new SecurityException("Requires READ_INPUT_STATE permission");
4413         }
4414         return mQueue.getKeycodeState(devid, sw);
4415     }
4416
4417     public int getTrackballKeycodeState(int sw) {
4418         if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4419                 "getTrackballKeycodeState()")) {
4420             throw new SecurityException("Requires READ_INPUT_STATE permission");
4421         }
4422         return mQueue.getTrackballKeycodeState(sw);
4423     }
4424
4425     public int getDPadKeycodeState(int sw) {
4426         if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4427                 "getDPadKeycodeState()")) {
4428             throw new SecurityException("Requires READ_INPUT_STATE permission");
4429         }
4430         return mQueue.getDPadKeycodeState(sw);
4431     }
4432
4433     public boolean hasKeys(int[] keycodes, boolean[] keyExists) {
4434         return KeyInputQueue.hasKeys(keycodes, keyExists);
4435     }
4436
4437     public void enableScreenAfterBoot() {
4438         synchronized(mWindowMap) {
4439             if (mSystemBooted) {
4440                 return;
4441             }
4442             mSystemBooted = true;
4443         }
4444
4445         performEnableScreen();
4446     }
4447
4448     public void enableScreenIfNeededLocked() {
4449         if (mDisplayEnabled) {
4450             return;
4451         }
4452         if (!mSystemBooted) {
4453             return;
4454         }
4455         mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN));
4456     }
4457
4458     public void performEnableScreen() {
4459         synchronized(mWindowMap) {
4460             if (mDisplayEnabled) {
4461                 return;
4462             }
4463             if (!mSystemBooted) {
4464                 return;
4465             }
4466
4467             // Don't enable the screen until all existing windows
4468             // have been drawn.
4469             final int N = mWindows.size();
4470             for (int i=0; i<N; i++) {
4471                 WindowState w = (WindowState)mWindows.get(i);
4472                 if (w.isVisibleLw() && !w.mObscured
4473                         && (w.mOrientationChanging || !w.isDrawnLw())) {
4474                     return;
4475                 }
4476             }
4477
4478             mDisplayEnabled = true;
4479             if (false) {
4480                 Slog.i(TAG, "ENABLING SCREEN!");
4481                 StringWriter sw = new StringWriter();
4482                 PrintWriter pw = new PrintWriter(sw);
4483                 this.dump(null, pw, null);
4484                 Slog.i(TAG, sw.toString());
4485             }
4486             try {
4487                 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
4488                 if (surfaceFlinger != null) {
4489                     //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
4490                     Parcel data = Parcel.obtain();
4491                     data.writeInterfaceToken("android.ui.ISurfaceComposer");
4492                     surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,
4493                                             data, null, 0);
4494                     data.recycle();
4495                 }
4496             } catch (RemoteException ex) {
4497                 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
4498             }
4499         }
4500
4501         mPolicy.enableScreenAfterBoot();
4502
4503         // Make sure the last requested orientation has been applied.
4504         setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false,
4505                 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
4506     }
4507
4508     public void setInTouchMode(boolean mode) {
4509         synchronized(mWindowMap) {
4510             mInTouchMode = mode;
4511         }
4512     }
4513
4514     public void setRotation(int rotation,
4515             boolean alwaysSendConfiguration, int animFlags) {
4516         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
4517                 "setRotation()")) {
4518             throw new SecurityException("Requires SET_ORIENTATION permission");
4519         }
4520
4521         setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags);
4522     }
4523
4524     public void setRotationUnchecked(int rotation,
4525             boolean alwaysSendConfiguration, int animFlags) {
4526         if(DEBUG_ORIENTATION) Slog.v(TAG,
4527                 "alwaysSendConfiguration set to "+alwaysSendConfiguration);
4528
4529         long origId = Binder.clearCallingIdentity();
4530         boolean changed;
4531         synchronized(mWindowMap) {
4532             changed = setRotationUncheckedLocked(rotation, animFlags);
4533         }
4534
4535         if (changed || alwaysSendConfiguration) {
4536             sendNewConfiguration();
4537         }
4538
4539         Binder.restoreCallingIdentity(origId);
4540     }
4541
4542     /**
4543      * Apply a new rotation to the screen, respecting the requests of
4544      * applications.  Use WindowManagerPolicy.USE_LAST_ROTATION to simply
4545      * re-evaluate the desired rotation.
4546      * 
4547      * Returns null if the rotation has been changed.  In this case YOU
4548      * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN.
4549      */
4550     public boolean setRotationUncheckedLocked(int rotation, int animFlags) {
4551         boolean changed;
4552         if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {
4553             rotation = mRequestedRotation;
4554         } else {
4555             mRequestedRotation = rotation;
4556             mLastRotationFlags = animFlags;
4557         }
4558         if (DEBUG_ORIENTATION) Slog.v(TAG, "Overwriting rotation value from " + rotation);
4559         rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation,
4560                 mRotation, mDisplayEnabled);
4561         if (DEBUG_ORIENTATION) Slog.v(TAG, "new rotation is set to " + rotation);
4562         changed = mDisplayEnabled && mRotation != rotation;
4563
4564         if (changed) {
4565             if (DEBUG_ORIENTATION) Slog.v(TAG,
4566                     "Rotation changed to " + rotation
4567                     + " from " + mRotation
4568                     + " (forceApp=" + mForcedAppOrientation
4569                     + ", req=" + mRequestedRotation + ")");
4570             mRotation = rotation;
4571             mWindowsFreezingScreen = true;
4572             mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
4573             mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
4574                     2000);
4575             mWaitingForConfig = true;
4576             mLayoutNeeded = true;
4577             startFreezingDisplayLocked();
4578             Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
4579             mQueue.setOrientation(rotation);
4580             if (mDisplayEnabled) {
4581                 Surface.setOrientation(0, rotation, animFlags);
4582             }
4583             for (int i=mWindows.size()-1; i>=0; i--) {
4584                 WindowState w = (WindowState)mWindows.get(i);
4585                 if (w.mSurface != null) {
4586                     w.mOrientationChanging = true;
4587                 }
4588             }
4589             for (int i=mRotationWatchers.size()-1; i>=0; i--) {
4590                 try {
4591                     mRotationWatchers.get(i).onRotationChanged(rotation);
4592                 } catch (RemoteException e) {
4593                 }
4594             }
4595         } //end if changed
4596
4597         return changed;
4598     }
4599
4600     public int getRotation() {
4601         return mRotation;
4602     }
4603
4604     public int watchRotation(IRotationWatcher watcher) {
4605         final IBinder watcherBinder = watcher.asBinder();
4606         IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
4607             public void binderDied() {
4608                 synchronized (mWindowMap) {
4609                     for (int i=0; i<mRotationWatchers.size(); i++) {
4610                         if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
4611                             IRotationWatcher removed = mRotationWatchers.remove(i);
4612                             if (removed != null) {
4613                                 removed.asBinder().unlinkToDeath(this, 0);
4614                             }
4615                             i--;
4616                         }
4617                     }
4618                 }
4619             }
4620         };
4621
4622         synchronized (mWindowMap) {
4623             try {
4624                 watcher.asBinder().linkToDeath(dr, 0);
4625                 mRotationWatchers.add(watcher);
4626             } catch (RemoteException e) {
4627                 // Client died, no cleanup needed.
4628             }
4629
4630             return mRotation;
4631         }
4632     }
4633
4634     /**
4635      * Starts the view server on the specified port.
4636      *
4637      * @param port The port to listener to.
4638      *
4639      * @return True if the server was successfully started, false otherwise.
4640      *
4641      * @see com.android.server.ViewServer
4642      * @see com.android.server.ViewServer#VIEW_SERVER_DEFAULT_PORT
4643      */
4644     public boolean startViewServer(int port) {
4645         if (isSystemSecure()) {
4646             return false;
4647         }
4648
4649         if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
4650             return false;
4651         }
4652
4653         if (port < 1024) {
4654             return false;
4655         }
4656
4657         if (mViewServer != null) {
4658             if (!mViewServer.isRunning()) {
4659                 try {
4660                     return mViewServer.start();
4661                 } catch (IOException e) {
4662                     Slog.w(TAG, "View server did not start");
4663                 }
4664             }
4665             return false;
4666         }
4667
4668         try {
4669             mViewServer = new ViewServer(this, port);
4670             return mViewServer.start();
4671         } catch (IOException e) {
4672             Slog.w(TAG, "View server did not start");
4673         }
4674         return false;
4675     }
4676
4677     private boolean isSystemSecure() {
4678         return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
4679                 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
4680     }
4681
4682     /**
4683      * Stops the view server if it exists.
4684      *
4685      * @return True if the server stopped, false if it wasn't started or
4686      *         couldn't be stopped.
4687      *
4688      * @see com.android.server.ViewServer
4689      */
4690     public boolean stopViewServer() {
4691         if (isSystemSecure()) {
4692             return false;
4693         }
4694
4695         if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
4696             return false;
4697         }
4698
4699         if (mViewServer != null) {
4700             return mViewServer.stop();
4701         }
4702         return false;
4703     }
4704
4705     /**
4706      * Indicates whether the view server is running.
4707      *
4708      * @return True if the server is running, false otherwise.
4709      *
4710      * @see com.android.server.ViewServer
4711      */
4712     public boolean isViewServerRunning() {
4713         if (isSystemSecure()) {
4714             return false;
4715         }
4716
4717         if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
4718             return false;
4719         }
4720
4721         return mViewServer != null && mViewServer.isRunning();
4722     }
4723
4724     /**
4725      * Lists all availble windows in the system. The listing is written in the
4726      * specified Socket's output stream with the following syntax:
4727      * windowHashCodeInHexadecimal windowName
4728      * Each line of the ouput represents a different window.
4729      *
4730      * @param client The remote client to send the listing to.
4731      * @return False if an error occured, true otherwise.
4732      */
4733     boolean viewServerListWindows(Socket client) {
4734         if (isSystemSecure()) {
4735             return false;
4736         }
4737
4738         boolean result = true;
4739
4740         Object[] windows;
4741         synchronized (mWindowMap) {
4742             windows = new Object[mWindows.size()];
4743             //noinspection unchecked
4744             windows = mWindows.toArray(windows);
4745         }
4746
4747         BufferedWriter out = null;
4748
4749         // Any uncaught exception will crash the system process
4750         try {
4751             OutputStream clientStream = client.getOutputStream();
4752             out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4753
4754             final int count = windows.length;
4755             for (int i = 0; i < count; i++) {
4756                 final WindowState w = (WindowState) windows[i];
4757                 out.write(Integer.toHexString(System.identityHashCode(w)));
4758                 out.write(' ');
4759                 out.append(w.mAttrs.getTitle());
4760                 out.write('\n');
4761             }
4762
4763             out.write("DONE.\n");
4764             out.flush();
4765         } catch (Exception e) {
4766             result = false;
4767         } finally {
4768             if (out != null) {
4769                 try {
4770                     out.close();
4771                 } catch (IOException e) {
4772                     result = false;
4773                 }
4774             }
4775         }
4776
4777         return result;
4778     }
4779
4780     /**
4781      * Sends a command to a target window. The result of the command, if any, will be
4782      * written in the output stream of the specified socket.
4783      *
4784      * The parameters must follow this syntax:
4785      * windowHashcode extra
4786      *
4787      * Where XX is the length in characeters of the windowTitle.
4788      *
4789      * The first parameter is the target window. The window with the specified hashcode
4790      * will be the target. If no target can be found, nothing happens. The extra parameters
4791      * will be delivered to the target window and as parameters to the command itself.
4792      *
4793      * @param client The remote client to sent the result, if any, to.
4794      * @param command The command to execute.
4795      * @param parameters The command parameters.
4796      *
4797      * @return True if the command was successfully delivered, false otherwise. This does
4798      *         not indicate whether the command itself was successful.
4799      */
4800     boolean viewServerWindowCommand(Socket client, String command, String parameters) {
4801         if (isSystemSecure()) {
4802             return false;
4803         }
4804
4805         boolean success = true;
4806         Parcel data = null;
4807         Parcel reply = null;
4808
4809         // Any uncaught exception will crash the system process
4810         try {
4811             // Find the hashcode of the window
4812             int index = parameters.indexOf(' ');
4813             if (index == -1) {
4814                 index = parameters.length();
4815             }
4816             final String code = parameters.substring(0, index);
4817             int hashCode = (int) Long.parseLong(code, 16);
4818
4819             // Extract the command's parameter after the window description
4820             if (index < parameters.length()) {
4821                 parameters = parameters.substring(index + 1);
4822             } else {
4823                 parameters = "";
4824             }
4825
4826             final WindowManagerService.WindowState window = findWindow(hashCode);
4827             if (window == null) {
4828                 return false;
4829             }
4830
4831             data = Parcel.obtain();
4832             data.writeInterfaceToken("android.view.IWindow");
4833             data.writeString(command);
4834             data.writeString(parameters);
4835             data.writeInt(1);
4836             ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
4837
4838             reply = Parcel.obtain();
4839
4840             final IBinder binder = window.mClient.asBinder();
4841             // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
4842             binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
4843
4844             reply.readException();
4845
4846         } catch (Exception e) {
4847             Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
4848             success = false;
4849         } finally {
4850             if (data != null) {
4851                 data.recycle();
4852             }
4853             if (reply != null) {
4854                 reply.recycle();
4855             }
4856         }
4857
4858         return success;
4859     }
4860
4861     private WindowState findWindow(int hashCode) {
4862         if (hashCode == -1) {
4863             return getFocusedWindow();
4864         }
4865
4866         synchronized (mWindowMap) {
4867             final ArrayList windows = mWindows;
4868             final int count = windows.size();
4869
4870             for (int i = 0; i < count; i++) {
4871                 WindowState w = (WindowState) windows.get(i);
4872                 if (System.identityHashCode(w) == hashCode) {
4873                     return w;
4874                 }
4875             }
4876         }
4877
4878         return null;
4879     }
4880
4881     /*
4882      * Instruct the Activity Manager to fetch the current configuration and broadcast
4883      * that to config-changed listeners if appropriate.
4884      */
4885     void sendNewConfiguration() {
4886         try {
4887             mActivityManager.updateConfiguration(null);
4888         } catch (RemoteException e) {
4889         }
4890     }
4891
4892     public Configuration computeNewConfiguration() {
4893         synchronized (mWindowMap) {
4894             return computeNewConfigurationLocked();
4895         }
4896     }
4897
4898     Configuration computeNewConfigurationLocked() {
4899         Configuration config = new Configuration();
4900         if (!computeNewConfigurationLocked(config)) {
4901             return null;
4902         }
4903         return config;
4904     }
4905
4906     boolean computeNewConfigurationLocked(Configuration config) {
4907         if (mDisplay == null) {
4908             return false;
4909         }
4910         mQueue.getInputConfiguration(config);
4911
4912         // Use the effective "visual" dimensions based on current rotation
4913         final boolean rotated = (mRotation == Surface.ROTATION_90
4914                 || mRotation == Surface.ROTATION_270);
4915         final int dw = rotated ? mInitialDisplayHeight : mInitialDisplayWidth;
4916         final int dh = rotated ? mInitialDisplayWidth : mInitialDisplayHeight;
4917
4918         int orientation = Configuration.ORIENTATION_SQUARE;
4919         if (dw < dh) {
4920             orientation = Configuration.ORIENTATION_PORTRAIT;
4921         } else if (dw > dh) {
4922             orientation = Configuration.ORIENTATION_LANDSCAPE;
4923         }
4924         config.orientation = orientation;
4925
4926         DisplayMetrics dm = new DisplayMetrics();
4927         mDisplay.getMetrics(dm);
4928         CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame);
4929
4930         if (mScreenLayout == Configuration.SCREENLAYOUT_SIZE_UNDEFINED) {
4931             // Note we only do this once because at this point we don't
4932             // expect the screen to change in this way at runtime, and want
4933             // to avoid all of this computation for every config change.
4934             int longSize = dw;
4935             int shortSize = dh;
4936             if (longSize < shortSize) {
4937                 int tmp = longSize;
4938                 longSize = shortSize;
4939                 shortSize = tmp;
4940             }
4941             longSize = (int)(longSize/dm.density);
4942             shortSize = (int)(shortSize/dm.density);
4943
4944             // These semi-magic numbers define our compatibility modes for
4945             // applications with different screens.  Don't change unless you
4946             // make sure to test lots and lots of apps!
4947             if (longSize < 470) {
4948                 // This is shorter than an HVGA normal density screen (which
4949                 // is 480 pixels on its long side).
4950                 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL
4951                         | Configuration.SCREENLAYOUT_LONG_NO;
4952             } else {
4953                 // Is this a large screen?
4954                 if (longSize > 640 && shortSize >= 480) {
4955                     // VGA or larger screens at medium density are the point
4956                     // at which we consider it to be a large screen.
4957                     mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
4958                 } else {
4959                     mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL;
4960
4961                     // If this screen is wider than normal HVGA, or taller
4962                     // than FWVGA, then for old apps we want to run in size
4963                     // compatibility mode.
4964                     if (shortSize > 321 || longSize > 570) {
4965                         mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
4966                     }
4967                 }
4968
4969                 // Is this a long screen?
4970                 if (((longSize*3)/5) >= (shortSize-1)) {
4971                     // Anything wider than WVGA (5:3) is considering to be long.
4972                     mScreenLayout |= Configuration.SCREENLAYOUT_LONG_YES;
4973                 } else {
4974                     mScreenLayout |= Configuration.SCREENLAYOUT_LONG_NO;
4975                 }
4976             }
4977         }
4978         config.screenLayout = mScreenLayout;
4979
4980         config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
4981         config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
4982         mPolicy.adjustConfigurationLw(config);
4983         return true;
4984     }
4985
4986     // -------------------------------------------------------------
4987     // Input Events and Focus Management
4988     // -------------------------------------------------------------
4989
4990     private final void wakeupIfNeeded(WindowState targetWin, int eventType) {
4991         long curTime = SystemClock.uptimeMillis();
4992
4993         if (eventType == TOUCH_EVENT || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) {
4994             if (mLastTouchEventType == eventType &&
4995                     (curTime - mLastUserActivityCallTime) < MIN_TIME_BETWEEN_USERACTIVITIES) {
4996                 return;
4997             }
4998             mLastUserActivityCallTime = curTime;
4999             mLastTouchEventType = eventType;
5000         }
5001
5002         if (targetWin == null
5003                 || targetWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
5004             mPowerManager.userActivity(curTime, false, eventType, false);
5005         }
5006     }
5007
5008     // tells if it's a cheek event or not -- this function is stateful
5009     private static final int EVENT_NONE = 0;
5010     private static final int EVENT_UNKNOWN = 0;
5011     private static final int EVENT_CHEEK = 0;
5012     private static final int EVENT_IGNORE_DURATION = 300; // ms
5013     private static final float CHEEK_THRESHOLD = 0.6f;
5014     private int mEventState = EVENT_NONE;
5015     private float mEventSize;
5016
5017     private int eventType(MotionEvent ev) {
5018         float size = ev.getSize();
5019         switch (ev.getAction()) {
5020         case MotionEvent.ACTION_DOWN:
5021             mEventSize = size;
5022             return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_EVENT;
5023         case MotionEvent.ACTION_UP:
5024             if (size > mEventSize) mEventSize = size;
5025             return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_UP_EVENT;
5026         case MotionEvent.ACTION_MOVE:
5027             final int N = ev.getHistorySize();
5028             if (size > mEventSize) mEventSize = size;
5029             if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
5030             for (int i=0; i<N; i++) {
5031                 size = ev.getHistoricalSize(i);
5032                 if (size > mEventSize) mEventSize = size;
5033                 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
5034             }
5035             if (ev.getEventTime() < ev.getDownTime() + EVENT_IGNORE_DURATION) {
5036                 return TOUCH_EVENT;
5037             } else {
5038                 return LONG_TOUCH_EVENT;
5039             }
5040         default:
5041             // not good
5042             return OTHER_EVENT;
5043         }
5044     }
5045
5046     /**
5047      * @return Returns true if event was dispatched, false if it was dropped for any reason
5048      */
5049     private int dispatchPointer(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
5050         if (DEBUG_INPUT || WindowManagerPolicy.WATCH_POINTER) Slog.v(TAG,
5051                 "dispatchPointer " + ev);
5052
5053         if (MEASURE_LATENCY) {
5054             lt.sample("3 Wait for last dispatch ", System.nanoTime() - qev.whenNano);
5055         }
5056
5057         Object targetObj = mKeyWaiter.waitForNextEventTarget(null, qev,
5058                 ev, true, false, pid, uid);
5059
5060         if (MEASURE_LATENCY) {
5061             lt.sample("3 Last dispatch finished ", System.nanoTime() - qev.whenNano);
5062         }
5063
5064         int action = ev.getAction();
5065
5066         if (action == MotionEvent.ACTION_UP) {
5067             // let go of our target
5068             mKeyWaiter.mMotionTarget = null;
5069             mPowerManager.logPointerUpEvent();
5070         } else if (action == MotionEvent.ACTION_DOWN) {
5071             mPowerManager.logPointerDownEvent();
5072         }
5073
5074         if (targetObj == null) {
5075             // In this case we are either dropping the event, or have received
5076             // a move or up without a down.  It is common to receive move
5077             // events in such a way, since this means the user is moving the
5078             // pointer without actually pressing down.  All other cases should
5079             // be atypical, so let's log them.
5080             if (action != MotionEvent.ACTION_MOVE) {
5081                 Slog.w(TAG, "No window to dispatch pointer action " + ev.getAction());
5082             }
5083             synchronized (mWindowMap) {
5084                 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true);
5085             }
5086             if (qev != null) {
5087                 mQueue.recycleEvent(qev);
5088             }
5089             ev.recycle();
5090             return INJECT_FAILED;
5091         }
5092         if (targetObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
5093             synchronized (mWindowMap) {
5094                 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true);
5095             }
5096             if (qev != null) {
5097                 mQueue.recycleEvent(qev);
5098             }
5099             ev.recycle();
5100             return INJECT_SUCCEEDED;
5101         }
5102
5103         WindowState target = (WindowState)targetObj;
5104
5105         final long eventTime = ev.getEventTime();
5106         final long eventTimeNano = ev.getEventTimeNano();
5107
5108         //Slog.i(TAG, "Sending " + ev + " to " + target);
5109
5110         if (uid != 0 && uid != target.mSession.mUid) {
5111             if (mContext.checkPermission(
5112                     android.Manifest.permission.INJECT_EVENTS, pid, uid)
5113                     != PackageManager.PERMISSION_GRANTED) {
5114                 Slog.w(TAG, "Permission denied: injecting pointer event from pid "
5115                         + pid + " uid " + uid + " to window " + target
5116                         + " owned by uid " + target.mSession.mUid);
5117                 if (qev != null) {
5118                     mQueue.recycleEvent(qev);
5119                 }
5120                 ev.recycle();
5121                 return INJECT_NO_PERMISSION;
5122             }
5123         }
5124
5125         if (MEASURE_LATENCY) {
5126             lt.sample("4 in dispatchPointer     ", System.nanoTime() - eventTimeNano);
5127         }
5128
5129         if ((target.mAttrs.flags &
5130                         WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) != 0) {
5131             //target wants to ignore fat touch events
5132             boolean cheekPress = mPolicy.isCheekPressedAgainstScreen(ev);
5133             //explicit flag to return without processing event further
5134             boolean returnFlag = false;
5135             if((action == MotionEvent.ACTION_DOWN)) {
5136                 mFatTouch = false;
5137                 if(cheekPress) {
5138                     mFatTouch = true;
5139                     returnFlag = true;
5140                 }
5141             } else {
5142                 if(action == MotionEvent.ACTION_UP) {
5143                     if(mFatTouch) {
5144                         //earlier even was invalid doesnt matter if current up is cheekpress or not
5145                         mFatTouch = false;
5146                         returnFlag = true;
5147                     } else if(cheekPress) {
5148                         //cancel the earlier event
5149                         ev.setAction(MotionEvent.ACTION_CANCEL);
5150                         action = MotionEvent.ACTION_CANCEL;
5151                     }
5152                 } else if(action == MotionEvent.ACTION_MOVE) {
5153                     if(mFatTouch) {
5154                         //two cases here
5155                         //an invalid down followed by 0 or moves(valid or invalid)
5156                         //a valid down,  invalid move, more moves. want to ignore till up
5157                         returnFlag = true;
5158                     } else if(cheekPress) {
5159                         //valid down followed by invalid moves
5160                         //an invalid move have to cancel earlier action
5161                         ev.setAction(MotionEvent.ACTION_CANCEL);
5162                         action = MotionEvent.ACTION_CANCEL;
5163                         if (DEBUG_INPUT) Slog.v(TAG, "Sending cancel for invalid ACTION_MOVE");
5164                         //note that the subsequent invalid moves will not get here
5165                         mFatTouch = true;
5166                     }
5167                 }
5168             } //else if action
5169             if(returnFlag) {
5170                 //recycle que, ev
5171                 if (qev != null) {
5172                     mQueue.recycleEvent(qev);
5173                 }
5174                 ev.recycle();
5175                 return INJECT_FAILED;
5176             }
5177         } //end if target
5178
5179         // Enable this for testing the "right" value
5180         if (false && action == MotionEvent.ACTION_DOWN) {
5181             int max_events_per_sec = 35;
5182             try {
5183                 max_events_per_sec = Integer.parseInt(SystemProperties
5184                         .get("windowsmgr.max_events_per_sec"));
5185                 if (max_events_per_sec < 1) {
5186                     max_events_per_sec = 35;
5187                 }
5188             } catch (NumberFormatException e) {
5189             }
5190             mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
5191         }
5192
5193         /*
5194          * Throttle events to minimize CPU usage when there's a flood of events
5195          * e.g. constant contact with the screen
5196          */
5197         if (action == MotionEvent.ACTION_MOVE) {
5198             long nextEventTime = mLastTouchEventTime + mMinWaitTimeBetweenTouchEvents;
5199             long now = SystemClock.uptimeMillis();
5200             if (now < nextEventTime) {
5201                 try {
5202                     Thread.sleep(nextEventTime - now);
5203                 } catch (InterruptedException e) {
5204                 }
5205                 mLastTouchEventTime = nextEventTime;
5206             } else {
5207                 mLastTouchEventTime = now;
5208             }
5209         }
5210
5211         if (MEASURE_LATENCY) {
5212             lt.sample("5 in dispatchPointer     ", System.nanoTime() - eventTimeNano);
5213         }
5214
5215         synchronized(mWindowMap) {
5216             if (!target.isVisibleLw()) {
5217                 // During this motion dispatch, the target window has become
5218                 // invisible.
5219                 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), false);
5220                 if (qev != null) {
5221                     mQueue.recycleEvent(qev);
5222                 }
5223                 ev.recycle();
5224                 return INJECT_SUCCEEDED;
5225             }
5226
5227             if (qev != null && action == MotionEvent.ACTION_MOVE) {
5228                 mKeyWaiter.bindTargetWindowLocked(target,
5229                         KeyWaiter.RETURN_PENDING_POINTER, qev);
5230                 ev = null;
5231             } else {
5232                 if (action == MotionEvent.ACTION_DOWN) {
5233                     WindowState out = mKeyWaiter.mOutsideTouchTargets;
5234                     if (out != null) {
5235                         MotionEvent oev = MotionEvent.obtain(ev);
5236                         oev.setAction(MotionEvent.ACTION_OUTSIDE);
5237                         do {
5238                             final Rect frame = out.mFrame;
5239                             oev.offsetLocation(-(float)frame.left, -(float)frame.top);
5240                             try {
5241                                 out.mClient.dispatchPointer(oev, eventTime, false);
5242                             } catch (android.os.RemoteException e) {
5243                                 Slog.i(TAG, "WINDOW DIED during outside motion dispatch: " + out);
5244                             }
5245                             oev.offsetLocation((float)frame.left, (float)frame.top);
5246                             out = out.mNextOutsideTouch;
5247                         } while (out != null);
5248                         mKeyWaiter.mOutsideTouchTargets = null;
5249                     }
5250                 }
5251
5252                 dispatchPointerElsewhereLocked(target, null, ev, ev.getEventTime(), false);
5253
5254                 final Rect frame = target.mFrame;
5255                 ev.offsetLocation(-(float)frame.left, -(float)frame.top);
5256                 mKeyWaiter.bindTargetWindowLocked(target);
5257             }
5258         }
5259
5260         // finally offset the event to the target's coordinate system and
5261         // dispatch the event.
5262         try {
5263             if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) {
5264                 Slog.v(TAG, "Delivering pointer " + qev + " to " + target);
5265             }
5266
5267             if (MEASURE_LATENCY) {
5268                 lt.sample("6 before svr->client ipc ", System.nanoTime() - eventTimeNano);
5269             }
5270
5271             target.mClient.dispatchPointer(ev, eventTime, true);
5272
5273             if (MEASURE_LATENCY) {
5274                 lt.sample("7 after  svr->client ipc ", System.nanoTime() - eventTimeNano);
5275             }
5276             return INJECT_SUCCEEDED;
5277         } catch (android.os.RemoteException e) {
5278             Slog.i(TAG, "WINDOW DIED during motion dispatch: " + target);
5279             mKeyWaiter.mMotionTarget = null;
5280             try {
5281                 removeWindow(target.mSession, target.mClient);
5282             } catch (java.util.NoSuchElementException ex) {
5283                 // This will happen if the window has already been
5284                 // removed.
5285             }
5286         }
5287         return INJECT_FAILED;
5288     }
5289
5290     /**
5291      * @return Returns true if event was dispatched, false if it was dropped for any reason
5292      */
5293     private int dispatchTrackball(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
5294         if (DEBUG_INPUT) Slog.v(
5295                 TAG, "dispatchTrackball [" + ev.getAction() +"] <" + ev.getX() + ", " + ev.getY() + ">");
5296
5297         Object focusObj = mKeyWaiter.waitForNextEventTarget(null, qev,
5298                 ev, false, false, pid, uid);
5299         if (focusObj == null) {
5300             Slog.w(TAG, "No focus window, dropping trackball: " + ev);
5301             if (qev != null) {
5302                 mQueue.recycleEvent(qev);
5303             }
5304             ev.recycle();
5305             return INJECT_FAILED;
5306         }
5307         if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
5308             if (qev != null) {
5309                 mQueue.recycleEvent(qev);
5310             }
5311             ev.recycle();
5312             return INJECT_SUCCEEDED;
5313         }
5314
5315         WindowState focus = (WindowState)focusObj;
5316
5317         if (uid != 0 && uid != focus.mSession.mUid) {
5318             if (mContext.checkPermission(
5319                     android.Manifest.permission.INJECT_EVENTS, pid, uid)
5320                     != PackageManager.PERMISSION_GRANTED) {
5321                 Slog.w(TAG, "Permission denied: injecting key event from pid "
5322                         + pid + " uid " + uid + " to window " + focus
5323                         + " owned by uid " + focus.mSession.mUid);
5324                 if (qev != null) {
5325                     mQueue.recycleEvent(qev);
5326                 }
5327                 ev.recycle();
5328                 return INJECT_NO_PERMISSION;
5329             }
5330         }
5331
5332         final long eventTime = ev.getEventTime();
5333
5334         synchronized(mWindowMap) {
5335             if (qev != null && ev.getAction() == MotionEvent.ACTION_MOVE) {
5336                 mKeyWaiter.bindTargetWindowLocked(focus,
5337                         KeyWaiter.RETURN_PENDING_TRACKBALL, qev);
5338                 // We don't deliver movement events to the client, we hold
5339                 // them and wait for them to call back.
5340                 ev = null;
5341             } else {
5342                 mKeyWaiter.bindTargetWindowLocked(focus);
5343             }
5344         }
5345
5346         try {
5347             focus.mClient.dispatchTrackball(ev, eventTime, true);
5348             return INJECT_SUCCEEDED;
5349         } catch (android.os.RemoteException e) {
5350             Slog.i(TAG, "WINDOW DIED during key dispatch: " + focus);
5351             try {
5352                 removeWindow(focus.mSession, focus.mClient);
5353             } catch (java.util.NoSuchElementException ex) {
5354                 // This will happen if the window has already been
5355                 // removed.
5356             }
5357         }
5358
5359         return INJECT_FAILED;
5360     }
5361
5362     /**
5363      * @return Returns true if event was dispatched, false if it was dropped for any reason
5364      */
5365     private int dispatchKey(KeyEvent event, int pid, int uid) {
5366         if (DEBUG_INPUT) Slog.v(TAG, "Dispatch key: " + event);
5367
5368         Object focusObj = mKeyWaiter.waitForNextEventTarget(event, null,
5369                 null, false, false, pid, uid);
5370         if (focusObj == null) {
5371             Slog.w(TAG, "No focus window, dropping: " + event);
5372             return INJECT_FAILED;
5373         }
5374         if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
5375             return INJECT_SUCCEEDED;
5376         }
5377
5378         // Okay we have finished waiting for the last event to be processed.
5379         // First off, if this is a repeat event, check to see if there is
5380         // a corresponding up event in the queue.  If there is, we will
5381         // just drop the repeat, because it makes no sense to repeat after
5382         // the user has released a key.  (This is especially important for
5383         // long presses.)
5384         if (event.getRepeatCount() > 0 && mQueue.hasKeyUpEvent(event)) {
5385             return INJECT_SUCCEEDED;
5386         }
5387
5388         WindowState focus = (WindowState)focusObj;
5389
5390         if (DEBUG_INPUT) Slog.v(
5391             TAG, "Dispatching to " + focus + ": " + event);
5392
5393         if (uid != 0 && uid != focus.mSession.mUid) {
5394             if (mContext.checkPermission(
5395                     android.Manifest.permission.INJECT_EVENTS, pid, uid)
5396                     != PackageManager.PERMISSION_GRANTED) {
5397                 Slog.w(TAG, "Permission denied: injecting key event from pid "
5398                         + pid + " uid " + uid + " to window " + focus
5399                         + " owned by uid " + focus.mSession.mUid);
5400                 return INJECT_NO_PERMISSION;
5401             }
5402         }
5403
5404         synchronized(mWindowMap) {
5405             mKeyWaiter.bindTargetWindowLocked(focus);
5406         }
5407
5408         // NOSHIP extra state logging
5409         mKeyWaiter.recordDispatchState(event, focus);
5410         // END NOSHIP
5411
5412         try {
5413             if (DEBUG_INPUT || DEBUG_FOCUS) {
5414                 Slog.v(TAG, "Delivering key " + event.getKeyCode()
5415                         + " to " + focus);
5416             }
5417             focus.mClient.dispatchKey(event);
5418             return INJECT_SUCCEEDED;
5419         } catch (android.os.RemoteException e) {
5420             Slog.i(TAG, "WINDOW DIED during key dispatch: " + focus);
5421             try {
5422                 removeWindow(focus.mSession, focus.mClient);
5423             } catch (java.util.NoSuchElementException ex) {
5424                 // This will happen if the window has already been
5425                 // removed.
5426             }
5427         }
5428
5429         return INJECT_FAILED;
5430     }
5431
5432     public void pauseKeyDispatching(IBinder _token) {
5433         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5434                 "pauseKeyDispatching()")) {
5435             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
5436         }
5437
5438         synchronized (mWindowMap) {
5439             WindowToken token = mTokenMap.get(_token);
5440             if (token != null) {
5441                 mKeyWaiter.pauseDispatchingLocked(token);
5442             }
5443         }
5444     }
5445
5446     public void resumeKeyDispatching(IBinder _token) {
5447         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5448                 "resumeKeyDispatching()")) {
5449             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
5450         }
5451
5452         synchronized (mWindowMap) {
5453             WindowToken token = mTokenMap.get(_token);
5454             if (token != null) {
5455                 mKeyWaiter.resumeDispatchingLocked(token);
5456             }
5457         }
5458     }
5459
5460     public void setEventDispatching(boolean enabled) {
5461         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5462                 "resumeKeyDispatching()")) {
5463             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
5464         }
5465
5466         synchronized (mWindowMap) {
5467             mKeyWaiter.setEventDispatchingLocked(enabled);
5468         }
5469     }
5470
5471     /**
5472      * Injects a keystroke event into the UI.
5473      *
5474      * @param ev A motion event describing the keystroke action.  (Be sure to use
5475      * {@link SystemClock#uptimeMillis()} as the timebase.)
5476      * @param sync If true, wait for the event to be completed before returning to the caller.
5477      * @return Returns true if event was dispatched, false if it was dropped for any reason
5478      */
5479     public boolean injectKeyEvent(KeyEvent ev, boolean sync) {
5480         long downTime = ev.getDownTime();
5481         long eventTime = ev.getEventTime();
5482
5483         int action = ev.getAction();
5484         int code = ev.getKeyCode();
5485         int repeatCount = ev.getRepeatCount();
5486         int metaState = ev.getMetaState();
5487         int deviceId = ev.getDeviceId();
5488         int scancode = ev.getScanCode();
5489
5490         if (eventTime == 0) eventTime = SystemClock.uptimeMillis();
5491         if (downTime == 0) downTime = eventTime;
5492
5493         KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
5494                 deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM);
5495
5496         final int pid = Binder.getCallingPid();
5497         final int uid = Binder.getCallingUid();
5498         final long ident = Binder.clearCallingIdentity();
5499         final int result = dispatchKey(newEvent, pid, uid);
5500         if (sync) {
5501             mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
5502         }
5503         Binder.restoreCallingIdentity(ident);
5504         switch (result) {
5505             case INJECT_NO_PERMISSION:
5506                 throw new SecurityException(
5507                         "Injecting to another application requires INJECT_EVENTS permission");
5508             case INJECT_SUCCEEDED:
5509                 return true;
5510         }
5511         return false;
5512     }
5513
5514     /**
5515      * Inject a pointer (touch) event into the UI.
5516      *
5517      * @param ev A motion event describing the pointer (touch) action.  (As noted in
5518      * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
5519      * {@link SystemClock#uptimeMillis()} as the timebase.)
5520      * @param sync If true, wait for the event to be completed before returning to the caller.
5521      * @return Returns true if event was dispatched, false if it was dropped for any reason
5522      */
5523     public boolean injectPointerEvent(MotionEvent ev, boolean sync) {
5524         final int pid = Binder.getCallingPid();
5525         final int uid = Binder.getCallingUid();
5526         final long ident = Binder.clearCallingIdentity();
5527         final int result = dispatchPointer(null, ev, pid, uid);
5528         if (sync) {
5529             mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
5530         }
5531         Binder.restoreCallingIdentity(ident);
5532         switch (result) {
5533             case INJECT_NO_PERMISSION:
5534                 throw new SecurityException(
5535                         "Injecting to another application requires INJECT_EVENTS permission");
5536             case INJECT_SUCCEEDED:
5537                 return true;
5538         }
5539         return false;
5540     }
5541
5542     /**
5543      * Inject a trackball (navigation device) event into the UI.
5544      *
5545      * @param ev A motion event describing the trackball action.  (As noted in
5546      * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
5547      * {@link SystemClock#uptimeMillis()} as the timebase.)
5548      * @param sync If true, wait for the event to be completed before returning to the caller.
5549      * @return Returns true if event was dispatched, false if it was dropped for any reason
5550      */
5551     public boolean injectTrackballEvent(MotionEvent ev, boolean sync) {
5552         final int pid = Binder.getCallingPid();
5553         final int uid = Binder.getCallingUid();
5554         final long ident = Binder.clearCallingIdentity();
5555         final int result = dispatchTrackball(null, ev, pid, uid);
5556         if (sync) {
5557             mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
5558         }
5559         Binder.restoreCallingIdentity(ident);
5560         switch (result) {
5561             case INJECT_NO_PERMISSION:
5562                 throw new SecurityException(
5563                         "Injecting to another application requires INJECT_EVENTS permission");
5564             case INJECT_SUCCEEDED:
5565                 return true;
5566         }
5567         return false;
5568     }
5569
5570     private WindowState getFocusedWindow() {
5571         synchronized (mWindowMap) {
5572             return getFocusedWindowLocked();
5573         }
5574     }
5575
5576     private WindowState getFocusedWindowLocked() {
5577         return mCurrentFocus;
5578     }
5579
5580     /**
5581      * This class holds the state for dispatching key events.  This state
5582      * is protected by the KeyWaiter instance, NOT by the window lock.  You
5583      * can be holding the main window lock while acquire the KeyWaiter lock,
5584      * but not the other way around.
5585      */
5586     final class KeyWaiter {
5587         // NOSHIP debugging
5588         public class DispatchState {
5589             private KeyEvent event;
5590             private WindowState focus;
5591             private long time;
5592             private WindowState lastWin;
5593             private IBinder lastBinder;
5594             private boolean finished;
5595             private boolean gotFirstWindow;
5596             private boolean eventDispatching;
5597             private long timeToSwitch;
5598             private boolean wasFrozen;
5599             private boolean focusPaused;
5600             private WindowState curFocus;
5601
5602             DispatchState(KeyEvent theEvent, WindowState theFocus) {
5603                 focus = theFocus;
5604                 event = theEvent;
5605                 time = System.currentTimeMillis();
5606                 // snapshot KeyWaiter state
5607                 lastWin = mLastWin;
5608                 lastBinder = mLastBinder;
5609                 finished = mFinished;
5610                 gotFirstWindow = mGotFirstWindow;
5611                 eventDispatching = mEventDispatching;
5612                 timeToSwitch = mTimeToSwitch;
5613                 wasFrozen = mWasFrozen;
5614                 curFocus = mCurrentFocus;
5615                 // cache the paused state at ctor time as well
5616                 if (theFocus == null || theFocus.mToken == null) {
5617                     focusPaused = false;
5618                 } else {
5619                     focusPaused = theFocus.mToken.paused;
5620                 }
5621             }
5622
5623             public String toString() {
5624                 return "{{" + event + " to " + focus + " @ " + time
5625                         + " lw=" + lastWin + " lb=" + lastBinder
5626                         + " fin=" + finished + " gfw=" + gotFirstWindow
5627                         + " ed=" + eventDispatching + " tts=" + timeToSwitch
5628                         + " wf=" + wasFrozen + " fp=" + focusPaused
5629                         + " mcf=" + curFocus + "}}";
5630             }
5631         };
5632         private DispatchState mDispatchState = null;
5633         public void recordDispatchState(KeyEvent theEvent, WindowState theFocus) {
5634             mDispatchState = new DispatchState(theEvent, theFocus);
5635         }
5636         // END NOSHIP
5637
5638         public static final int RETURN_NOTHING = 0;
5639         public static final int RETURN_PENDING_POINTER = 1;
5640         public static final int RETURN_PENDING_TRACKBALL = 2;
5641
5642         final Object SKIP_TARGET_TOKEN = new Object();
5643         final Object CONSUMED_EVENT_TOKEN = new Object();
5644
5645         private WindowState mLastWin = null;
5646         private IBinder mLastBinder = null;
5647         private boolean mFinished = true;
5648         private boolean mGotFirstWindow = false;
5649         private boolean mEventDispatching = true;
5650         private long mTimeToSwitch = 0;
5651         /* package */ boolean mWasFrozen = false;
5652
5653         // Target of Motion events
5654         WindowState mMotionTarget;
5655
5656         // Windows above the target who would like to receive an "outside"
5657         // touch event for any down events outside of them.
5658         WindowState mOutsideTouchTargets;
5659
5660         /**
5661          * Wait for the last event dispatch to complete, then find the next
5662          * target that should receive the given event and wait for that one
5663          * to be ready to receive it.
5664          */
5665         Object waitForNextEventTarget(KeyEvent nextKey, QueuedEvent qev,
5666                 MotionEvent nextMotion, boolean isPointerEvent,
5667                 boolean failIfTimeout, int callingPid, int callingUid) {
5668             long startTime = SystemClock.uptimeMillis();
5669             long keyDispatchingTimeout = 5 * 1000;
5670             long waitedFor = 0;
5671
5672             while (true) {
5673                 // Figure out which window we care about.  It is either the
5674                 // last window we are waiting to have process the event or,
5675                 // if none, then the next window we think the event should go
5676                 // to.  Note: we retrieve mLastWin outside of the lock, so
5677                 // it may change before we lock.  Thus we must check it again.
5678                 WindowState targetWin = mLastWin;
5679                 boolean targetIsNew = targetWin == null;
5680                 if (DEBUG_INPUT) Slog.v(
5681                         TAG, "waitForLastKey: mFinished=" + mFinished +
5682                         ", mLastWin=" + mLastWin);
5683                 if (targetIsNew) {
5684                     Object target = findTargetWindow(nextKey, qev, nextMotion,
5685                             isPointerEvent, callingPid, callingUid);
5686                     if (target == SKIP_TARGET_TOKEN) {
5687                         // The user has pressed a special key, and we are
5688                         // dropping all pending events before it.
5689                         if (DEBUG_INPUT) Slog.v(TAG, "Skipping: " + nextKey
5690                                 + " " + nextMotion);
5691                         return null;
5692                     }
5693                     if (target == CONSUMED_EVENT_TOKEN) {
5694                         if (DEBUG_INPUT) Slog.v(TAG, "Consumed: " + nextKey
5695                                 + " " + nextMotion);
5696                         return target;
5697                     }
5698                     targetWin = (WindowState)target;
5699                 }
5700
5701                 AppWindowToken targetApp = null;
5702
5703                 // Now: is it okay to send the next event to this window?
5704                 synchronized (this) {
5705                     // First: did we come here based on the last window not
5706                     // being null, but it changed by the time we got here?
5707                     // If so, try again.
5708                     if (!targetIsNew && mLastWin == null) {
5709                         continue;
5710                     }
5711
5712                     // We never dispatch events if not finished with the
5713                     // last one, or the display is frozen.
5714                     if (mFinished && !mDisplayFrozen) {
5715                         // If event dispatching is disabled, then we
5716                         // just consume the events.
5717                         if (!mEventDispatching) {
5718                             if (DEBUG_INPUT) Slog.v(TAG,
5719                                     "Skipping event; dispatching disabled: "
5720                                     + nextKey + " " + nextMotion);
5721                             return null;
5722                         }
5723                         if (targetWin != null) {
5724                             // If this is a new target, and that target is not
5725                             // paused or unresponsive, then all looks good to
5726                             // handle the event.
5727                             if (targetIsNew && !targetWin.mToken.paused) {
5728                                 return targetWin;
5729                             }
5730
5731                         // If we didn't find a target window, and there is no
5732                         // focused app window, then just eat the events.
5733                         } else if (mFocusedApp == null) {
5734                             if (DEBUG_INPUT) Slog.v(TAG,
5735                                     "Skipping event; no focused app: "
5736                                     + nextKey + " " + nextMotion);
5737                             return null;
5738                         }
5739                     }
5740
5741                     if (DEBUG_INPUT) Slog.v(
5742                             TAG, "Waiting for last key in " + mLastBinder
5743                             + " target=" + targetWin
5744                             + " mFinished=" + mFinished
5745                             + " mDisplayFrozen=" + mDisplayFrozen
5746                             + " targetIsNew=" + targetIsNew
5747                             + " paused="
5748                             + (targetWin != null ? targetWin.mToken.paused : false)
5749                             + " mFocusedApp=" + mFocusedApp
5750                             + " mCurrentFocus=" + mCurrentFocus);
5751
5752                     targetApp = targetWin != null
5753                             ? targetWin.mAppToken : mFocusedApp;
5754
5755                     long curTimeout = keyDispatchingTimeout;
5756                     if (mTimeToSwitch != 0) {
5757                         long now = SystemClock.uptimeMillis();
5758                         if (mTimeToSwitch <= now) {
5759                             // If an app switch key has been pressed, and we have
5760                             // waited too long for the current app to finish
5761                             // processing keys, then wait no more!
5762                             doFinishedKeyLocked(false);
5763                             continue;
5764                         }
5765                         long switchTimeout = mTimeToSwitch - now;
5766                         if (curTimeout > switchTimeout) {
5767                             curTimeout = switchTimeout;
5768                         }
5769                     }
5770
5771                     try {
5772                         // after that continue
5773                         // processing keys, so we don't get stuck.
5774                         if (DEBUG_INPUT) Slog.v(
5775                                 TAG, "Waiting for key dispatch: " + curTimeout);
5776                         wait(curTimeout);
5777                         if (DEBUG_INPUT) Slog.v(TAG, "Finished waiting @"
5778                                 + SystemClock.uptimeMillis() + " startTime="
5779                                 + startTime + " switchTime=" + mTimeToSwitch
5780                                 + " target=" + targetWin + " mLW=" + mLastWin
5781                                 + " mLB=" + mLastBinder + " fin=" + mFinished
5782                                 + " mCurrentFocus=" + mCurrentFocus);
5783                     } catch (InterruptedException e) {
5784                     }
5785                 }
5786
5787                 // If we were frozen during configuration change, restart the
5788                 // timeout checks from now; otherwise look at whether we timed
5789                 // out before awakening.
5790                 if (mWasFrozen) {
5791                     waitedFor = 0;
5792                     mWasFrozen = false;
5793                 } else {
5794                     waitedFor = SystemClock.uptimeMillis() - startTime;
5795                 }
5796
5797                 if (waitedFor >= keyDispatchingTimeout && mTimeToSwitch == 0) {
5798                     IApplicationToken at = null;
5799                     synchronized (this) {
5800                         Slog.w(TAG, "Key dispatching timed out sending to " +
5801                               (targetWin != null ? targetWin.mAttrs.getTitle()
5802                               : "<null>: no window ready for key dispatch"));
5803                         // NOSHIP debugging
5804                         Slog.w(TAG, "Previous dispatch state: " + mDispatchState);
5805                         Slog.w(TAG, "Current dispatch state: " +
5806                                 new DispatchState(nextKey, targetWin));
5807                         // END NOSHIP
5808                         //dump();
5809                         if (targetWin != null) {
5810                             at = targetWin.getAppToken();
5811                         } else if (targetApp != null) {
5812                             at = targetApp.appToken;
5813                         }
5814                     }
5815
5816                     boolean abort = true;
5817                     if (at != null) {
5818                         try {
5819                             long timeout = at.getKeyDispatchingTimeout();
5820                             if (timeout > waitedFor) {
5821                                 // we did not wait the proper amount of time for this application.
5822                                 // set the timeout to be the real timeout and wait again.
5823                                 keyDispatchingTimeout = timeout - waitedFor;
5824                                 continue;
5825                             } else {
5826                                 abort = at.keyDispatchingTimedOut();
5827                             }
5828                         } catch (RemoteException ex) {
5829                         }
5830                     }
5831
5832                     synchronized (this) {
5833                         if (abort && (mLastWin == targetWin || targetWin == null)) {
5834                             mFinished = true;
5835                             if (mLastWin != null) {
5836                                 if (DEBUG_INPUT) Slog.v(TAG,
5837                                         "Window " + mLastWin +
5838                                         " timed out on key input");
5839                                 if (mLastWin.mToken.paused) {
5840                                     Slog.w(TAG, "Un-pausing dispatching to this window");
5841                                     mLastWin.mToken.paused = false;
5842                                 }
5843                             }
5844                             if (mMotionTarget == targetWin) {
5845                                 mMotionTarget = null;
5846                             }
5847                             mLastWin = null;
5848                             mLastBinder = null;
5849                             if (failIfTimeout || targetWin == null) {
5850                                 return null;
5851                             }
5852                         } else {
5853                             Slog.w(TAG, "Continuing to wait for key to be dispatched");
5854                             startTime = SystemClock.uptimeMillis();
5855                         }
5856                     }
5857                 }
5858             }
5859         }
5860
5861         Object findTargetWindow(KeyEvent nextKey, QueuedEvent qev,
5862                 MotionEvent nextMotion, boolean isPointerEvent,
5863                 int callingPid, int callingUid) {
5864             mOutsideTouchTargets = null;
5865
5866             if (nextKey != null) {
5867                 // Find the target window for a normal key event.
5868                 final int keycode = nextKey.getKeyCode();
5869                 final int repeatCount = nextKey.getRepeatCount();
5870                 final boolean down = nextKey.getAction() != KeyEvent.ACTION_UP;
5871                 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(keycode);
5872
5873                 if (!dispatch) {
5874                     if (callingUid == 0 ||
5875                             mContext.checkPermission(
5876                                     android.Manifest.permission.INJECT_EVENTS,
5877                                     callingPid, callingUid)
5878                                     == PackageManager.PERMISSION_GRANTED) {
5879                         mPolicy.interceptKeyTi(null, keycode,
5880                                 nextKey.getMetaState(), down, repeatCount,
5881                                 nextKey.getFlags());
5882                     }
5883                     Slog.w(TAG, "Event timeout during app switch: dropping "
5884                             + nextKey);
5885                     return SKIP_TARGET_TOKEN;
5886                 }
5887
5888                 // System.out.println("##### [" + SystemClock.uptimeMillis() + "] WindowManagerService.dispatchKey(" + keycode + ", " + down + ", " + repeatCount + ")");
5889
5890                 WindowState focus = null;
5891                 synchronized(mWindowMap) {
5892                     focus = getFocusedWindowLocked();
5893                 }
5894
5895                 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
5896
5897                 if (callingUid == 0 ||
5898                         (focus != null && callingUid == focus.mSession.mUid) ||
5899                         mContext.checkPermission(
5900                                 android.Manifest.permission.INJECT_EVENTS,
5901                                 callingPid, callingUid)
5902                                 == PackageManager.PERMISSION_GRANTED) {
5903                     if (mPolicy.interceptKeyTi(focus,
5904                             keycode, nextKey.getMetaState(), down, repeatCount,
5905                             nextKey.getFlags())) {
5906                         return CONSUMED_EVENT_TOKEN;
5907                     }
5908                 }
5909
5910                 return focus;
5911
5912             } else if (!isPointerEvent) {
5913                 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(-1);
5914                 if (!dispatch) {
5915                     Slog.w(TAG, "Event timeout during app switch: dropping trackball "
5916                             + nextMotion);
5917                     return SKIP_TARGET_TOKEN;
5918                 }
5919
5920                 WindowState focus = null;
5921                 synchronized(mWindowMap) {
5922                     focus = getFocusedWindowLocked();
5923                 }
5924
5925                 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
5926                 return focus;
5927             }
5928
5929             if (nextMotion == null) {
5930                 return SKIP_TARGET_TOKEN;
5931             }
5932
5933             boolean dispatch = mKeyWaiter.checkShouldDispatchKey(
5934                     KeyEvent.KEYCODE_UNKNOWN);
5935             if (!dispatch) {
5936                 Slog.w(TAG, "Event timeout during app switch: dropping pointer "
5937                         + nextMotion);
5938                 return SKIP_TARGET_TOKEN;
5939             }
5940
5941             // Find the target window for a pointer event.
5942             int action = nextMotion.getAction();
5943             final float xf = nextMotion.getX();
5944             final float yf = nextMotion.getY();
5945             final long eventTime = nextMotion.getEventTime();
5946
5947             final boolean screenWasOff = qev != null
5948                     && (qev.flags&WindowManagerPolicy.FLAG_BRIGHT_HERE) != 0;
5949
5950             WindowState target = null;
5951
5952             synchronized(mWindowMap) {
5953                 synchronized (this) {
5954                     if (action == MotionEvent.ACTION_DOWN) {
5955                         if (mMotionTarget != null) {
5956                             // this is weird, we got a pen down, but we thought it was
5957                             // already down!
5958                             // XXX: We should probably send an ACTION_UP to the current
5959                             // target.
5960                             Slog.w(TAG, "Pointer down received while already down in: "
5961                                     + mMotionTarget);
5962                             mMotionTarget = null;
5963                         }
5964
5965                         // ACTION_DOWN is special, because we need to lock next events to
5966                         // the window we'll land onto.
5967                         final int x = (int)xf;
5968                         final int y = (int)yf;
5969
5970                         final ArrayList windows = mWindows;
5971                         final int N = windows.size();
5972                         WindowState topErrWindow = null;
5973                         final Rect tmpRect = mTempRect;
5974                         for (int i=N-1; i>=0; i--) {
5975                             WindowState child = (WindowState)windows.get(i);
5976                             //Slog.i(TAG, "Checking dispatch to: " + child);
5977                             final int flags = child.mAttrs.flags;
5978                             if ((flags & WindowManager.LayoutParams.FLAG_SYSTEM_ERROR) != 0) {
5979                                 if (topErrWindow == null) {
5980                                     topErrWindow = child;
5981                                 }
5982                             }
5983                             if (!child.isVisibleLw()) {
5984                                 //Slog.i(TAG, "Not visible!");
5985                                 continue;
5986                             }
5987                             if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
5988                                 //Slog.i(TAG, "Not touchable!");
5989                                 if ((flags & WindowManager.LayoutParams
5990                                         .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
5991                                     child.mNextOutsideTouch = mOutsideTouchTargets;
5992                                     mOutsideTouchTargets = child;
5993                                 }
5994                                 continue;
5995                             }
5996                             tmpRect.set(child.mFrame);
5997                             if (child.mTouchableInsets == ViewTreeObserver
5998                                         .InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT) {
5999                                 // The touch is inside of the window if it is
6000                                 // inside the frame, AND the content part of that
6001                                 // frame that was given by the application.
6002                                 tmpRect.left += child.mGivenContentInsets.left;
6003                                 tmpRect.top += child.mGivenContentInsets.top;
6004                                 tmpRect.right -= child.mGivenContentInsets.right;
6005                                 tmpRect.bottom -= child.mGivenContentInsets.bottom;
6006                             } else if (child.mTouchableInsets == ViewTreeObserver
6007                                         .InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE) {
6008                                 // The touch is inside of the window if it is
6009                                 // inside the frame, AND the visible part of that
6010                                 // frame that was given by the application.
6011                                 tmpRect.left += child.mGivenVisibleInsets.left;
6012                                 tmpRect.top += child.mGivenVisibleInsets.top;
6013                                 tmpRect.right -= child.mGivenVisibleInsets.right;
6014                                 tmpRect.bottom -= child.mGivenVisibleInsets.bottom;
6015                             }
6016                             final int touchFlags = flags &
6017                                 (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6018                                 |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
6019                             if (tmpRect.contains(x, y) || touchFlags == 0) {
6020                                 //Slog.i(TAG, "Using this target!");
6021                                 if (!screenWasOff || (flags &
6022                                         WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING) != 0) {
6023                                     mMotionTarget = child;
6024                                 } else {
6025                                     //Slog.i(TAG, "Waking, skip!");
6026                                     mMotionTarget = null;
6027                                 }
6028                                 break;
6029                             }
6030
6031                             if ((flags & WindowManager.LayoutParams
6032                                     .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
6033                                 child.mNextOutsideTouch = mOutsideTouchTargets;
6034                                 mOutsideTouchTargets = child;
6035                                 //Slog.i(TAG, "Adding to outside target list: " + child);
6036                             }
6037                         }
6038
6039                         // if there's an error window but it's not accepting
6040                         // focus (typically because it is not yet visible) just
6041                         // wait for it -- any other focused window may in fact
6042                         // be in ANR state.
6043                         if (topErrWindow != null && mMotionTarget != topErrWindow) {
6044                             mMotionTarget = null;
6045                         }
6046                     }
6047
6048                     target = mMotionTarget;
6049                 }
6050             }
6051
6052             wakeupIfNeeded(target, eventType(nextMotion));
6053
6054             // Pointer events are a little different -- if there isn't a
6055             // target found for any event, then just drop it.
6056             return target != null ? target : SKIP_TARGET_TOKEN;
6057         }
6058
6059         boolean checkShouldDispatchKey(int keycode) {
6060             synchronized (this) {
6061                 if (mPolicy.isAppSwitchKeyTqTiLwLi(keycode)) {
6062                     mTimeToSwitch = 0;
6063                     return true;
6064                 }
6065                 if (mTimeToSwitch != 0
6066                         && mTimeToSwitch < SystemClock.uptimeMillis()) {
6067                     return false;
6068                 }
6069                 return true;
6070             }
6071         }
6072
6073         void bindTargetWindowLocked(WindowState win,
6074                 int pendingWhat, QueuedEvent pendingMotion) {
6075             synchronized (this) {
6076                 bindTargetWindowLockedLocked(win, pendingWhat, pendingMotion);
6077             }
6078         }
6079
6080         void bindTargetWindowLocked(WindowState win) {
6081             synchronized (this) {
6082                 bindTargetWindowLockedLocked(win, RETURN_NOTHING, null);
6083             }
6084         }
6085
6086         void bindTargetWindowLockedLocked(WindowState win,
6087                 int pendingWhat, QueuedEvent pendingMotion) {
6088             mLastWin = win;
6089             mLastBinder = win.mClient.asBinder();
6090             mFinished = false;
6091             if (pendingMotion != null) {
6092                 final Session s = win.mSession;
6093                 if (pendingWhat == RETURN_PENDING_POINTER) {
6094                     releasePendingPointerLocked(s);
6095                     s.mPendingPointerMove = pendingMotion;
6096                     s.mPendingPointerWindow = win;
6097                     if (DEBUG_INPUT) Slog.v(TAG,
6098                             "bindTargetToWindow " + s.mPendingPointerMove);
6099                 } else if (pendingWhat == RETURN_PENDING_TRACKBALL) {
6100                     releasePendingTrackballLocked(s);
6101                     s.mPendingTrackballMove = pendingMotion;
6102                     s.mPendingTrackballWindow = win;
6103                 }
6104             }
6105         }
6106
6107         void releasePendingPointerLocked(Session s) {
6108             if (DEBUG_INPUT) Slog.v(TAG,
6109                     "releasePendingPointer " + s.mPendingPointerMove);
6110             if (s.mPendingPointerMove != null) {
6111                 mQueue.recycleEvent(s.mPendingPointerMove);
6112                 s.mPendingPointerMove = null;
6113             }
6114         }
6115
6116         void releasePendingTrackballLocked(Session s) {
6117             if (s.mPendingTrackballMove != null) {
6118                 mQueue.recycleEvent(s.mPendingTrackballMove);
6119                 s.mPendingTrackballMove = null;
6120             }
6121         }
6122
6123         MotionEvent finishedKey(Session session, IWindow client, boolean force,
6124                 int returnWhat) {
6125             if (DEBUG_INPUT) Slog.v(
6126                 TAG, "finishedKey: client=" + client + ", force=" + force);
6127
6128             if (client == null) {
6129                 return null;
6130             }
6131
6132             MotionEvent res = null;
6133             QueuedEvent qev = null;
6134             WindowState win = null;
6135
6136             synchronized (this) {
6137                 if (DEBUG_INPUT) Slog.v(
6138                     TAG, "finishedKey: client=" + client.asBinder()
6139                     + ", force=" + force + ", last=" + mLastBinder
6140                     + " (token=" + (mLastWin != null ? mLastWin.mToken : null) + ")");
6141
6142                 if (returnWhat == RETURN_PENDING_POINTER) {
6143                     qev = session.mPendingPointerMove;
6144                     win = session.mPendingPointerWindow;
6145                     session.mPendingPointerMove = null;
6146                     session.mPendingPointerWindow = null;
6147                 } else if (returnWhat == RETURN_PENDING_TRACKBALL) {
6148                     qev = session.mPendingTrackballMove;
6149                     win = session.mPendingTrackballWindow;
6150                     session.mPendingTrackballMove = null;
6151                     session.mPendingTrackballWindow = null;
6152                 }
6153
6154                 if (mLastBinder == client.asBinder()) {
6155                     if (DEBUG_INPUT) Slog.v(
6156                         TAG, "finishedKey: last paused="
6157                         + ((mLastWin != null) ? mLastWin.mToken.paused : "null"));
6158                     if (mLastWin != null && (!mLastWin.mToken.paused || force
6159                             || !mEventDispatching)) {
6160                         doFinishedKeyLocked(true);
6161                     } else {
6162                         // Make sure to wake up anyone currently waiting to
6163                         // dispatch a key, so they can re-evaluate their
6164                         // current situation.
6165                         mFinished = true;
6166                         notifyAll();
6167                     }
6168                 }
6169
6170                 if (qev != null) {
6171                     res = (MotionEvent)qev.event;
6172                     if (DEBUG_INPUT) Slog.v(TAG,
6173                             "Returning pending motion: " + res);
6174                     mQueue.recycleEvent(qev);
6175                     if (win != null && returnWhat == RETURN_PENDING_POINTER) {
6176                         res.offsetLocation(-win.mFrame.left, -win.mFrame.top);
6177                     }
6178                 }
6179             }
6180
6181             if (res != null && returnWhat == RETURN_PENDING_POINTER) {
6182                 synchronized (mWindowMap) {
6183                     dispatchPointerElsewhereLocked(win, win, res, res.getEventTime(), false);
6184                 }
6185             }
6186
6187             return res;
6188         }
6189
6190         void tickle() {
6191             synchronized (this) {
6192                 notifyAll();
6193             }
6194         }
6195
6196         void handleNewWindowLocked(WindowState newWindow) {
6197             if (!newWindow.canReceiveKeys()) {
6198                 return;
6199             }
6200             synchronized (this) {
6201                 if (DEBUG_INPUT) Slog.v(
6202                     TAG, "New key dispatch window: win="
6203                     + newWindow.mClient.asBinder()
6204                     + ", last=" + mLastBinder
6205                     + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
6206                     + "), finished=" + mFinished + ", paused="
6207                     + newWindow.mToken.paused);
6208
6209                 // Displaying a window implicitly causes dispatching to
6210                 // be unpaused.  (This is to protect against bugs if someone
6211                 // pauses dispatching but forgets to resume.)
6212                 newWindow.mToken.paused = false;
6213
6214                 mGotFirstWindow = true;
6215
6216                 if ((newWindow.mAttrs.flags & FLAG_SYSTEM_ERROR) != 0) {
6217                     if (DEBUG_INPUT) Slog.v(TAG,
6218                             "New SYSTEM_ERROR window; resetting state");
6219                     mLastWin = null;
6220                     mLastBinder = null;
6221                     mMotionTarget = null;
6222                     mFinished = true;
6223                 } else if (mLastWin != null) {
6224                     // If the new window is above the window we are
6225                     // waiting on, then stop waiting and let key dispatching
6226                     // start on the new guy.
6227                     if (DEBUG_INPUT) Slog.v(
6228                         TAG, "Last win layer=" + mLastWin.mLayer
6229                         + ", new win layer=" + newWindow.mLayer);
6230                     if (newWindow.mLayer >= mLastWin.mLayer) {
6231                         // The new window is above the old; finish pending input to the last
6232                         // window and start directing it to the new one.
6233                         mLastWin.mToken.paused = false;
6234                         doFinishedKeyLocked(false);  // does a notifyAll()
6235                         return;
6236                     }
6237                 }
6238
6239                 // Now that we've put a new window state in place, make the event waiter
6240                 // take notice and retarget its attentions.
6241                 notifyAll();
6242             }
6243         }
6244
6245         void pauseDispatchingLocked(WindowToken token) {
6246             synchronized (this)
6247             {
6248                 if (DEBUG_INPUT) Slog.v(TAG, "Pausing WindowToken " + token);
6249                 token.paused = true;
6250
6251                 /*
6252                 if (mLastWin != null && !mFinished && mLastWin.mBaseLayer <= layer) {
6253                     mPaused = true;
6254                 } else {
6255                     if (mLastWin == null) {
6256                         Slog.i(TAG, "Key dispatching not paused: no last window.");
6257                     } else if (mFinished) {
6258                         Slog.i(TAG, "Key dispatching not paused: finished last key.");
6259                     } else {
6260                         Slog.i(TAG, "Key dispatching not paused: window in higher layer.");
6261                     }
6262                 }
6263                 */
6264             }
6265         }
6266
6267         void resumeDispatchingLocked(WindowToken token) {
6268             synchronized (this) {
6269                 if (token.paused) {
6270                     if (DEBUG_INPUT) Slog.v(
6271                         TAG, "Resuming WindowToken " + token
6272                         + ", last=" + mLastBinder
6273                         + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
6274                         + "), finished=" + mFinished + ", paused="
6275                         + token.paused);
6276                     token.paused = false;
6277                     if (mLastWin != null && mLastWin.mToken == token && mFinished) {
6278                         doFinishedKeyLocked(false);
6279                     } else {
6280                         notifyAll();
6281                     }
6282                 }
6283             }
6284         }
6285
6286         void setEventDispatchingLocked(boolean enabled) {
6287             synchronized (this) {
6288                 mEventDispatching = enabled;
6289                 notifyAll();
6290             }
6291         }
6292
6293         void appSwitchComing() {
6294             synchronized (this) {
6295                 // Don't wait for more than .5 seconds for app to finish
6296                 // processing the pending events.
6297                 long now = SystemClock.uptimeMillis() + 500;
6298                 if (DEBUG_INPUT) Slog.v(TAG, "appSwitchComing: " + now);
6299                 if (mTimeToSwitch == 0 || now < mTimeToSwitch) {
6300                     mTimeToSwitch = now;
6301                 }
6302                 notifyAll();
6303             }
6304         }
6305
6306         private final void doFinishedKeyLocked(boolean force) {
6307             if (mLastWin != null) {
6308                 releasePendingPointerLocked(mLastWin.mSession);
6309                 releasePendingTrackballLocked(mLastWin.mSession);
6310             }
6311
6312             if (force || mLastWin == null || !mLastWin.mToken.paused
6313                     || !mLastWin.isVisibleLw()) {
6314                 // If the current window has been paused, we aren't -really-
6315                 // finished...  so let the waiters still wait.
6316                 mLastWin = null;
6317                 mLastBinder = null;
6318             }
6319             mFinished = true;
6320             notifyAll();
6321         }
6322     }
6323
6324     private class KeyQ extends KeyInputQueue
6325             implements KeyInputQueue.FilterCallback {
6326         PowerManager.WakeLock mHoldingScreen;
6327
6328         KeyQ() {
6329             super(mContext, WindowManagerService.this);
6330             PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
6331             mHoldingScreen = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
6332                     "KEEP_SCREEN_ON_FLAG");
6333             mHoldingScreen.setReferenceCounted(false);
6334         }
6335
6336         @Override
6337         boolean preprocessEvent(InputDevice device, RawInputEvent event) {
6338             if (mPolicy.preprocessInputEventTq(event)) {
6339                 return true;
6340             }
6341
6342             switch (event.type) {
6343                 case RawInputEvent.EV_KEY: {
6344                     // XXX begin hack
6345                     if (DEBUG) {
6346                         if (event.keycode == KeyEvent.KEYCODE_G) {
6347                             if (event.value != 0) {
6348                                 // G down
6349                                 mPolicy.screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
6350                             }
6351                             return false;
6352                         }
6353                         if (event.keycode == KeyEvent.KEYCODE_D) {
6354                             if (event.value != 0) {
6355                                 //dump();
6356                             }
6357                             return false;
6358                         }
6359                     }
6360                     // XXX end hack
6361
6362                     boolean screenIsOff = !mPowerManager.isScreenOn();
6363                     boolean screenIsDim = !mPowerManager.isScreenBright();
6364                     int actions = mPolicy.interceptKeyTq(event, !screenIsOff);
6365
6366                     if ((actions & WindowManagerPolicy.ACTION_GO_TO_SLEEP) != 0) {
6367                         mPowerManager.goToSleep(event.when);
6368                     }
6369
6370                     if (screenIsOff) {
6371                         event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6372                     }
6373                     if (screenIsDim) {
6374                         event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6375                     }
6376                     if ((actions & WindowManagerPolicy.ACTION_POKE_USER_ACTIVITY) != 0) {
6377                         mPowerManager.userActivity(event.when, false,
6378                                 LocalPowerManager.BUTTON_EVENT, false);
6379                     }
6380
6381                     if ((actions & WindowManagerPolicy.ACTION_PASS_TO_USER) != 0) {
6382                         if (event.value != 0 && mPolicy.isAppSwitchKeyTqTiLwLi(event.keycode)) {
6383                             filterQueue(this);
6384                             mKeyWaiter.appSwitchComing();
6385                         }
6386                         return true;
6387                     } else {
6388                         return false;
6389                     }
6390                 }
6391
6392                 case RawInputEvent.EV_REL: {
6393                     boolean screenIsOff = !mPowerManager.isScreenOn();
6394                     boolean screenIsDim = !mPowerManager.isScreenBright();
6395                     if (screenIsOff) {
6396                         if (!mPolicy.isWakeRelMovementTq(event.deviceId,
6397                                 device.classes, event)) {
6398                             //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey");
6399                             return false;
6400                         }
6401                         event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6402                     }
6403                     if (screenIsDim) {
6404                         event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6405                     }
6406                     return true;
6407                 }
6408
6409                 case RawInputEvent.EV_ABS: {
6410                     boolean screenIsOff = !mPowerManager.isScreenOn();
6411                     boolean screenIsDim = !mPowerManager.isScreenBright();
6412                     if (screenIsOff) {
6413                         if (!mPolicy.isWakeAbsMovementTq(event.deviceId,
6414                                 device.classes, event)) {
6415                             //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey");
6416                             return false;
6417                         }
6418                         event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6419                     }
6420                     if (screenIsDim) {
6421                         event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6422                     }
6423                     return true;
6424                 }
6425
6426                 default:
6427                     return true;
6428             }
6429         }
6430
6431         public int filterEvent(QueuedEvent ev) {
6432             switch (ev.classType) {
6433                 case RawInputEvent.CLASS_KEYBOARD:
6434                     KeyEvent ke = (KeyEvent)ev.event;
6435                     if (mPolicy.isMovementKeyTi(ke.getKeyCode())) {
6436                         Slog.w(TAG, "Dropping movement key during app switch: "
6437                                 + ke.getKeyCode() + ", action=" + ke.getAction());
6438                         return FILTER_REMOVE;
6439                     }
6440                     return FILTER_ABORT;
6441                 default:
6442                     return FILTER_KEEP;
6443             }
6444         }
6445
6446         /**
6447          * Must be called with the main window manager lock held.
6448          */
6449         void setHoldScreenLocked(boolean holding) {
6450             boolean state = mHoldingScreen.isHeld();
6451             if (holding != state) {
6452                 if (holding) {
6453                     mHoldingScreen.acquire();
6454                 } else {
6455                     mPolicy.screenOnStoppedLw();
6456                     mHoldingScreen.release();
6457                 }
6458             }
6459         }
6460     }
6461
6462     public boolean detectSafeMode() {
6463         mSafeMode = mPolicy.detectSafeMode();
6464         return mSafeMode;
6465     }
6466
6467     public void systemReady() {
6468         mPolicy.systemReady();
6469     }
6470
6471     private final class InputDispatcherThread extends Thread {
6472         // Time to wait when there is nothing to do: 9999 seconds.
6473         static final int LONG_WAIT=9999*1000;
6474
6475         public InputDispatcherThread() {
6476             super("InputDispatcher");
6477         }
6478
6479         @Override
6480         public void run() {
6481             while (true) {
6482                 try {
6483                     process();
6484                 } catch (Exception e) {
6485                     Slog.e(TAG, "Exception in input dispatcher", e);
6486                 }
6487             }
6488         }
6489
6490         private void process() {
6491             android.os.Process.setThreadPriority(
6492                     android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
6493
6494             // The last key event we saw
6495             KeyEvent lastKey = null;
6496
6497             // Last keydown time for auto-repeating keys
6498             long lastKeyTime = SystemClock.uptimeMillis();
6499             long nextKeyTime = lastKeyTime+LONG_WAIT;
6500             long downTime = 0;
6501
6502             // How many successive repeats we generated
6503             int keyRepeatCount = 0;
6504
6505             // Need to report that configuration has changed?
6506             boolean configChanged = false;
6507
6508             while (true) {
6509                 long curTime = SystemClock.uptimeMillis();
6510
6511                 if (DEBUG_INPUT) Slog.v(
6512                     TAG, "Waiting for next key: now=" + curTime
6513                     + ", repeat @ " + nextKeyTime);
6514
6515                 // Retrieve next event, waiting only as long as the next
6516                 // repeat timeout.  If the configuration has changed, then
6517                 // don't wait at all -- we'll report the change as soon as
6518                 // we have processed all events.
6519                 QueuedEvent ev = mQueue.getEvent(
6520                     (int)((!configChanged && curTime < nextKeyTime)
6521                             ? (nextKeyTime-curTime) : 0));
6522
6523                 if (DEBUG_INPUT && ev != null) Slog.v(
6524                         TAG, "Event: type=" + ev.classType + " data=" + ev.event);
6525
6526                 if (MEASURE_LATENCY) {
6527                     lt.sample("2 got event              ", System.nanoTime() - ev.whenNano);
6528                 }
6529
6530                 if (lastKey != null && !mPolicy.allowKeyRepeat()) {
6531                     // cancel key repeat at the request of the policy.
6532                     lastKey = null;
6533                     downTime = 0;
6534                     lastKeyTime = curTime;
6535                     nextKeyTime = curTime + LONG_WAIT;
6536                 }
6537                 try {
6538                     if (ev != null) {
6539                         curTime = SystemClock.uptimeMillis();
6540                         int eventType;
6541                         if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
6542                             eventType = eventType((MotionEvent)ev.event);
6543                         } else if (ev.classType == RawInputEvent.CLASS_KEYBOARD ||
6544                                     ev.classType == RawInputEvent.CLASS_TRACKBALL) {
6545                             eventType = LocalPowerManager.BUTTON_EVENT;
6546                         } else {
6547                             eventType = LocalPowerManager.OTHER_EVENT;
6548                         }
6549                         try {
6550                             if ((curTime - mLastBatteryStatsCallTime)
6551                                     >= MIN_TIME_BETWEEN_USERACTIVITIES) {
6552                                 mLastBatteryStatsCallTime = curTime;
6553                                 mBatteryStats.noteInputEvent();
6554                             }
6555                         } catch (RemoteException e) {
6556                             // Ignore
6557                         }
6558
6559                         if (ev.classType == RawInputEvent.CLASS_CONFIGURATION_CHANGED) {
6560                             // do not wake screen in this case
6561                         } else if (eventType != TOUCH_EVENT
6562                                 && eventType != LONG_TOUCH_EVENT
6563                                 && eventType != CHEEK_EVENT) {
6564                             mPowerManager.userActivity(curTime, false,
6565                                     eventType, false);
6566                         } else if (mLastTouchEventType != eventType
6567                                 || (curTime - mLastUserActivityCallTime)
6568                                 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
6569                             mLastUserActivityCallTime = curTime;
6570                             mLastTouchEventType = eventType;
6571                             mPowerManager.userActivity(curTime, false,
6572                                     eventType, false);
6573                         }
6574
6575                         switch (ev.classType) {
6576                             case RawInputEvent.CLASS_KEYBOARD:
6577                                 KeyEvent ke = (KeyEvent)ev.event;
6578                                 if (ke.isDown()) {
6579                                     lastKeyTime = curTime;
6580                                     if (lastKey != null &&
6581                                             ke.getKeyCode() == lastKey.getKeyCode()) {
6582                                         keyRepeatCount++;
6583                                         // Arbitrary long timeout to block
6584                                         // repeating here since we know that
6585                                         // the device driver takes care of it.
6586                                         nextKeyTime = lastKeyTime + LONG_WAIT;
6587                                         if (DEBUG_INPUT) Slog.v(
6588                                                 TAG, "Received repeated key down");
6589                                     } else {
6590                                         downTime = curTime;
6591                                         keyRepeatCount = 0;
6592                                         nextKeyTime = lastKeyTime
6593                                                 + ViewConfiguration.getLongPressTimeout();
6594                                         if (DEBUG_INPUT) Slog.v(
6595                                             TAG, "Received key down: first repeat @ "
6596                                             + nextKeyTime);
6597                                     }
6598                                     lastKey = ke;
6599                                 } else {
6600                                     lastKey = null;
6601                                     downTime = 0;
6602                                     keyRepeatCount = 0;
6603                                     // Arbitrary long timeout.
6604                                     lastKeyTime = curTime;
6605                                     nextKeyTime = curTime + LONG_WAIT;
6606                                     if (DEBUG_INPUT) Slog.v(
6607                                         TAG, "Received key up: ignore repeat @ "
6608                                         + nextKeyTime);
6609                                 }
6610                                 if (keyRepeatCount > 0) {
6611                                     dispatchKey(KeyEvent.changeTimeRepeat(ke,
6612                                             ke.getEventTime(), keyRepeatCount), 0, 0);
6613                                 } else {
6614                                     dispatchKey(ke, 0, 0);
6615                                 }
6616                                 mQueue.recycleEvent(ev);
6617                                 break;
6618                             case RawInputEvent.CLASS_TOUCHSCREEN:
6619                                 //Slog.i(TAG, "Read next event " + ev);
6620                                 dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
6621                                 break;
6622                             case RawInputEvent.CLASS_TRACKBALL:
6623                                 dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0);
6624                                 break;
6625                             case RawInputEvent.CLASS_CONFIGURATION_CHANGED:
6626                                 configChanged = true;
6627                                 break;
6628                             default:
6629                                 mQueue.recycleEvent(ev);
6630                             break;
6631                         }
6632
6633                     } else if (configChanged) {
6634                         configChanged = false;
6635                         sendNewConfiguration();
6636
6637                     } else if (lastKey != null) {
6638                         curTime = SystemClock.uptimeMillis();
6639
6640                         // Timeout occurred while key was down.  If it is at or
6641                         // past the key repeat time, dispatch the repeat.
6642                         if (DEBUG_INPUT) Slog.v(
6643                             TAG, "Key timeout: repeat=" + nextKeyTime
6644                             + ", now=" + curTime);
6645                         if (curTime < nextKeyTime) {
6646                             continue;
6647                         }
6648
6649                         lastKeyTime = nextKeyTime;
6650                         nextKeyTime = nextKeyTime + KEY_REPEAT_DELAY;
6651                         keyRepeatCount++;
6652                         if (DEBUG_INPUT) Slog.v(
6653                             TAG, "Key repeat: count=" + keyRepeatCount
6654                             + ", next @ " + nextKeyTime);
6655                         KeyEvent newEvent;
6656                         if (downTime != 0 && (downTime
6657                                 + ViewConfiguration.getLongPressTimeout())
6658                                 <= curTime) {
6659                             newEvent = KeyEvent.changeTimeRepeat(lastKey,
6660                                     curTime, keyRepeatCount,
6661                                     lastKey.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6662                             downTime = 0;
6663                         } else {
6664                             newEvent = KeyEvent.changeTimeRepeat(lastKey,
6665                                     curTime, keyRepeatCount);
6666                         }
6667                         dispatchKey(newEvent, 0, 0);
6668
6669                     } else {
6670                         curTime = SystemClock.uptimeMillis();
6671
6672                         lastKeyTime = curTime;
6673                         nextKeyTime = curTime + LONG_WAIT;
6674                     }
6675
6676                 } catch (Exception e) {
6677                     Slog.e(TAG,
6678                         "Input thread received uncaught exception: " + e, e);
6679                 }
6680             }
6681         }
6682     }
6683
6684     // -------------------------------------------------------------
6685     // Client Session State
6686     // -------------------------------------------------------------
6687
6688     private final class Session extends IWindowSession.Stub
6689             implements IBinder.DeathRecipient {
6690         final IInputMethodClient mClient;
6691         final IInputContext mInputContext;
6692         final int mUid;
6693         final int mPid;
6694         final String mStringName;
6695         SurfaceSession mSurfaceSession;
6696         int mNumWindow = 0;
6697         boolean mClientDead = false;
6698
6699         /**
6700          * Current pointer move event being dispatched to client window...  must
6701          * hold key lock to access.
6702          */
6703         QueuedEvent mPendingPointerMove;
6704         WindowState mPendingPointerWindow;
6705
6706         /**
6707          * Current trackball move event being dispatched to client window...  must
6708          * hold key lock to access.
6709          */
6710         QueuedEvent mPendingTrackballMove;
6711         WindowState mPendingTrackballWindow;
6712
6713         public Session(IInputMethodClient client, IInputContext inputContext) {
6714             mClient = client;
6715             mInputContext = inputContext;
6716             mUid = Binder.getCallingUid();
6717             mPid = Binder.getCallingPid();
6718             StringBuilder sb = new StringBuilder();
6719             sb.append("Session{");
6720             sb.append(Integer.toHexString(System.identityHashCode(this)));
6721             sb.append(" uid ");
6722             sb.append(mUid);
6723             sb.append("}");
6724             mStringName = sb.toString();
6725
6726             synchronized (mWindowMap) {
6727                 if (mInputMethodManager == null && mHaveInputMethods) {
6728                     IBinder b = ServiceManager.getService(
6729                             Context.INPUT_METHOD_SERVICE);
6730                     mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
6731                 }
6732             }
6733             long ident = Binder.clearCallingIdentity();
6734             try {
6735                 // Note: it is safe to call in to the input method manager
6736                 // here because we are not holding our lock.
6737                 if (mInputMethodManager != null) {
6738                     mInputMethodManager.addClient(client, inputContext,
6739                             mUid, mPid);
6740                 } else {
6741                     client.setUsingInputMethod(false);
6742                 }
6743                 client.asBinder().linkToDeath(this, 0);
6744             } catch (RemoteException e) {
6745                 // The caller has died, so we can just forget about this.
6746                 try {
6747                     if (mInputMethodManager != null) {
6748                         mInputMethodManager.removeClient(client);
6749                     }
6750                 } catch (RemoteException ee) {
6751                 }
6752             } finally {
6753                 Binder.restoreCallingIdentity(ident);
6754             }
6755         }
6756
6757         @Override
6758         public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
6759                 throws RemoteException {
6760             try {
6761                 return super.onTransact(code, data, reply, flags);
6762             } catch (RuntimeException e) {
6763                 // Log all 'real' exceptions thrown to the caller
6764                 if (!(e instanceof SecurityException)) {
6765                     Slog.e(TAG, "Window Session Crash", e);
6766                 }
6767                 throw e;
6768             }
6769         }
6770
6771         public void binderDied() {
6772             // Note: it is safe to call in to the input method manager
6773             // here because we are not holding our lock.
6774             try {
6775                 if (mInputMethodManager != null) {
6776                     mInputMethodManager.removeClient(mClient);
6777                 }
6778             } catch (RemoteException e) {
6779             }
6780             synchronized(mWindowMap) {
6781                 mClient.asBinder().unlinkToDeath(this, 0);
6782                 mClientDead = true;
6783                 killSessionLocked();
6784             }
6785         }
6786
6787         public int add(IWindow window, WindowManager.LayoutParams attrs,
6788                 int viewVisibility, Rect outContentInsets) {
6789             return addWindow(this, window, attrs, viewVisibility, outContentInsets);
6790         }
6791
6792         public void remove(IWindow window) {
6793             removeWindow(this, window);
6794         }
6795
6796         public int relayout(IWindow window, WindowManager.LayoutParams attrs,
6797                 int requestedWidth, int requestedHeight, int viewFlags,
6798                 boolean insetsPending, Rect outFrame, Rect outContentInsets,
6799                 Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
6800             return relayoutWindow(this, window, attrs,
6801                     requestedWidth, requestedHeight, viewFlags, insetsPending,
6802                     outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
6803         }
6804
6805         public void setTransparentRegion(IWindow window, Region region) {
6806             setTransparentRegionWindow(this, window, region);
6807         }
6808
6809         public void setInsets(IWindow window, int touchableInsets,
6810                 Rect contentInsets, Rect visibleInsets) {
6811             setInsetsWindow(this, window, touchableInsets, contentInsets,
6812                     visibleInsets);
6813         }
6814
6815         public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
6816             getWindowDisplayFrame(this, window, outDisplayFrame);
6817         }
6818
6819         public void finishDrawing(IWindow window) {
6820             if (localLOGV) Slog.v(
6821                 TAG, "IWindow finishDrawing called for " + window);
6822             finishDrawingWindow(this, window);
6823         }
6824
6825         public void finishKey(IWindow window) {
6826             if (localLOGV) Slog.v(
6827                 TAG, "IWindow finishKey called for " + window);
6828             mKeyWaiter.finishedKey(this, window, false,
6829                     KeyWaiter.RETURN_NOTHING);
6830         }
6831
6832         public MotionEvent getPendingPointerMove(IWindow window) {
6833             if (localLOGV) Slog.v(
6834                     TAG, "IWindow getPendingMotionEvent called for " + window);
6835             return mKeyWaiter.finishedKey(this, window, false,
6836                     KeyWaiter.RETURN_PENDING_POINTER);
6837         }
6838
6839         public MotionEvent getPendingTrackballMove(IWindow window) {
6840             if (localLOGV) Slog.v(
6841                     TAG, "IWindow getPendingMotionEvent called for " + window);
6842             return mKeyWaiter.finishedKey(this, window, false,
6843                     KeyWaiter.RETURN_PENDING_TRACKBALL);
6844         }
6845
6846         public void setInTouchMode(boolean mode) {
6847             synchronized(mWindowMap) {
6848                 mInTouchMode = mode;
6849             }
6850         }
6851
6852         public boolean getInTouchMode() {
6853             synchronized(mWindowMap) {
6854                 return mInTouchMode;
6855             }
6856         }
6857
6858         public boolean performHapticFeedback(IWindow window, int effectId,
6859                 boolean always) {
6860             synchronized(mWindowMap) {
6861                 long ident = Binder.clearCallingIdentity();
6862                 try {
6863                     return mPolicy.performHapticFeedbackLw(
6864                             windowForClientLocked(this, window, true),
6865                             effectId, always);
6866                 } finally {
6867                     Binder.restoreCallingIdentity(ident);
6868                 }
6869             }
6870         }
6871
6872         public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
6873             synchronized(mWindowMap) {
6874                 long ident = Binder.clearCallingIdentity();
6875                 try {
6876                     setWindowWallpaperPositionLocked(
6877                             windowForClientLocked(this, window, true),
6878                             x, y, xStep, yStep);
6879                 } finally {
6880                     Binder.restoreCallingIdentity(ident);
6881                 }
6882             }
6883         }
6884
6885         public void wallpaperOffsetsComplete(IBinder window) {
6886             WindowManagerService.this.wallpaperOffsetsComplete(window);
6887         }
6888
6889         public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
6890                 int z, Bundle extras, boolean sync) {
6891             synchronized(mWindowMap) {
6892                 long ident = Binder.clearCallingIdentity();
6893                 try {
6894                     return sendWindowWallpaperCommandLocked(
6895                             windowForClientLocked(this, window, true),
6896                             action, x, y, z, extras, sync);
6897                 } finally {
6898                     Binder.restoreCallingIdentity(ident);
6899                 }
6900             }
6901         }
6902
6903         public void wallpaperCommandComplete(IBinder window, Bundle result) {
6904             WindowManagerService.this.wallpaperCommandComplete(window, result);
6905         }
6906
6907         void windowAddedLocked() {
6908             if (mSurfaceSession == null) {
6909                 if (localLOGV) Slog.v(
6910                     TAG, "First window added to " + this + ", creating SurfaceSession");
6911                 mSurfaceSession = new SurfaceSession();
6912                 if (SHOW_TRANSACTIONS) Slog.i(
6913                         TAG, "  NEW SURFACE SESSION " + mSurfaceSession);
6914                 mSessions.add(this);
6915             }
6916             mNumWindow++;
6917         }
6918
6919         void windowRemovedLocked() {
6920             mNumWindow--;
6921             killSessionLocked();
6922         }
6923
6924         void killSessionLocked() {
6925             if (mNumWindow <= 0 && mClientDead) {
6926                 mSessions.remove(this);
6927                 if (mSurfaceSession != null) {
6928                     if (localLOGV) Slog.v(
6929                         TAG, "Last window removed from " + this
6930                         + ", destroying " + mSurfaceSession);
6931                     if (SHOW_TRANSACTIONS) Slog.i(
6932                             TAG, "  KILL SURFACE SESSION " + mSurfaceSession);
6933                     try {
6934                         mSurfaceSession.kill();
6935                     } catch (Exception e) {
6936                         Slog.w(TAG, "Exception thrown when killing surface session "
6937                             + mSurfaceSession + " in session " + this
6938                             + ": " + e.toString());
6939                     }
6940                     mSurfaceSession = null;
6941                 }
6942             }
6943         }
6944
6945         void dump(PrintWriter pw, String prefix) {
6946             pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
6947                     pw.print(" mClientDead="); pw.print(mClientDead);
6948                     pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
6949             if (mPendingPointerWindow != null || mPendingPointerMove != null) {
6950                 pw.print(prefix);
6951                         pw.print("mPendingPointerWindow="); pw.print(mPendingPointerWindow);
6952                         pw.print(" mPendingPointerMove="); pw.println(mPendingPointerMove);
6953             }
6954             if (mPendingTrackballWindow != null || mPendingTrackballMove != null) {
6955                 pw.print(prefix);
6956                         pw.print("mPendingTrackballWindow="); pw.print(mPendingTrackballWindow);
6957                         pw.print(" mPendingTrackballMove="); pw.println(mPendingTrackballMove);
6958             }
6959         }
6960
6961         @Override
6962         public String toString() {
6963             return mStringName;
6964         }
6965     }
6966
6967     // -------------------------------------------------------------
6968     // Client Window State
6969     // -------------------------------------------------------------
6970
6971     private final class WindowState implements WindowManagerPolicy.WindowState {
6972         final Session mSession;
6973         final IWindow mClient;
6974         WindowToken mToken;
6975         WindowToken mRootToken;
6976         AppWindowToken mAppToken;
6977         AppWindowToken mTargetAppToken;
6978         final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
6979         final DeathRecipient mDeathRecipient;
6980         final WindowState mAttachedWindow;
6981         final ArrayList mChildWindows = new ArrayList();
6982         final int mBaseLayer;
6983         final int mSubLayer;
6984         final boolean mLayoutAttached;
6985         final boolean mIsImWindow;
6986         final boolean mIsWallpaper;
6987         final boolean mIsFloatingLayer;
6988         int mViewVisibility;
6989         boolean mPolicyVisibility = true;
6990         boolean mPolicyVisibilityAfterAnim = true;
6991         boolean mAppFreezing;
6992         Surface mSurface;
6993         boolean mReportDestroySurface;
6994         boolean mSurfacePendingDestroy;
6995         boolean mAttachedHidden;    // is our parent window hidden?
6996         boolean mLastHidden;        // was this window last hidden?
6997         boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
6998         int mRequestedWidth;
6999         int mRequestedHeight;
7000         int mLastRequestedWidth;
7001         int mLastRequestedHeight;
7002         int mLayer;
7003         int mAnimLayer;
7004         int mLastLayer;
7005         boolean mHaveFrame;
7006         boolean mObscured;
7007         boolean mTurnOnScreen;
7008
7009         WindowState mNextOutsideTouch;
7010
7011         int mLayoutSeq = -1;
7012         
7013         Configuration mConfiguration = null;
7014         
7015         // Actual frame shown on-screen (may be modified by animation)
7016         final Rect mShownFrame = new Rect();
7017         final Rect mLastShownFrame = new Rect();
7018
7019         /**
7020          * Set when we have changed the size of the surface, to know that
7021          * we must tell them application to resize (and thus redraw itself).
7022          */
7023         boolean mSurfaceResized;
7024         
7025         /**
7026          * Insets that determine the actually visible area
7027          */
7028         final Rect mVisibleInsets = new Rect();
7029         final Rect mLastVisibleInsets = new Rect();
7030         boolean mVisibleInsetsChanged;
7031
7032         /**
7033          * Insets that are covered by system windows
7034          */
7035         final Rect mContentInsets = new Rect();
7036         final Rect mLastContentInsets = new Rect();
7037         boolean mContentInsetsChanged;
7038
7039         /**
7040          * Set to true if we are waiting for this window to receive its
7041          * given internal insets before laying out other windows based on it.
7042          */
7043         boolean mGivenInsetsPending;
7044
7045         /**
7046          * These are the content insets that were given during layout for
7047          * this window, to be applied to windows behind it.
7048          */
7049         final Rect mGivenContentInsets = new Rect();
7050
7051         /**
7052          * These are the visible insets that were given during layout for
7053          * this window, to be applied to windows behind it.
7054          */
7055         final Rect mGivenVisibleInsets = new Rect();
7056
7057         /**
7058          * Flag indicating whether the touchable region should be adjusted by
7059          * the visible insets; if false the area outside the visible insets is
7060          * NOT touchable, so we must use those to adjust the frame during hit
7061          * tests.
7062          */
7063         int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
7064
7065         // Current transformation being applied.
7066         float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
7067         float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
7068         float mHScale=1, mVScale=1;
7069         float mLastHScale=1, mLastVScale=1;
7070         final Matrix mTmpMatrix = new Matrix();
7071
7072         // "Real" frame that the application sees.
7073         final Rect mFrame = new Rect();
7074         final Rect mLastFrame = new Rect();
7075
7076         final Rect mContainingFrame = new Rect();
7077         final Rect mDisplayFrame = new Rect();
7078         final Rect mContentFrame = new Rect();
7079         final Rect mVisibleFrame = new Rect();
7080
7081         float mShownAlpha = 1;
7082         float mAlpha = 1;
7083         float mLastAlpha = 1;
7084
7085         // Set to true if, when the window gets displayed, it should perform
7086         // an enter animation.
7087         boolean mEnterAnimationPending;
7088
7089         // Currently running animation.
7090         boolean mAnimating;
7091         boolean mLocalAnimating;
7092         Animation mAnimation;
7093         boolean mAnimationIsEntrance;
7094         boolean mHasTransformation;
7095         boolean mHasLocalTransformation;
7096         final Transformation mTransformation = new Transformation();
7097
7098         // If a window showing a wallpaper: the requested offset for the
7099         // wallpaper; if a wallpaper window: the currently applied offset.
7100         float mWallpaperX = -1;
7101         float mWallpaperY = -1;
7102
7103         // If a window showing a wallpaper: what fraction of the offset
7104         // range corresponds to a full virtual screen.
7105         float mWallpaperXStep = -1;
7106         float mWallpaperYStep = -1;
7107
7108         // Wallpaper windows: pixels offset based on above variables.
7109         int mXOffset;
7110         int mYOffset;
7111
7112         // This is set after IWindowSession.relayout() has been called at
7113         // least once for the window.  It allows us to detect the situation
7114         // where we don't yet have a surface, but should have one soon, so
7115         // we can give the window focus before waiting for the relayout.
7116         boolean mRelayoutCalled;
7117
7118         // This is set after the Surface has been created but before the
7119         // window has been drawn.  During this time the surface is hidden.
7120         boolean mDrawPending;
7121
7122         // This is set after the window has finished drawing for the first
7123         // time but before its surface is shown.  The surface will be
7124         // displayed when the next layout is run.
7125         boolean mCommitDrawPending;
7126
7127         // This is set during the time after the window's drawing has been
7128         // committed, and before its surface is actually shown.  It is used
7129         // to delay showing the surface until all windows in a token are ready
7130         // to be shown.
7131         boolean mReadyToShow;
7132
7133         // Set when the window has been shown in the screen the first time.
7134         boolean mHasDrawn;
7135
7136         // Currently running an exit animation?
7137         boolean mExiting;
7138
7139         // Currently on the mDestroySurface list?
7140         boolean mDestroying;
7141
7142         // Completely remove from window manager after exit animation?
7143         boolean mRemoveOnExit;
7144
7145         // Set when the orientation is changing and this window has not yet
7146         // been updated for the new orientation.
7147         boolean mOrientationChanging;
7148
7149         // Is this window now (or just being) removed?
7150         boolean mRemoved;
7151
7152         // For debugging, this is the last information given to the surface flinger.
7153         boolean mSurfaceShown;
7154         int mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
7155         int mSurfaceLayer;
7156         float mSurfaceAlpha;
7157         
7158         WindowState(Session s, IWindow c, WindowToken token,
7159                WindowState attachedWindow, WindowManager.LayoutParams a,
7160                int viewVisibility) {
7161             mSession = s;
7162             mClient = c;
7163             mToken = token;
7164             mAttrs.copyFrom(a);
7165             mViewVisibility = viewVisibility;
7166             DeathRecipient deathRecipient = new DeathRecipient();
7167             mAlpha = a.alpha;
7168             if (localLOGV) Slog.v(
7169                 TAG, "Window " + this + " client=" + c.asBinder()
7170                 + " token=" + token + " (" + mAttrs.token + ")");
7171             try {
7172                 c.asBinder().linkToDeath(deathRecipient, 0);
7173             } catch (RemoteException e) {
7174                 mDeathRecipient = null;
7175                 mAttachedWindow = null;
7176                 mLayoutAttached = false;
7177                 mIsImWindow = false;
7178                 mIsWallpaper = false;
7179                 mIsFloatingLayer = false;
7180                 mBaseLayer = 0;
7181                 mSubLayer = 0;
7182                 return;
7183             }
7184             mDeathRecipient = deathRecipient;
7185
7186             if ((mAttrs.type >= FIRST_SUB_WINDOW &&
7187                     mAttrs.type <= LAST_SUB_WINDOW)) {
7188                 // The multiplier here is to reserve space for multiple
7189                 // windows in the same type layer.
7190                 mBaseLayer = mPolicy.windowTypeToLayerLw(
7191                         attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER
7192                         + TYPE_LAYER_OFFSET;
7193                 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
7194                 mAttachedWindow = attachedWindow;
7195                 mAttachedWindow.mChildWindows.add(this);
7196                 mLayoutAttached = mAttrs.type !=
7197                         WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
7198                 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
7199                         || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
7200                 mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
7201                 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
7202             } else {
7203                 // The multiplier here is to reserve space for multiple
7204                 // windows in the same type layer.
7205                 mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
7206                         * TYPE_LAYER_MULTIPLIER
7207                         + TYPE_LAYER_OFFSET;
7208                 mSubLayer = 0;
7209                 mAttachedWindow = null;
7210                 mLayoutAttached = false;
7211                 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
7212                         || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
7213                 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
7214                 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
7215             }
7216
7217             WindowState appWin = this;
7218             while (appWin.mAttachedWindow != null) {
7219                 appWin = mAttachedWindow;
7220             }
7221             WindowToken appToken = appWin.mToken;
7222             while (appToken.appWindowToken == null) {
7223                 WindowToken parent = mTokenMap.get(appToken.token);
7224                 if (parent == null || appToken == parent) {
7225                     break;
7226                 }
7227                 appToken = parent;
7228             }
7229             mRootToken = appToken;
7230             mAppToken = appToken.appWindowToken;
7231
7232             mSurface = null;
7233             mRequestedWidth = 0;
7234             mRequestedHeight = 0;
7235             mLastRequestedWidth = 0;
7236             mLastRequestedHeight = 0;
7237             mXOffset = 0;
7238             mYOffset = 0;
7239             mLayer = 0;
7240             mAnimLayer = 0;
7241             mLastLayer = 0;
7242         }
7243
7244         void attach() {
7245             if (localLOGV) Slog.v(
7246                 TAG, "Attaching " + this + " token=" + mToken
7247                 + ", list=" + mToken.windows);
7248             mSession.windowAddedLocked();
7249         }
7250
7251         public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
7252             mHaveFrame = true;
7253
7254             final Rect container = mContainingFrame;
7255             container.set(pf);
7256
7257             final Rect display = mDisplayFrame;
7258             display.set(df);
7259
7260             if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
7261                 container.intersect(mCompatibleScreenFrame);
7262                 if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
7263                     display.intersect(mCompatibleScreenFrame);
7264                 }
7265             }
7266
7267             final int pw = container.right - container.left;
7268             final int ph = container.bottom - container.top;
7269
7270             int w,h;
7271             if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
7272                 w = mAttrs.width < 0 ? pw : mAttrs.width;
7273                 h = mAttrs.height< 0 ? ph : mAttrs.height;
7274             } else {
7275                 w = mAttrs.width == mAttrs.MATCH_PARENT ? pw : mRequestedWidth;
7276                 h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight;
7277             }
7278
7279             final Rect content = mContentFrame;
7280             content.set(cf);
7281
7282             final Rect visible = mVisibleFrame;
7283             visible.set(vf);
7284
7285             final Rect frame = mFrame;
7286             final int fw = frame.width();
7287             final int fh = frame.height();
7288
7289             //System.out.println("In: w=" + w + " h=" + h + " container=" +
7290             //                   container + " x=" + mAttrs.x + " y=" + mAttrs.y);
7291
7292             Gravity.apply(mAttrs.gravity, w, h, container,
7293                     (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
7294                     (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
7295
7296             //System.out.println("Out: " + mFrame);
7297
7298             // Now make sure the window fits in the overall display.
7299             Gravity.applyDisplay(mAttrs.gravity, df, frame);
7300
7301             // Make sure the content and visible frames are inside of the
7302             // final window frame.
7303             if (content.left < frame.left) content.left = frame.left;
7304             if (content.top < frame.top) content.top = frame.top;
7305             if (content.right > frame.right) content.right = frame.right;
7306             if (content.bottom > frame.bottom) content.bottom = frame.bottom;
7307             if (visible.left < frame.left) visible.left = frame.left;
7308             if (visible.top < frame.top) visible.top = frame.top;
7309             if (visible.right > frame.right) visible.right = frame.right;
7310             if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
7311
7312             final Rect contentInsets = mContentInsets;
7313             contentInsets.left = content.left-frame.left;
7314             contentInsets.top = content.top-frame.top;
7315             contentInsets.right = frame.right-content.right;
7316             contentInsets.bottom = frame.bottom-content.bottom;
7317
7318             final Rect visibleInsets = mVisibleInsets;
7319             visibleInsets.left = visible.left-frame.left;
7320             visibleInsets.top = visible.top-frame.top;
7321             visibleInsets.right = frame.right-visible.right;
7322             visibleInsets.bottom = frame.bottom-visible.bottom;
7323
7324             if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
7325                 updateWallpaperOffsetLocked(this, mDisplay.getWidth(),
7326                         mDisplay.getHeight(), false);
7327             }
7328
7329             if (localLOGV) {
7330                 //if ("com.google.android.youtube".equals(mAttrs.packageName)
7331                 //        && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
7332                     Slog.v(TAG, "Resolving (mRequestedWidth="
7333                             + mRequestedWidth + ", mRequestedheight="
7334                             + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
7335                             + "): frame=" + mFrame.toShortString()
7336                             + " ci=" + contentInsets.toShortString()
7337                             + " vi=" + visibleInsets.toShortString());
7338                 //}
7339             }
7340         }
7341
7342         public Rect getFrameLw() {
7343             return mFrame;
7344         }
7345
7346         public Rect getShownFrameLw() {
7347             return mShownFrame;
7348         }
7349
7350         public Rect getDisplayFrameLw() {
7351             return mDisplayFrame;
7352         }
7353
7354         public Rect getContentFrameLw() {
7355             return mContentFrame;
7356         }
7357
7358         public Rect getVisibleFrameLw() {
7359             return mVisibleFrame;
7360         }
7361
7362         public boolean getGivenInsetsPendingLw() {
7363             return mGivenInsetsPending;
7364         }
7365
7366         public Rect getGivenContentInsetsLw() {
7367             return mGivenContentInsets;
7368         }
7369
7370         public Rect getGivenVisibleInsetsLw() {
7371             return mGivenVisibleInsets;
7372         }
7373
7374         public WindowManager.LayoutParams getAttrs() {
7375             return mAttrs;
7376         }
7377
7378         public int getSurfaceLayer() {
7379             return mLayer;
7380         }
7381
7382         public IApplicationToken getAppToken() {
7383             return mAppToken != null ? mAppToken.appToken : null;
7384         }
7385
7386         public boolean hasAppShownWindows() {
7387             return mAppToken != null ? mAppToken.firstWindowDrawn : false;
7388         }
7389
7390         public void setAnimation(Animation anim) {
7391             if (localLOGV) Slog.v(
7392                 TAG, "Setting animation in " + this + ": " + anim);
7393             mAnimating = false;
7394             mLocalAnimating = false;
7395             mAnimation = anim;
7396             mAnimation.restrictDuration(MAX_ANIMATION_DURATION);
7397             mAnimation.scaleCurrentDuration(mWindowAnimationScale);
7398         }
7399
7400         public void clearAnimation() {
7401             if (mAnimation != null) {
7402                 mAnimating = true;
7403                 mLocalAnimating = false;
7404                 mAnimation = null;
7405             }
7406         }
7407
7408         Surface createSurfaceLocked() {
7409             if (mSurface == null) {
7410                 mReportDestroySurface = false;
7411                 mSurfacePendingDestroy = false;
7412                 mDrawPending = true;
7413                 mCommitDrawPending = false;
7414                 mReadyToShow = false;
7415                 if (mAppToken != null) {
7416                     mAppToken.allDrawn = false;
7417                 }
7418
7419                 int flags = 0;
7420                 if (mAttrs.memoryType == MEMORY_TYPE_PUSH_BUFFERS) {
7421                     flags |= Surface.PUSH_BUFFERS;
7422                 }
7423
7424                 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
7425                     flags |= Surface.SECURE;
7426                 }
7427                 if (DEBUG_VISIBILITY) Slog.v(
7428                     TAG, "Creating surface in session "
7429                     + mSession.mSurfaceSession + " window " + this
7430                     + " w=" + mFrame.width()
7431                     + " h=" + mFrame.height() + " format="
7432                     + mAttrs.format + " flags=" + flags);
7433
7434                 int w = mFrame.width();
7435                 int h = mFrame.height();
7436                 if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
7437                     // for a scaled surface, we always want the requested
7438                     // size.
7439                     w = mRequestedWidth;
7440                     h = mRequestedHeight;
7441                 }
7442
7443                 // Something is wrong and SurfaceFlinger will not like this,
7444                 // try to revert to sane values
7445                 if (w <= 0) w = 1;
7446                 if (h <= 0) h = 1;
7447
7448                 mSurfaceShown = false;
7449                 mSurfaceLayer = 0;
7450                 mSurfaceAlpha = 1;
7451                 mSurfaceX = 0;
7452                 mSurfaceY = 0;
7453                 mSurfaceW = w;
7454                 mSurfaceH = h;
7455                 try {
7456                     mSurface = new Surface(
7457                             mSession.mSurfaceSession, mSession.mPid,
7458                             mAttrs.getTitle().toString(),
7459                             0, w, h, mAttrs.format, flags);
7460                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  CREATE SURFACE "
7461                             + mSurface + " IN SESSION "
7462                             + mSession.mSurfaceSession
7463                             + ": pid=" + mSession.mPid + " format="
7464                             + mAttrs.format + " flags=0x"
7465                             + Integer.toHexString(flags)
7466                             + " / " + this);
7467                 } catch (Surface.OutOfResourcesException e) {
7468                     Slog.w(TAG, "OutOfResourcesException creating surface");
7469                     reclaimSomeSurfaceMemoryLocked(this, "create");
7470                     return null;
7471                 } catch (Exception e) {
7472                     Slog.e(TAG, "Exception creating surface", e);
7473                     return null;
7474                 }
7475
7476                 if (localLOGV) Slog.v(
7477                     TAG, "Got surface: " + mSurface
7478                     + ", set left=" + mFrame.left + " top=" + mFrame.top
7479                     + ", animLayer=" + mAnimLayer);
7480                 if (SHOW_TRANSACTIONS) {
7481                     Slog.i(TAG, ">>> OPEN TRANSACTION");
7482                     if (SHOW_TRANSACTIONS) logSurface(this,
7483                             "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
7484                             mFrame.width() + "x" + mFrame.height() + "), layer=" +
7485                             mAnimLayer + " HIDE", null);
7486                 }
7487                 Surface.openTransaction();
7488                 try {
7489                     try {
7490                         mSurfaceX = mFrame.left + mXOffset;
7491                         mSurfaceY = mFrame.top + mYOffset;
7492                         mSurface.setPosition(mSurfaceX, mSurfaceY);
7493                         mSurfaceLayer = mAnimLayer;
7494                         mSurface.setLayer(mAnimLayer);
7495                         mSurfaceShown = false;
7496                         mSurface.hide();
7497                         if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
7498                             if (SHOW_TRANSACTIONS) logSurface(this, "DITHER", null);
7499                             mSurface.setFlags(Surface.SURFACE_DITHER,
7500                                     Surface.SURFACE_DITHER);
7501                         }
7502                     } catch (RuntimeException e) {
7503                         Slog.w(TAG, "Error creating surface in " + w, e);
7504                         reclaimSomeSurfaceMemoryLocked(this, "create-init");
7505                     }
7506                     mLastHidden = true;
7507                 } finally {
7508                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
7509                     Surface.closeTransaction();
7510                 }
7511                 if (localLOGV) Slog.v(
7512                         TAG, "Created surface " + this);
7513             }
7514             return mSurface;
7515         }
7516
7517         void destroySurfaceLocked() {
7518             // Window is no longer on-screen, so can no longer receive
7519             // key events...  if we were waiting for it to finish
7520             // handling a key event, the wait is over!
7521             mKeyWaiter.finishedKey(mSession, mClient, true,
7522                     KeyWaiter.RETURN_NOTHING);
7523             mKeyWaiter.releasePendingPointerLocked(mSession);
7524             mKeyWaiter.releasePendingTrackballLocked(mSession);
7525
7526             if (mAppToken != null && this == mAppToken.startingWindow) {
7527                 mAppToken.startingDisplayed = false;
7528             }
7529
7530             if (mSurface != null) {
7531                 mDrawPending = false;
7532                 mCommitDrawPending = false;
7533                 mReadyToShow = false;
7534
7535                 int i = mChildWindows.size();
7536                 while (i > 0) {
7537                     i--;
7538                     WindowState c = (WindowState)mChildWindows.get(i);
7539                     c.mAttachedHidden = true;
7540                 }
7541
7542                 if (mReportDestroySurface) {
7543                     mReportDestroySurface = false;
7544                     mSurfacePendingDestroy = true;
7545                     try {
7546                         mClient.dispatchGetNewSurface();
7547                         // We'll really destroy on the next time around.
7548                         return;
7549                     } catch (RemoteException e) {
7550                     }
7551                 }
7552
7553                 try {
7554                     if (DEBUG_VISIBILITY) {
7555                         RuntimeException e = null;
7556                         if (!HIDE_STACK_CRAWLS) {
7557                             e = new RuntimeException();
7558                             e.fillInStackTrace();
7559                         }
7560                         Slog.w(TAG, "Window " + this + " destroying surface "
7561                                 + mSurface + ", session " + mSession, e);
7562                     }
7563                     if (SHOW_TRANSACTIONS) {
7564                         RuntimeException e = null;
7565                         if (!HIDE_STACK_CRAWLS) {
7566                             e = new RuntimeException();
7567                             e.fillInStackTrace();
7568                         }
7569                         if (SHOW_TRANSACTIONS) logSurface(this, "DESTROY", e);
7570                     }
7571                     mSurface.destroy();
7572                 } catch (RuntimeException e) {
7573                     Slog.w(TAG, "Exception thrown when destroying Window " + this
7574                         + " surface " + mSurface + " session " + mSession
7575                         + ": " + e.toString());
7576                 }
7577
7578                 mSurfaceShown = false;
7579                 mSurface = null;
7580             }
7581         }
7582
7583         boolean finishDrawingLocked() {
7584             if (mDrawPending) {
7585                 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Slog.v(
7586                     TAG, "finishDrawingLocked: " + mSurface);
7587                 mCommitDrawPending = true;
7588                 mDrawPending = false;
7589                 return true;
7590             }
7591             return false;
7592         }
7593
7594         // This must be called while inside a transaction.
7595         boolean commitFinishDrawingLocked(long currentTime) {
7596             //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
7597             if (!mCommitDrawPending) {
7598                 return false;
7599             }
7600             mCommitDrawPending = false;
7601             mReadyToShow = true;
7602             final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
7603             final AppWindowToken atoken = mAppToken;
7604             if (atoken == null || atoken.allDrawn || starting) {
7605                 performShowLocked();
7606             }
7607             return true;
7608         }
7609
7610         // This must be called while inside a transaction.
7611         boolean performShowLocked() {
7612             if (DEBUG_VISIBILITY) {
7613                 RuntimeException e = null;
7614                 if (!HIDE_STACK_CRAWLS) {
7615                     e = new RuntimeException();
7616                     e.fillInStackTrace();
7617                 }
7618                 Slog.v(TAG, "performShow on " + this
7619                         + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
7620                         + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
7621             }
7622             if (mReadyToShow && isReadyForDisplay()) {
7623                 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) logSurface(this,
7624                         "SHOW (performShowLocked)", null);
7625                 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
7626                         + " during animation: policyVis=" + mPolicyVisibility
7627                         + " attHidden=" + mAttachedHidden
7628                         + " tok.hiddenRequested="
7629                         + (mAppToken != null ? mAppToken.hiddenRequested : false)
7630                         + " tok.hidden="
7631                         + (mAppToken != null ? mAppToken.hidden : false)
7632                         + " animating=" + mAnimating
7633                         + " tok animating="
7634                         + (mAppToken != null ? mAppToken.animating : false));
7635                 if (!showSurfaceRobustlyLocked(this)) {
7636                     return false;
7637                 }
7638                 mLastAlpha = -1;
7639                 mHasDrawn = true;
7640                 mLastHidden = false;
7641                 mReadyToShow = false;
7642                 enableScreenIfNeededLocked();
7643
7644                 applyEnterAnimationLocked(this);
7645
7646                 int i = mChildWindows.size();
7647                 while (i > 0) {
7648                     i--;
7649                     WindowState c = (WindowState)mChildWindows.get(i);
7650                     if (c.mAttachedHidden) {
7651                         c.mAttachedHidden = false;
7652                         if (c.mSurface != null) {
7653                             c.performShowLocked();
7654                             // It hadn't been shown, which means layout not
7655                             // performed on it, so now we want to make sure to
7656                             // do a layout.  If called from within the transaction
7657                             // loop, this will cause it to restart with a new
7658                             // layout.
7659                             mLayoutNeeded = true;
7660                         }
7661                     }
7662                 }
7663
7664                 if (mAttrs.type != TYPE_APPLICATION_STARTING
7665                         && mAppToken != null) {
7666                     mAppToken.firstWindowDrawn = true;
7667
7668                     if (mAppToken.startingData != null) {
7669                         if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG,
7670                                 "Finish starting " + mToken
7671                                 + ": first real window is shown, no animation");
7672                         // If this initial window is animating, stop it -- we
7673                         // will do an animation to reveal it from behind the
7674                         // starting window, so there is no need for it to also
7675                         // be doing its own stuff.
7676                         if (mAnimation != null) {
7677                             mAnimation = null;
7678                             // Make sure we clean up the animation.
7679                             mAnimating = true;
7680                         }
7681                         mFinishedStarting.add(mAppToken);
7682                         mH.sendEmptyMessage(H.FINISHED_STARTING);
7683                     }
7684                     mAppToken.updateReportedVisibilityLocked();
7685                 }
7686             }
7687             return true;
7688         }
7689
7690         // This must be called while inside a transaction.  Returns true if
7691         // there is more animation to run.
7692         boolean stepAnimationLocked(long currentTime, int dw, int dh) {
7693             if (!mDisplayFrozen && mPolicy.isScreenOn()) {
7694                 // We will run animations as long as the display isn't frozen.
7695
7696                 if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
7697                     mHasTransformation = true;
7698                     mHasLocalTransformation = true;
7699                     if (!mLocalAnimating) {
7700                         if (DEBUG_ANIM) Slog.v(
7701                             TAG, "Starting animation in " + this +
7702                             " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
7703                             " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale);
7704                         mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
7705                         mAnimation.setStartTime(currentTime);
7706                         mLocalAnimating = true;
7707                         mAnimating = true;
7708                     }
7709                     mTransformation.clear();
7710                     final boolean more = mAnimation.getTransformation(
7711                         currentTime, mTransformation);
7712                     if (DEBUG_ANIM) Slog.v(
7713                         TAG, "Stepped animation in " + this +
7714                         ": more=" + more + ", xform=" + mTransformation);
7715                     if (more) {
7716                         // we're not done!
7717                         return true;
7718                     }
7719                     if (DEBUG_ANIM) Slog.v(
7720                         TAG, "Finished animation in " + this +
7721                         " @ " + currentTime);
7722                     mAnimation = null;
7723                     //WindowManagerService.this.dump();
7724                 }
7725                 mHasLocalTransformation = false;
7726                 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
7727                         && mAppToken.animation != null) {
7728                     // When our app token is animating, we kind-of pretend like
7729                     // we are as well.  Note the mLocalAnimating mAnimationIsEntrance
7730                     // part of this check means that we will only do this if
7731                     // our window is not currently exiting, or it is not
7732                     // locally animating itself.  The idea being that one that
7733                     // is exiting and doing a local animation should be removed
7734                     // once that animation is done.
7735                     mAnimating = true;
7736                     mHasTransformation = true;
7737                     mTransformation.clear();
7738                     return false;
7739                 } else if (mHasTransformation) {
7740                     // Little trick to get through the path below to act like
7741                     // we have finished an animation.
7742                     mAnimating = true;
7743                 } else if (isAnimating()) {
7744                     mAnimating = true;
7745                 }
7746             } else if (mAnimation != null) {
7747                 // If the display is frozen, and there is a pending animation,
7748                 // clear it and make sure we run the cleanup code.
7749                 mAnimating = true;
7750                 mLocalAnimating = true;
7751                 mAnimation = null;
7752             }
7753
7754             if (!mAnimating && !mLocalAnimating) {
7755                 return false;
7756             }
7757
7758             if (DEBUG_ANIM) Slog.v(
7759                 TAG, "Animation done in " + this + ": exiting=" + mExiting
7760                 + ", reportedVisible="
7761                 + (mAppToken != null ? mAppToken.reportedVisible : false));
7762
7763             mAnimating = false;
7764             mLocalAnimating = false;
7765             mAnimation = null;
7766             mAnimLayer = mLayer;
7767             if (mIsImWindow) {
7768                 mAnimLayer += mInputMethodAnimLayerAdjustment;
7769             } else if (mIsWallpaper) {
7770                 mAnimLayer += mWallpaperAnimLayerAdjustment;
7771             }
7772             if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
7773                     + " anim layer: " + mAnimLayer);
7774             mHasTransformation = false;
7775             mHasLocalTransformation = false;
7776             if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
7777                 if (DEBUG_VISIBILITY) {
7778                     Slog.v(TAG, "Policy visibility changing after anim in " + this + ": "
7779                             + mPolicyVisibilityAfterAnim);
7780                 }
7781                 mPolicyVisibility = mPolicyVisibilityAfterAnim;
7782                 if (!mPolicyVisibility) {
7783                     if (mCurrentFocus == this) {
7784                         mFocusMayChange = true;
7785                     }
7786                     // Window is no longer visible -- make sure if we were waiting
7787                     // for it to be displayed before enabling the display, that
7788                     // we allow the display to be enabled now.
7789                     enableScreenIfNeededLocked();
7790                 }
7791             }
7792             mTransformation.clear();
7793             if (mHasDrawn
7794                     && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
7795                     && mAppToken != null
7796                     && mAppToken.firstWindowDrawn
7797                     && mAppToken.startingData != null) {
7798                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting "
7799                         + mToken + ": first real window done animating");
7800                 mFinishedStarting.add(mAppToken);
7801                 mH.sendEmptyMessage(H.FINISHED_STARTING);
7802             }
7803
7804             finishExit();
7805
7806             if (mAppToken != null) {
7807                 mAppToken.updateReportedVisibilityLocked();
7808             }
7809
7810             return false;
7811         }
7812
7813         void finishExit() {
7814             if (DEBUG_ANIM) Slog.v(
7815                     TAG, "finishExit in " + this
7816                     + ": exiting=" + mExiting
7817                     + " remove=" + mRemoveOnExit
7818                     + " windowAnimating=" + isWindowAnimating());
7819
7820             final int N = mChildWindows.size();
7821             for (int i=0; i<N; i++) {
7822                 ((WindowState)mChildWindows.get(i)).finishExit();
7823             }
7824
7825             if (!mExiting) {
7826                 return;
7827             }
7828
7829             if (isWindowAnimating()) {
7830                 return;
7831             }
7832
7833             if (localLOGV) Slog.v(
7834                     TAG, "Exit animation finished in " + this
7835                     + ": remove=" + mRemoveOnExit);
7836             if (mSurface != null) {
7837                 mDestroySurface.add(this);
7838                 mDestroying = true;
7839                 if (SHOW_TRANSACTIONS) logSurface(this, "HIDE (finishExit)", null);
7840                 mSurfaceShown = false;
7841                 try {
7842                     mSurface.hide();
7843                 } catch (RuntimeException e) {
7844                     Slog.w(TAG, "Error hiding surface in " + this, e);
7845                 }
7846                 mLastHidden = true;
7847                 mKeyWaiter.releasePendingPointerLocked(mSession);
7848             }
7849             mExiting = false;
7850             if (mRemoveOnExit) {
7851                 mPendingRemove.add(this);
7852                 mRemoveOnExit = false;
7853             }
7854         }
7855
7856         boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
7857             if (dsdx < .99999f || dsdx > 1.00001f) return false;
7858             if (dtdy < .99999f || dtdy > 1.00001f) return false;
7859             if (dtdx < -.000001f || dtdx > .000001f) return false;
7860             if (dsdy < -.000001f || dsdy > .000001f) return false;
7861             return true;
7862         }
7863
7864         void computeShownFrameLocked() {
7865             final boolean selfTransformation = mHasLocalTransformation;
7866             Transformation attachedTransformation =
7867                     (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
7868                     ? mAttachedWindow.mTransformation : null;
7869             Transformation appTransformation =
7870                     (mAppToken != null && mAppToken.hasTransformation)
7871                     ? mAppToken.transformation : null;
7872
7873             // Wallpapers are animated based on the "real" window they
7874             // are currently targeting.
7875             if (mAttrs.type == TYPE_WALLPAPER && mLowerWallpaperTarget == null
7876                     && mWallpaperTarget != null) {
7877                 if (mWallpaperTarget.mHasLocalTransformation &&
7878                         mWallpaperTarget.mAnimation != null &&
7879                         !mWallpaperTarget.mAnimation.getDetachWallpaper()) {
7880                     attachedTransformation = mWallpaperTarget.mTransformation;
7881                     if (DEBUG_WALLPAPER && attachedTransformation != null) {
7882                         Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
7883                     }
7884                 }
7885                 if (mWallpaperTarget.mAppToken != null &&
7886                         mWallpaperTarget.mAppToken.hasTransformation &&
7887                         mWallpaperTarget.mAppToken.animation != null &&
7888                         !mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
7889                     appTransformation = mWallpaperTarget.mAppToken.transformation;
7890                     if (DEBUG_WALLPAPER && appTransformation != null) {
7891                         Slog.v(TAG, "WP target app xform: " + appTransformation);
7892                     }
7893                 }
7894             }
7895
7896             if (selfTransformation || attachedTransformation != null
7897                     || appTransformation != null) {
7898                 // cache often used attributes locally
7899                 final Rect frame = mFrame;
7900                 final float tmpFloats[] = mTmpFloats;
7901                 final Matrix tmpMatrix = mTmpMatrix;
7902
7903                 // Compute the desired transformation.
7904                 tmpMatrix.setTranslate(0, 0);
7905                 if (selfTransformation) {
7906                     tmpMatrix.postConcat(mTransformation.getMatrix());
7907                 }
7908                 tmpMatrix.postTranslate(frame.left, frame.top);
7909                 if (attachedTransformation != null) {
7910                     tmpMatrix.postConcat(attachedTransformation.getMatrix());
7911                 }
7912                 if (appTransformation != null) {
7913                     tmpMatrix.postConcat(appTransformation.getMatrix());
7914                 }
7915
7916                 // "convert" it into SurfaceFlinger's format
7917                 // (a 2x2 matrix + an offset)
7918                 // Here we must not transform the position of the surface
7919                 // since it is already included in the transformation.
7920                 //Slog.i(TAG, "Transform: " + matrix);
7921
7922                 tmpMatrix.getValues(tmpFloats);
7923                 mDsDx = tmpFloats[Matrix.MSCALE_X];
7924                 mDtDx = tmpFloats[Matrix.MSKEW_X];
7925                 mDsDy = tmpFloats[Matrix.MSKEW_Y];
7926                 mDtDy = tmpFloats[Matrix.MSCALE_Y];
7927                 int x = (int)tmpFloats[Matrix.MTRANS_X] + mXOffset;
7928                 int y = (int)tmpFloats[Matrix.MTRANS_Y] + mYOffset;
7929                 int w = frame.width();
7930                 int h = frame.height();
7931                 mShownFrame.set(x, y, x+w, y+h);
7932
7933                 // Now set the alpha...  but because our current hardware
7934                 // can't do alpha transformation on a non-opaque surface,
7935                 // turn it off if we are running an animation that is also
7936                 // transforming since it is more important to have that
7937                 // animation be smooth.
7938                 mShownAlpha = mAlpha;
7939                 if (!mLimitedAlphaCompositing
7940                         || (!PixelFormat.formatHasAlpha(mAttrs.format)
7941                         || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
7942                                 && x == frame.left && y == frame.top))) {
7943                     //Slog.i(TAG, "Applying alpha transform");
7944                     if (selfTransformation) {
7945                         mShownAlpha *= mTransformation.getAlpha();
7946                     }
7947                     if (attachedTransformation != null) {
7948                         mShownAlpha *= attachedTransformation.getAlpha();
7949                     }
7950                     if (appTransformation != null) {
7951                         mShownAlpha *= appTransformation.getAlpha();
7952                     }
7953                 } else {
7954                     //Slog.i(TAG, "Not applying alpha transform");
7955                 }
7956
7957                 if (localLOGV) Slog.v(
7958                     TAG, "Continuing animation in " + this +
7959                     ": " + mShownFrame +
7960                     ", alpha=" + mTransformation.getAlpha());
7961                 return;
7962             }
7963
7964             mShownFrame.set(mFrame);
7965             if (mXOffset != 0 || mYOffset != 0) {
7966                 mShownFrame.offset(mXOffset, mYOffset);
7967             }
7968             mShownAlpha = mAlpha;
7969             mDsDx = 1;
7970             mDtDx = 0;
7971             mDsDy = 0;
7972             mDtDy = 1;
7973         }
7974
7975         /**
7976          * Is this window visible?  It is not visible if there is no
7977          * surface, or we are in the process of running an exit animation
7978          * that will remove the surface, or its app token has been hidden.
7979          */
7980         public boolean isVisibleLw() {
7981             final AppWindowToken atoken = mAppToken;
7982             return mSurface != null && mPolicyVisibility && !mAttachedHidden
7983                     && (atoken == null || !atoken.hiddenRequested)
7984                     && !mExiting && !mDestroying;
7985         }
7986
7987         /**
7988          * Like {@link #isVisibleLw}, but also counts a window that is currently
7989          * "hidden" behind the keyguard as visible.  This allows us to apply
7990          * things like window flags that impact the keyguard.
7991          * XXX I am starting to think we need to have ANOTHER visibility flag
7992          * for this "hidden behind keyguard" state rather than overloading
7993          * mPolicyVisibility.  Ungh.
7994          */
7995         public boolean isVisibleOrBehindKeyguardLw() {
7996             final AppWindowToken atoken = mAppToken;
7997             return mSurface != null && !mAttachedHidden
7998                     && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
7999                     && (mOrientationChanging || (!mDrawPending && !mCommitDrawPending))
8000                     && !mExiting && !mDestroying;
8001         }
8002
8003         /**
8004          * Is this window visible, ignoring its app token?  It is not visible
8005          * if there is no surface, or we are in the process of running an exit animation
8006          * that will remove the surface.
8007          */
8008         public boolean isWinVisibleLw() {
8009             final AppWindowToken atoken = mAppToken;
8010             return mSurface != null && mPolicyVisibility && !mAttachedHidden
8011                     && (atoken == null || !atoken.hiddenRequested || atoken.animating)
8012                     && !mExiting && !mDestroying;
8013         }
8014
8015         /**
8016          * The same as isVisible(), but follows the current hidden state of
8017          * the associated app token, not the pending requested hidden state.
8018          */
8019         boolean isVisibleNow() {
8020             return mSurface != null && mPolicyVisibility && !mAttachedHidden
8021                     && !mRootToken.hidden && !mExiting && !mDestroying;
8022         }
8023
8024         /**
8025          * Same as isVisible(), but we also count it as visible between the
8026          * call to IWindowSession.add() and the first relayout().
8027          */
8028         boolean isVisibleOrAdding() {
8029             final AppWindowToken atoken = mAppToken;
8030             return ((mSurface != null && !mReportDestroySurface)
8031                             || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
8032                     && mPolicyVisibility && !mAttachedHidden
8033                     && (atoken == null || !atoken.hiddenRequested)
8034                     && !mExiting && !mDestroying;
8035         }
8036
8037         /**
8038          * Is this window currently on-screen?  It is on-screen either if it
8039          * is visible or it is currently running an animation before no longer
8040          * being visible.
8041          */
8042         boolean isOnScreen() {
8043             final AppWindowToken atoken = mAppToken;
8044             if (atoken != null) {
8045                 return mSurface != null && mPolicyVisibility && !mDestroying
8046                         && ((!mAttachedHidden && !atoken.hiddenRequested)
8047                                 || mAnimation != null || atoken.animation != null);
8048             } else {
8049                 return mSurface != null && mPolicyVisibility && !mDestroying
8050                         && (!mAttachedHidden || mAnimation != null);
8051             }
8052         }
8053
8054         /**
8055          * Like isOnScreen(), but we don't return true if the window is part
8056          * of a transition that has not yet been started.
8057          */
8058         boolean isReadyForDisplay() {
8059             if (mRootToken.waitingToShow &&
8060                     mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
8061                 return false;
8062             }
8063             final AppWindowToken atoken = mAppToken;
8064             final boolean animating = atoken != null
8065                     ? (atoken.animation != null) : false;
8066             return mSurface != null && mPolicyVisibility && !mDestroying
8067                     && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
8068                                     && !mRootToken.hidden)
8069                             || mAnimation != null || animating);
8070         }
8071
8072         /** Is the window or its container currently animating? */
8073         boolean isAnimating() {
8074             final WindowState attached = mAttachedWindow;
8075             final AppWindowToken atoken = mAppToken;
8076             return mAnimation != null
8077                     || (attached != null && attached.mAnimation != null)
8078                     || (atoken != null &&
8079                             (atoken.animation != null
8080                                     || atoken.inPendingTransaction));
8081         }
8082
8083         /** Is this window currently animating? */
8084         boolean isWindowAnimating() {
8085             return mAnimation != null;
8086         }
8087
8088         /**
8089          * Like isOnScreen, but returns false if the surface hasn't yet
8090          * been drawn.
8091          */
8092         public boolean isDisplayedLw() {
8093             final AppWindowToken atoken = mAppToken;
8094             return mSurface != null && mPolicyVisibility && !mDestroying
8095                 && !mDrawPending && !mCommitDrawPending
8096                 && ((!mAttachedHidden &&
8097                         (atoken == null || !atoken.hiddenRequested))
8098                         || mAnimating);
8099         }
8100
8101         /**
8102          * Returns true if the window has a surface that it has drawn a
8103          * complete UI in to.  Note that this returns true if the orientation
8104          * is changing even if the window hasn't redrawn because we don't want
8105          * to stop things from executing during that time.
8106          */
8107         public boolean isDrawnLw() {
8108             final AppWindowToken atoken = mAppToken;
8109             return mSurface != null && !mDestroying
8110                 && (mOrientationChanging || (!mDrawPending && !mCommitDrawPending));
8111         }
8112
8113         public boolean fillsScreenLw(int screenWidth, int screenHeight,
8114                                    boolean shownFrame, boolean onlyOpaque) {
8115             if (mSurface == null) {
8116                 return false;
8117             }
8118             if (mAppToken != null && !mAppToken.appFullscreen) {
8119                 return false;
8120             }
8121             if (onlyOpaque && mAttrs.format != PixelFormat.OPAQUE) {
8122                 return false;
8123             }
8124             final Rect frame = shownFrame ? mShownFrame : mFrame;
8125
8126             if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
8127                 return frame.left <= mCompatibleScreenFrame.left &&
8128                         frame.top <= mCompatibleScreenFrame.top &&
8129                         frame.right >= mCompatibleScreenFrame.right &&
8130                         frame.bottom >= mCompatibleScreenFrame.bottom;
8131             } else {
8132                 return frame.left <= 0 && frame.top <= 0
8133                         && frame.right >= screenWidth
8134                         && frame.bottom >= screenHeight;
8135             }
8136         }
8137
8138         /**
8139          * Return true if the window is opaque and fully drawn.  This indicates
8140          * it may obscure windows behind it.
8141          */
8142         boolean isOpaqueDrawn() {
8143             return (mAttrs.format == PixelFormat.OPAQUE
8144                             || mAttrs.type == TYPE_WALLPAPER)
8145                     && mSurface != null && mAnimation == null
8146                     && (mAppToken == null || mAppToken.animation == null)
8147                     && !mDrawPending && !mCommitDrawPending;
8148         }
8149
8150         boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
8151             return
8152                  // only if the application is requesting compatible window
8153                  (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
8154                  // only if it's visible
8155                  mHasDrawn && mViewVisibility == View.VISIBLE &&
8156                  // and only if the application fills the compatible screen
8157                  mFrame.left <= mCompatibleScreenFrame.left &&
8158                  mFrame.top <= mCompatibleScreenFrame.top &&
8159                  mFrame.right >= mCompatibleScreenFrame.right &&
8160                  mFrame.bottom >= mCompatibleScreenFrame.bottom &&
8161                  // and starting window do not need background filler
8162                  mAttrs.type != mAttrs.TYPE_APPLICATION_STARTING;
8163         }
8164
8165         boolean isFullscreen(int screenWidth, int screenHeight) {
8166             return mFrame.left <= 0 && mFrame.top <= 0 &&
8167                     mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
8168         }
8169
8170         void removeLocked() {
8171             if (mAttachedWindow != null) {
8172                 mAttachedWindow.mChildWindows.remove(this);
8173             }
8174             destroySurfaceLocked();
8175             mSession.windowRemovedLocked();
8176             try {
8177                 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
8178             } catch (RuntimeException e) {
8179                 // Ignore if it has already been removed (usually because
8180                 // we are doing this as part of processing a death note.)
8181             }
8182         }
8183
8184         private class DeathRecipient implements IBinder.DeathRecipient {
8185             public void binderDied() {
8186                 try {
8187                     synchronized(mWindowMap) {
8188                         WindowState win = windowForClientLocked(mSession, mClient, false);
8189                         Slog.i(TAG, "WIN DEATH: " + win);
8190                         if (win != null) {
8191                             removeWindowLocked(mSession, win);
8192                         }
8193                     }
8194                 } catch (IllegalArgumentException ex) {
8195                     // This will happen if the window has already been
8196                     // removed.
8197                 }
8198             }
8199         }
8200
8201         /** Returns true if this window desires key events. */
8202         public final boolean canReceiveKeys() {
8203             return     isVisibleOrAdding()
8204                     && (mViewVisibility == View.VISIBLE)
8205                     && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
8206         }
8207
8208         public boolean hasDrawnLw() {
8209             return mHasDrawn;
8210         }
8211
8212         public boolean showLw(boolean doAnimation) {
8213             return showLw(doAnimation, true);
8214         }
8215
8216         boolean showLw(boolean doAnimation, boolean requestAnim) {
8217             if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
8218                 return false;
8219             }
8220             if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
8221             if (doAnimation) {
8222                 if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
8223                         + mPolicyVisibility + " mAnimation=" + mAnimation);
8224                 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
8225                     doAnimation = false;
8226                 } else if (mPolicyVisibility && mAnimation == null) {
8227                     // Check for the case where we are currently visible and
8228                     // not animating; we do not want to do animation at such a
8229                     // point to become visible when we already are.
8230                     doAnimation = false;
8231                 }
8232             }
8233             mPolicyVisibility = true;
8234             mPolicyVisibilityAfterAnim = true;
8235             if (doAnimation) {
8236                 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
8237             }
8238             if (requestAnim) {
8239                 requestAnimationLocked(0);
8240             }
8241             return true;
8242         }
8243
8244         public boolean hideLw(boolean doAnimation) {
8245             return hideLw(doAnimation, true);
8246         }
8247
8248         boolean hideLw(boolean doAnimation, boolean requestAnim) {
8249             if (doAnimation) {
8250                 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
8251                     doAnimation = false;
8252                 }
8253             }
8254             boolean current = doAnimation ? mPolicyVisibilityAfterAnim
8255                     : mPolicyVisibility;
8256             if (!current) {
8257                 return false;
8258             }
8259             if (doAnimation) {
8260                 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
8261                 if (mAnimation == null) {
8262                     doAnimation = false;
8263                 }
8264             }
8265             if (doAnimation) {
8266                 mPolicyVisibilityAfterAnim = false;
8267             } else {
8268                 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
8269                 mPolicyVisibilityAfterAnim = false;
8270                 mPolicyVisibility = false;
8271                 // Window is no longer visible -- make sure if we were waiting
8272                 // for it to be displayed before enabling the display, that
8273                 // we allow the display to be enabled now.
8274                 enableScreenIfNeededLocked();
8275                 if (mCurrentFocus == this) {
8276                     mFocusMayChange = true;
8277                 }
8278             }
8279             if (requestAnim) {
8280                 requestAnimationLocked(0);
8281             }
8282             return true;
8283         }
8284
8285         void dump(PrintWriter pw, String prefix) {
8286             pw.print(prefix); pw.print("mSession="); pw.print(mSession);
8287                     pw.print(" mClient="); pw.println(mClient.asBinder());
8288             pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
8289             if (mAttachedWindow != null || mLayoutAttached) {
8290                 pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
8291                         pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
8292             }
8293             if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
8294                 pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
8295                         pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
8296                         pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
8297                         pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
8298             }
8299             pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
8300                     pw.print(" mSubLayer="); pw.print(mSubLayer);
8301                     pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
8302                     pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
8303                           : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
8304                     pw.print("="); pw.print(mAnimLayer);
8305                     pw.print(" mLastLayer="); pw.println(mLastLayer);
8306             if (mSurface != null) {
8307                 pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
8308                 pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
8309                         pw.print(" layer="); pw.print(mSurfaceLayer);
8310                         pw.print(" alpha="); pw.print(mSurfaceAlpha);
8311                         pw.print(" rect=("); pw.print(mSurfaceX);
8312                         pw.print(","); pw.print(mSurfaceY);
8313                         pw.print(") "); pw.print(mSurfaceW);
8314                         pw.print(" x "); pw.println(mSurfaceH);
8315             }
8316             pw.print(prefix); pw.print("mToken="); pw.println(mToken);
8317             pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
8318             if (mAppToken != null) {
8319                 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
8320             }
8321             if (mTargetAppToken != null) {
8322                 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
8323             }
8324             pw.print(prefix); pw.print("mViewVisibility=0x");
8325                     pw.print(Integer.toHexString(mViewVisibility));
8326                     pw.print(" mLastHidden="); pw.print(mLastHidden);
8327                     pw.print(" mHaveFrame="); pw.print(mHaveFrame);
8328                     pw.print(" mObscured="); pw.println(mObscured);
8329             if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
8330                 pw.print(prefix); pw.print("mPolicyVisibility=");
8331                         pw.print(mPolicyVisibility);
8332                         pw.print(" mPolicyVisibilityAfterAnim=");
8333                         pw.print(mPolicyVisibilityAfterAnim);
8334                         pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
8335             }
8336             if (!mRelayoutCalled) {
8337                 pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
8338             }
8339             pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
8340                     pw.print(" h="); pw.print(mRequestedHeight);
8341                     pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
8342             if (mXOffset != 0 || mYOffset != 0) {
8343                 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
8344                         pw.print(" y="); pw.println(mYOffset);
8345             }
8346             pw.print(prefix); pw.print("mGivenContentInsets=");
8347                     mGivenContentInsets.printShortString(pw);
8348                     pw.print(" mGivenVisibleInsets=");
8349                     mGivenVisibleInsets.printShortString(pw);
8350                     pw.println();
8351             if (mTouchableInsets != 0 || mGivenInsetsPending) {
8352                 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
8353                         pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
8354             }
8355             pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
8356             pw.print(prefix); pw.print("mShownFrame=");
8357                     mShownFrame.printShortString(pw);
8358                     pw.print(" last="); mLastShownFrame.printShortString(pw);
8359                     pw.println();
8360             pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
8361                     pw.print(" last="); mLastFrame.printShortString(pw);
8362                     pw.println();
8363             pw.print(prefix); pw.print("mContainingFrame=");
8364                     mContainingFrame.printShortString(pw);
8365                     pw.print(" mDisplayFrame=");
8366                     mDisplayFrame.printShortString(pw);
8367                     pw.println();
8368             pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
8369                     pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
8370                     pw.println();
8371             pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
8372                     pw.print(" last="); mLastContentInsets.printShortString(pw);
8373                     pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
8374                     pw.print(" last="); mLastVisibleInsets.printShortString(pw);
8375                     pw.println();
8376             if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
8377                 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
8378                         pw.print(" mAlpha="); pw.print(mAlpha);
8379                         pw.print(" mLastAlpha="); pw.println(mLastAlpha);
8380             }
8381             if (mAnimating || mLocalAnimating || mAnimationIsEntrance
8382                     || mAnimation != null) {
8383                 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
8384                         pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
8385                         pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
8386                         pw.print(" mAnimation="); pw.println(mAnimation);
8387             }
8388             if (mHasTransformation || mHasLocalTransformation) {
8389                 pw.print(prefix); pw.print("XForm: has=");
8390                         pw.print(mHasTransformation);
8391                         pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
8392                         pw.print(" "); mTransformation.printShortString(pw);
8393                         pw.println();
8394             }
8395             pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
8396                     pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
8397                     pw.print(" mReadyToShow="); pw.print(mReadyToShow);
8398                     pw.print(" mHasDrawn="); pw.println(mHasDrawn);
8399             if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
8400                 pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
8401                         pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
8402                         pw.print(" mDestroying="); pw.print(mDestroying);
8403                         pw.print(" mRemoved="); pw.println(mRemoved);
8404             }
8405             if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
8406                 pw.print(prefix); pw.print("mOrientationChanging=");
8407                         pw.print(mOrientationChanging);
8408                         pw.print(" mAppFreezing="); pw.print(mAppFreezing);
8409                         pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
8410             }
8411             if (mHScale != 1 || mVScale != 1) {
8412                 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
8413                         pw.print(" mVScale="); pw.println(mVScale);
8414             }
8415             if (mWallpaperX != -1 || mWallpaperY != -1) {
8416                 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
8417                         pw.print(" mWallpaperY="); pw.println(mWallpaperY);
8418             }
8419             if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
8420                 pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
8421                         pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
8422             }
8423         }
8424
8425         @Override
8426         public String toString() {
8427             return "Window{"
8428                 + Integer.toHexString(System.identityHashCode(this))
8429                 + " " + mAttrs.getTitle() + " paused=" + mToken.paused + "}";
8430         }
8431     }
8432
8433     // -------------------------------------------------------------
8434     // Window Token State
8435     // -------------------------------------------------------------
8436
8437     class WindowToken {
8438         // The actual token.
8439         final IBinder token;
8440
8441         // The type of window this token is for, as per WindowManager.LayoutParams.
8442         final int windowType;
8443
8444         // Set if this token was explicitly added by a client, so should
8445         // not be removed when all windows are removed.
8446         final boolean explicit;
8447
8448         // For printing.
8449         String stringName;
8450
8451         // If this is an AppWindowToken, this is non-null.
8452         AppWindowToken appWindowToken;
8453
8454         // All of the windows associated with this token.
8455         final ArrayList<WindowState> windows = new ArrayList<WindowState>();
8456
8457         // Is key dispatching paused for this token?
8458         boolean paused = false;
8459
8460         // Should this token's windows be hidden?
8461         boolean hidden;
8462
8463         // Temporary for finding which tokens no longer have visible windows.
8464         boolean hasVisible;
8465
8466         // Set to true when this token is in a pending transaction where it
8467         // will be shown.
8468         boolean waitingToShow;
8469
8470         // Set to true when this token is in a pending transaction where it
8471         // will be hidden.
8472         boolean waitingToHide;
8473
8474         // Set to true when this token is in a pending transaction where its
8475         // windows will be put to the bottom of the list.
8476         boolean sendingToBottom;
8477
8478         // Set to true when this token is in a pending transaction where its
8479         // windows will be put to the top of the list.
8480         boolean sendingToTop;
8481
8482         WindowToken(IBinder _token, int type, boolean _explicit) {
8483             token = _token;
8484             windowType = type;
8485             explicit = _explicit;
8486         }
8487
8488         void dump(PrintWriter pw, String prefix) {
8489             pw.print(prefix); pw.print("token="); pw.println(token);
8490             pw.print(prefix); pw.print("windows="); pw.println(windows);
8491             pw.print(prefix); pw.print("windowType="); pw.print(windowType);
8492                     pw.print(" hidden="); pw.print(hidden);
8493                     pw.print(" hasVisible="); pw.println(hasVisible);
8494             if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) {
8495                 pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
8496                         pw.print(" waitingToHide="); pw.print(waitingToHide);
8497                         pw.print(" sendingToBottom="); pw.print(sendingToBottom);
8498                         pw.print(" sendingToTop="); pw.println(sendingToTop);
8499             }
8500         }
8501
8502         @Override
8503         public String toString() {
8504             if (stringName == null) {
8505                 StringBuilder sb = new StringBuilder();
8506                 sb.append("WindowToken{");
8507                 sb.append(Integer.toHexString(System.identityHashCode(this)));
8508                 sb.append(" token="); sb.append(token); sb.append('}');
8509                 stringName = sb.toString();
8510             }
8511             return stringName;
8512         }
8513     };
8514
8515     class AppWindowToken extends WindowToken {
8516         // Non-null only for application tokens.
8517         final IApplicationToken appToken;
8518
8519         // All of the windows and child windows that are included in this
8520         // application token.  Note this list is NOT sorted!
8521         final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
8522
8523         int groupId = -1;
8524         boolean appFullscreen;
8525         int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
8526
8527         // These are used for determining when all windows associated with
8528         // an activity have been drawn, so they can be made visible together
8529         // at the same time.
8530         int lastTransactionSequence = mTransactionSequence-1;
8531         int numInterestingWindows;
8532         int numDrawnWindows;
8533         boolean inPendingTransaction;
8534         boolean allDrawn;
8535
8536         // Is this token going to be hidden in a little while?  If so, it
8537         // won't be taken into account for setting the screen orientation.
8538         boolean willBeHidden;
8539
8540         // Is this window's surface needed?  This is almost like hidden, except
8541         // it will sometimes be true a little earlier: when the token has
8542         // been shown, but is still waiting for its app transition to execute
8543         // before making its windows shown.
8544         boolean hiddenRequested;
8545
8546         // Have we told the window clients to hide themselves?
8547         boolean clientHidden;
8548
8549         // Last visibility state we reported to the app token.
8550         boolean reportedVisible;
8551
8552         // Set to true when the token has been removed from the window mgr.
8553         boolean removed;
8554
8555         // Have we been asked to have this token keep the screen frozen?
8556         boolean freezingScreen;
8557
8558         boolean animating;
8559         Animation animation;
8560         boolean hasTransformation;
8561         final Transformation transformation = new Transformation();
8562
8563         // Offset to the window of all layers in the token, for use by
8564         // AppWindowToken animations.
8565         int animLayerAdjustment;
8566
8567         // Information about an application starting window if displayed.
8568         StartingData startingData;
8569         WindowState startingWindow;
8570         View startingView;
8571         boolean startingDisplayed;
8572         boolean startingMoved;
8573         boolean firstWindowDrawn;
8574
8575         AppWindowToken(IApplicationToken _token) {
8576             super(_token.asBinder(),
8577                     WindowManager.LayoutParams.TYPE_APPLICATION, true);
8578             appWindowToken = this;
8579             appToken = _token;
8580         }
8581
8582         public void setAnimation(Animation anim) {
8583             if (localLOGV) Slog.v(
8584                 TAG, "Setting animation in " + this + ": " + anim);
8585             animation = anim;
8586             animating = false;
8587             anim.restrictDuration(MAX_ANIMATION_DURATION);
8588             anim.scaleCurrentDuration(mTransitionAnimationScale);
8589             int zorder = anim.getZAdjustment();
8590             int adj = 0;
8591             if (zorder == Animation.ZORDER_TOP) {
8592                 adj = TYPE_LAYER_OFFSET;
8593             } else if (zorder == Animation.ZORDER_BOTTOM) {
8594                 adj = -TYPE_LAYER_OFFSET;
8595             }
8596
8597             if (animLayerAdjustment != adj) {
8598                 animLayerAdjustment = adj;
8599                 updateLayers();
8600             }
8601         }
8602
8603         public void setDummyAnimation() {
8604             if (animation == null) {
8605                 if (localLOGV) Slog.v(
8606                     TAG, "Setting dummy animation in " + this);
8607                 animation = sDummyAnimation;
8608             }
8609         }
8610
8611         public void clearAnimation() {
8612             if (animation != null) {
8613                 animation = null;
8614                 animating = true;
8615             }
8616         }
8617
8618         void updateLayers() {
8619             final int N = allAppWindows.size();
8620             final int adj = animLayerAdjustment;
8621             for (int i=0; i<N; i++) {
8622                 WindowState w = allAppWindows.get(i);
8623                 w.mAnimLayer = w.mLayer + adj;
8624                 if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": "
8625                         + w.mAnimLayer);
8626                 if (w == mInputMethodTarget) {
8627                     setInputMethodAnimLayerAdjustment(adj);
8628                 }
8629                 if (w == mWallpaperTarget && mLowerWallpaperTarget == null) {
8630                     setWallpaperAnimLayerAdjustmentLocked(adj);
8631                 }
8632             }
8633         }
8634
8635         void sendAppVisibilityToClients() {
8636             final int N = allAppWindows.size();
8637             for (int i=0; i<N; i++) {
8638                 WindowState win = allAppWindows.get(i);
8639                 if (win == startingWindow && clientHidden) {
8640                     // Don't hide the starting window.
8641                     continue;
8642                 }
8643                 try {
8644                     if (DEBUG_VISIBILITY) Slog.v(TAG,
8645                             "Setting visibility of " + win + ": " + (!clientHidden));
8646                     win.mClient.dispatchAppVisibility(!clientHidden);
8647                 } catch (RemoteException e) {
8648                 }
8649             }
8650         }
8651
8652         void showAllWindowsLocked() {
8653             final int NW = allAppWindows.size();
8654             for (int i=0; i<NW; i++) {
8655                 WindowState w = allAppWindows.get(i);
8656                 if (DEBUG_VISIBILITY) Slog.v(TAG,
8657                         "performing show on: " + w);
8658                 w.performShowLocked();
8659             }
8660         }
8661
8662         // This must be called while inside a transaction.
8663         boolean stepAnimationLocked(long currentTime, int dw, int dh) {
8664             if (!mDisplayFrozen && mPolicy.isScreenOn()) {
8665                 // We will run animations as long as the display isn't frozen.
8666
8667                 if (animation == sDummyAnimation) {
8668                     // This guy is going to animate, but not yet.  For now count
8669                     // it as not animating for purposes of scheduling transactions;
8670                     // when it is really time to animate, this will be set to
8671                     // a real animation and the next call will execute normally.
8672                     return false;
8673                 }
8674
8675                 if ((allDrawn || animating || startingDisplayed) && animation != null) {
8676                     if (!animating) {
8677                         if (DEBUG_ANIM) Slog.v(
8678                             TAG, "Starting animation in " + this +
8679                             " @ " + currentTime + ": dw=" + dw + " dh=" + dh
8680                             + " scale=" + mTransitionAnimationScale
8681                             + " allDrawn=" + allDrawn + " animating=" + animating);
8682                         animation.initialize(dw, dh, dw, dh);
8683                         animation.setStartTime(currentTime);
8684                         animating = true;
8685                     }
8686                     transformation.clear();
8687                     final boolean more = animation.getTransformation(
8688                         currentTime, transformation);
8689                     if (DEBUG_ANIM) Slog.v(
8690                         TAG, "Stepped animation in " + this +
8691                         ": more=" + more + ", xform=" + transformation);
8692                     if (more) {
8693                         // we're done!
8694                         hasTransformation = true;
8695                         return true;
8696                     }
8697                     if (DEBUG_ANIM) Slog.v(
8698                         TAG, "Finished animation in " + this +
8699                         " @ " + currentTime);
8700                     animation = null;
8701                 }
8702             } else if (animation != null) {
8703                 // If the display is frozen, and there is a pending animation,
8704                 // clear it and make sure we run the cleanup code.
8705                 animating = true;
8706                 animation = null;
8707             }
8708
8709             hasTransformation = false;
8710
8711             if (!animating) {
8712                 return false;
8713             }
8714
8715             clearAnimation();
8716             animating = false;
8717             if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) {
8718                 moveInputMethodWindowsIfNeededLocked(true);
8719             }
8720
8721             if (DEBUG_ANIM) Slog.v(
8722                     TAG, "Animation done in " + this
8723                     + ": reportedVisible=" + reportedVisible);
8724
8725             transformation.clear();
8726             if (animLayerAdjustment != 0) {
8727                 animLayerAdjustment = 0;
8728                 updateLayers();
8729             }
8730
8731             final int N = windows.size();
8732             for (int i=0; i<N; i++) {
8733                 ((WindowState)windows.get(i)).finishExit();
8734             }
8735             updateReportedVisibilityLocked();
8736
8737             return false;
8738         }
8739
8740         void updateReportedVisibilityLocked() {
8741             if (appToken == null) {
8742                 return;
8743             }
8744
8745             int numInteresting = 0;
8746             int numVisible = 0;
8747             boolean nowGone = true;
8748
8749             if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
8750             final int N = allAppWindows.size();
8751             for (int i=0; i<N; i++) {
8752                 WindowState win = allAppWindows.get(i);
8753                 if (win == startingWindow || win.mAppFreezing
8754                         || win.mViewVisibility != View.VISIBLE
8755                         || win.mAttrs.type == TYPE_APPLICATION_STARTING) {
8756                     continue;
8757                 }
8758                 if (DEBUG_VISIBILITY) {
8759                     Slog.v(TAG, "Win " + win + ": isDrawn="
8760                             + win.isDrawnLw()
8761                             + ", isAnimating=" + win.isAnimating());
8762                     if (!win.isDrawnLw()) {
8763                         Slog.v(TAG, "Not displayed: s=" + win.mSurface
8764                                 + " pv=" + win.mPolicyVisibility
8765                                 + " dp=" + win.mDrawPending
8766                                 + " cdp=" + win.mCommitDrawPending
8767                                 + " ah=" + win.mAttachedHidden
8768                                 + " th="
8769                                 + (win.mAppToken != null
8770                                         ? win.mAppToken.hiddenRequested : false)
8771                                 + " a=" + win.mAnimating);
8772                     }
8773                 }
8774                 numInteresting++;
8775                 if (win.isDrawnLw()) {
8776                     if (!win.isAnimating()) {
8777                         numVisible++;
8778                     }
8779                     nowGone = false;
8780                 } else if (win.isAnimating()) {
8781                     nowGone = false;
8782                 }
8783             }
8784
8785             boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
8786             if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
8787                     + numInteresting + " visible=" + numVisible);
8788             if (nowVisible != reportedVisible) {
8789                 if (DEBUG_VISIBILITY) Slog.v(
8790                         TAG, "Visibility changed in " + this
8791                         + ": vis=" + nowVisible);
8792                 reportedVisible = nowVisible;
8793                 Message m = mH.obtainMessage(
8794                         H.REPORT_APPLICATION_TOKEN_WINDOWS,
8795                         nowVisible ? 1 : 0,
8796                         nowGone ? 1 : 0,
8797                         this);
8798                     mH.sendMessage(m);
8799             }
8800         }
8801
8802         WindowState findMainWindow() {
8803             int j = windows.size();
8804             while (j > 0) {
8805                 j--;
8806                 WindowState win = windows.get(j);
8807                 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
8808                         || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
8809                     return win;
8810                 }
8811             }
8812             return null;
8813         }
8814
8815         void dump(PrintWriter pw, String prefix) {
8816             super.dump(pw, prefix);
8817             if (appToken != null) {
8818                 pw.print(prefix); pw.println("app=true");
8819             }
8820             if (allAppWindows.size() > 0) {
8821                 pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
8822             }
8823             pw.print(prefix); pw.print("groupId="); pw.print(groupId);
8824                     pw.print(" appFullscreen="); pw.print(appFullscreen);
8825                     pw.print(" requestedOrientation="); pw.println(requestedOrientation);
8826             pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
8827                     pw.print(" clientHidden="); pw.print(clientHidden);
8828                     pw.print(" willBeHidden="); pw.print(willBeHidden);
8829                     pw.print(" reportedVisible="); pw.println(reportedVisible);
8830             if (paused || freezingScreen) {
8831                 pw.print(prefix); pw.print("paused="); pw.print(paused);
8832                         pw.print(" freezingScreen="); pw.println(freezingScreen);
8833             }
8834             if (numInterestingWindows != 0 || numDrawnWindows != 0
8835                     || inPendingTransaction || allDrawn) {
8836                 pw.print(prefix); pw.print("numInterestingWindows=");
8837                         pw.print(numInterestingWindows);
8838                         pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
8839                         pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
8840                         pw.print(" allDrawn="); pw.println(allDrawn);
8841             }
8842             if (animating || animation != null) {
8843                 pw.print(prefix); pw.print("animating="); pw.print(animating);
8844                         pw.print(" animation="); pw.println(animation);
8845             }
8846             if (animLayerAdjustment != 0) {
8847                 pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
8848             }
8849             if (hasTransformation) {
8850                 pw.print(prefix); pw.print("hasTransformation="); pw.print(hasTransformation);
8851                         pw.print(" transformation="); transformation.printShortString(pw);
8852                         pw.println();
8853             }
8854             if (startingData != null || removed || firstWindowDrawn) {
8855                 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
8856                         pw.print(" removed="); pw.print(removed);
8857                         pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
8858             }
8859             if (startingWindow != null || startingView != null
8860                     || startingDisplayed || startingMoved) {
8861                 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
8862                         pw.print(" startingView="); pw.print(startingView);
8863                         pw.print(" startingDisplayed="); pw.print(startingDisplayed);
8864                         pw.print(" startingMoved"); pw.println(startingMoved);
8865             }
8866         }
8867
8868         @Override
8869         public String toString() {
8870             if (stringName == null) {
8871                 StringBuilder sb = new StringBuilder();
8872                 sb.append("AppWindowToken{");
8873                 sb.append(Integer.toHexString(System.identityHashCode(this)));
8874                 sb.append(" token="); sb.append(token); sb.append('}');
8875                 stringName = sb.toString();
8876             }
8877             return stringName;
8878         }
8879     }
8880
8881     // -------------------------------------------------------------
8882     // DummyAnimation
8883     // -------------------------------------------------------------
8884
8885     // This is an animation that does nothing: it just immediately finishes
8886     // itself every time it is called.  It is used as a stub animation in cases
8887     // where we want to synchronize multiple things that may be animating.
8888     static final class DummyAnimation extends Animation {
8889         public boolean getTransformation(long currentTime, Transformation outTransformation) {
8890             return false;
8891         }
8892     }
8893     static final Animation sDummyAnimation = new DummyAnimation();
8894
8895     // -------------------------------------------------------------
8896     // Async Handler
8897     // -------------------------------------------------------------
8898
8899     static final class StartingData {
8900         final String pkg;
8901         final int theme;
8902         final CharSequence nonLocalizedLabel;
8903         final int labelRes;
8904         final int icon;
8905
8906         StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
8907                 int _labelRes, int _icon) {
8908             pkg = _pkg;
8909             theme = _theme;
8910             nonLocalizedLabel = _nonLocalizedLabel;
8911             labelRes = _labelRes;
8912             icon = _icon;
8913         }
8914     }
8915
8916     private final class H extends Handler {
8917         public static final int REPORT_FOCUS_CHANGE = 2;
8918         public static final int REPORT_LOSING_FOCUS = 3;
8919         public static final int ANIMATE = 4;
8920         public static final int ADD_STARTING = 5;
8921         public static final int REMOVE_STARTING = 6;
8922         public static final int FINISHED_STARTING = 7;
8923         public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
8924         public static final int WINDOW_FREEZE_TIMEOUT = 11;
8925         public static final int HOLD_SCREEN_CHANGED = 12;
8926         public static final int APP_TRANSITION_TIMEOUT = 13;
8927         public static final int PERSIST_ANIMATION_SCALE = 14;
8928         public static final int FORCE_GC = 15;
8929         public static final int ENABLE_SCREEN = 16;
8930         public static final int APP_FREEZE_TIMEOUT = 17;
8931         public static final int SEND_NEW_CONFIGURATION = 18;
8932
8933         private Session mLastReportedHold;
8934
8935         public H() {
8936         }
8937
8938         @Override
8939         public void handleMessage(Message msg) {
8940             switch (msg.what) {
8941                 case REPORT_FOCUS_CHANGE: {
8942                     WindowState lastFocus;
8943                     WindowState newFocus;
8944
8945                     synchronized(mWindowMap) {
8946                         lastFocus = mLastFocus;
8947                         newFocus = mCurrentFocus;
8948                         if (lastFocus == newFocus) {
8949                             // Focus is not changing, so nothing to do.
8950                             return;
8951                         }
8952                         mLastFocus = newFocus;
8953                         //Slog.i(TAG, "Focus moving from " + lastFocus
8954                         //        + " to " + newFocus);
8955                         if (newFocus != null && lastFocus != null
8956                                 && !newFocus.isDisplayedLw()) {
8957                             //Slog.i(TAG, "Delaying loss of focus...");
8958                             mLosingFocus.add(lastFocus);
8959                             lastFocus = null;
8960                         }
8961                     }
8962
8963                     if (lastFocus != newFocus) {
8964                         //System.out.println("Changing focus from " + lastFocus
8965                         //                   + " to " + newFocus);
8966                         if (newFocus != null) {
8967                             try {
8968                                 //Slog.i(TAG, "Gaining focus: " + newFocus);
8969                                 newFocus.mClient.windowFocusChanged(true, mInTouchMode);
8970                             } catch (RemoteException e) {
8971                                 // Ignore if process has died.
8972                             }
8973                         }
8974
8975                         if (lastFocus != null) {
8976                             try {
8977                                 //Slog.i(TAG, "Losing focus: " + lastFocus);
8978                                 lastFocus.mClient.windowFocusChanged(false, mInTouchMode);
8979                             } catch (RemoteException e) {
8980                                 // Ignore if process has died.
8981                             }
8982                         }
8983                     }
8984                 } break;
8985
8986                 case REPORT_LOSING_FOCUS: {
8987                     ArrayList<WindowState> losers;
8988
8989                     synchronized(mWindowMap) {
8990                         losers = mLosingFocus;
8991                         mLosingFocus = new ArrayList<WindowState>();
8992                     }
8993
8994                     final int N = losers.size();
8995                     for (int i=0; i<N; i++) {
8996                         try {
8997                             //Slog.i(TAG, "Losing delayed focus: " + losers.get(i));
8998                             losers.get(i).mClient.windowFocusChanged(false, mInTouchMode);
8999                         } catch (RemoteException e) {
9000                              // Ignore if process has died.
9001                         }
9002                     }
9003                 } break;
9004
9005                 case ANIMATE: {
9006                     synchronized(mWindowMap) {
9007                         mAnimationPending = false;
9008                         performLayoutAndPlaceSurfacesLocked();
9009                     }
9010                 } break;
9011
9012                 case ADD_STARTING: {
9013                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9014                     final StartingData sd = wtoken.startingData;
9015
9016                     if (sd == null) {
9017                         // Animation has been canceled... do nothing.
9018                         return;
9019                     }
9020
9021                     if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
9022                             + wtoken + ": pkg=" + sd.pkg);
9023
9024                     View view = null;
9025                     try {
9026                         view = mPolicy.addStartingWindow(
9027                             wtoken.token, sd.pkg,
9028                             sd.theme, sd.nonLocalizedLabel, sd.labelRes,
9029                             sd.icon);
9030                     } catch (Exception e) {
9031                         Slog.w(TAG, "Exception when adding starting window", e);
9032                     }
9033
9034                     if (view != null) {
9035                         boolean abort = false;
9036
9037                         synchronized(mWindowMap) {
9038                             if (wtoken.removed || wtoken.startingData == null) {
9039                                 // If the window was successfully added, then
9040                                 // we need to remove it.
9041                                 if (wtoken.startingWindow != null) {
9042                                     if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
9043                                             "Aborted starting " + wtoken
9044                                             + ": removed=" + wtoken.removed
9045                                             + " startingData=" + wtoken.startingData);
9046                                     wtoken.startingWindow = null;
9047                                     wtoken.startingData = null;
9048                                     abort = true;
9049                                 }
9050                             } else {
9051                                 wtoken.startingView = view;
9052                             }
9053                             if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
9054                                     "Added starting " + wtoken
9055                                     + ": startingWindow="
9056                                     + wtoken.startingWindow + " startingView="
9057                                     + wtoken.startingView);
9058                         }
9059
9060                         if (abort) {
9061                             try {
9062                                 mPolicy.removeStartingWindow(wtoken.token, view);
9063                             } catch (Exception e) {
9064                                 Slog.w(TAG, "Exception when removing starting window", e);
9065                             }
9066                         }
9067                     }
9068                 } break;
9069
9070                 case REMOVE_STARTING: {
9071                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9072                     IBinder token = null;
9073                     View view = null;
9074                     synchronized (mWindowMap) {
9075                         if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
9076                                 + wtoken + ": startingWindow="
9077                                 + wtoken.startingWindow + " startingView="
9078                                 + wtoken.startingView);
9079                         if (wtoken.startingWindow != null) {
9080                             view = wtoken.startingView;
9081                             token = wtoken.token;
9082                             wtoken.startingData = null;
9083                             wtoken.startingView = null;
9084                             wtoken.startingWindow = null;
9085                         }
9086                     }
9087                     if (view != null) {
9088                         try {
9089                             mPolicy.removeStartingWindow(token, view);
9090                         } catch (Exception e) {
9091                             Slog.w(TAG, "Exception when removing starting window", e);
9092                         }
9093                     }
9094                 } break;
9095
9096                 case FINISHED_STARTING: {
9097                     IBinder token = null;
9098                     View view = null;
9099                     while (true) {
9100                         synchronized (mWindowMap) {
9101                             final int N = mFinishedStarting.size();
9102                             if (N <= 0) {
9103                                 break;
9104                             }
9105                             AppWindowToken wtoken = mFinishedStarting.remove(N-1);
9106
9107                             if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
9108                                     "Finished starting " + wtoken
9109                                     + ": startingWindow=" + wtoken.startingWindow
9110                                     + " startingView=" + wtoken.startingView);
9111
9112                             if (wtoken.startingWindow == null) {
9113                                 continue;
9114                             }
9115
9116                             view = wtoken.startingView;
9117                             token = wtoken.token;
9118                             wtoken.startingData = null;
9119                             wtoken.startingView = null;
9120                             wtoken.startingWindow = null;
9121                         }
9122
9123                         try {
9124                             mPolicy.removeStartingWindow(token, view);
9125                         } catch (Exception e) {
9126                             Slog.w(TAG, "Exception when removing starting window", e);
9127                         }
9128                     }
9129                 } break;
9130
9131                 case REPORT_APPLICATION_TOKEN_WINDOWS: {
9132                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9133
9134                     boolean nowVisible = msg.arg1 != 0;
9135                     boolean nowGone = msg.arg2 != 0;
9136
9137                     try {
9138                         if (DEBUG_VISIBILITY) Slog.v(
9139                                 TAG, "Reporting visible in " + wtoken
9140                                 + " visible=" + nowVisible
9141                                 + " gone=" + nowGone);
9142                         if (nowVisible) {
9143                             wtoken.appToken.windowsVisible();
9144                         } else {
9145                             wtoken.appToken.windowsGone();
9146                         }
9147                     } catch (RemoteException ex) {
9148                     }
9149                 } break;
9150
9151                 case WINDOW_FREEZE_TIMEOUT: {
9152                     synchronized (mWindowMap) {
9153                         Slog.w(TAG, "Window freeze timeout expired.");
9154                         int i = mWindows.size();
9155                         while (i > 0) {
9156                             i--;
9157                             WindowState w = (WindowState)mWindows.get(i);
9158                             if (w.mOrientationChanging) {
9159                                 w.mOrientationChanging = false;
9160                                 Slog.w(TAG, "Force clearing orientation change: " + w);
9161                             }
9162                         }
9163                         performLayoutAndPlaceSurfacesLocked();
9164                     }
9165                     break;
9166                 }
9167
9168                 case HOLD_SCREEN_CHANGED: {
9169                     Session oldHold;
9170                     Session newHold;
9171                     synchronized (mWindowMap) {
9172                         oldHold = mLastReportedHold;
9173                         newHold = (Session)msg.obj;
9174                         mLastReportedHold = newHold;
9175                     }
9176
9177                     if (oldHold != newHold) {
9178                         try {
9179                             if (oldHold != null) {
9180                                 mBatteryStats.noteStopWakelock(oldHold.mUid,
9181                                         "window",
9182                                         BatteryStats.WAKE_TYPE_WINDOW);
9183                             }
9184                             if (newHold != null) {
9185                                 mBatteryStats.noteStartWakelock(newHold.mUid,
9186                                         "window",
9187                                         BatteryStats.WAKE_TYPE_WINDOW);
9188                             }
9189                         } catch (RemoteException e) {
9190                         }
9191                     }
9192                     break;
9193                 }
9194
9195                 case APP_TRANSITION_TIMEOUT: {
9196                     synchronized (mWindowMap) {
9197                         if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
9198                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
9199                                     "*** APP TRANSITION TIMEOUT");
9200                             mAppTransitionReady = true;
9201                             mAppTransitionTimeout = true;
9202                             performLayoutAndPlaceSurfacesLocked();
9203                         }
9204                     }
9205                     break;
9206                 }
9207
9208                 case PERSIST_ANIMATION_SCALE: {
9209                     Settings.System.putFloat(mContext.getContentResolver(),
9210                             Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
9211                     Settings.System.putFloat(mContext.getContentResolver(),
9212                             Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
9213                     break;
9214                 }
9215
9216                 case FORCE_GC: {
9217                     synchronized(mWindowMap) {
9218                         if (mAnimationPending) {
9219                             // If we are animating, don't do the gc now but
9220                             // delay a bit so we don't interrupt the animation.
9221                             mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
9222                                     2000);
9223                             return;
9224                         }
9225                         // If we are currently rotating the display, it will
9226                         // schedule a new message when done.
9227                         if (mDisplayFrozen) {
9228                             return;
9229                         }
9230                         mFreezeGcPending = 0;
9231                     }
9232                     Runtime.getRuntime().gc();
9233                     break;
9234                 }
9235
9236                 case ENABLE_SCREEN: {
9237                     performEnableScreen();
9238                     break;
9239                 }
9240
9241                 case APP_FREEZE_TIMEOUT: {
9242                     synchronized (mWindowMap) {
9243                         Slog.w(TAG, "App freeze timeout expired.");
9244                         int i = mAppTokens.size();
9245                         while (i > 0) {
9246                             i--;
9247                             AppWindowToken tok = mAppTokens.get(i);
9248                             if (tok.freezingScreen) {
9249                                 Slog.w(TAG, "Force clearing freeze: " + tok);
9250                                 unsetAppFreezingScreenLocked(tok, true, true);
9251                             }
9252                         }
9253                     }
9254                     break;
9255                 }
9256
9257                 case SEND_NEW_CONFIGURATION: {
9258                     removeMessages(SEND_NEW_CONFIGURATION);
9259                     sendNewConfiguration();
9260                     break;
9261                 }
9262
9263             }
9264         }
9265     }
9266
9267     // -------------------------------------------------------------
9268     // IWindowManager API
9269     // -------------------------------------------------------------
9270
9271     public IWindowSession openSession(IInputMethodClient client,
9272             IInputContext inputContext) {
9273         if (client == null) throw new IllegalArgumentException("null client");
9274         if (inputContext == null) throw new IllegalArgumentException("null inputContext");
9275         return new Session(client, inputContext);
9276     }
9277
9278     public boolean inputMethodClientHasFocus(IInputMethodClient client) {
9279         synchronized (mWindowMap) {
9280             // The focus for the client is the window immediately below
9281             // where we would place the input method window.
9282             int idx = findDesiredInputMethodWindowIndexLocked(false);
9283             WindowState imFocus;
9284             if (idx > 0) {
9285                 imFocus = (WindowState)mWindows.get(idx-1);
9286                 if (imFocus != null) {
9287                     if (imFocus.mSession.mClient != null &&
9288                             imFocus.mSession.mClient.asBinder() == client.asBinder()) {
9289                         return true;
9290                     }
9291                 }
9292             }
9293         }
9294         return false;
9295     }
9296
9297     // -------------------------------------------------------------
9298     // Internals
9299     // -------------------------------------------------------------
9300
9301     final WindowState windowForClientLocked(Session session, IWindow client,
9302             boolean throwOnError) {
9303         return windowForClientLocked(session, client.asBinder(), throwOnError);
9304     }
9305
9306     final WindowState windowForClientLocked(Session session, IBinder client,
9307             boolean throwOnError) {
9308         WindowState win = mWindowMap.get(client);
9309         if (localLOGV) Slog.v(
9310             TAG, "Looking up client " + client + ": " + win);
9311         if (win == null) {
9312             RuntimeException ex = new IllegalArgumentException(
9313                     "Requested window " + client + " does not exist");
9314             if (throwOnError) {
9315                 throw ex;
9316             }
9317             Slog.w(TAG, "Failed looking up window", ex);
9318             return null;
9319         }
9320         if (session != null && win.mSession != session) {
9321             RuntimeException ex = new IllegalArgumentException(
9322                     "Requested window " + client + " is in session " +
9323                     win.mSession + ", not " + session);
9324             if (throwOnError) {
9325                 throw ex;
9326             }
9327             Slog.w(TAG, "Failed looking up window", ex);
9328             return null;
9329         }
9330
9331         return win;
9332     }
9333
9334     final void rebuildAppWindowListLocked() {
9335         int NW = mWindows.size();
9336         int i;
9337         int lastWallpaper = -1;
9338         int numRemoved = 0;
9339
9340         // First remove all existing app windows.
9341         i=0;
9342         while (i < NW) {
9343             WindowState w = (WindowState)mWindows.get(i);
9344             if (w.mAppToken != null) {
9345                 WindowState win = (WindowState)mWindows.remove(i);
9346                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
9347                         "Rebuild removing window: " + win);
9348                 NW--;
9349                 numRemoved++;
9350                 continue;
9351             } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER
9352                     && lastWallpaper == i-1) {
9353                 lastWallpaper = i;
9354             }
9355             i++;
9356         }
9357
9358         // The wallpaper window(s) typically live at the bottom of the stack,
9359         // so skip them before adding app tokens.
9360         lastWallpaper++;
9361         i = lastWallpaper;
9362
9363         // First add all of the exiting app tokens...  these are no longer
9364         // in the main app list, but still have windows shown.  We put them
9365         // in the back because now that the animation is over we no longer
9366         // will care about them.
9367         int NT = mExitingAppTokens.size();
9368         for (int j=0; j<NT; j++) {
9369             i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j));
9370         }
9371
9372         // And add in the still active app tokens in Z order.
9373         NT = mAppTokens.size();
9374         for (int j=0; j<NT; j++) {
9375             i = reAddAppWindowsLocked(i, mAppTokens.get(j));
9376         }
9377
9378         i -= lastWallpaper;
9379         if (i != numRemoved) {
9380             Slog.w(TAG, "Rebuild removed " + numRemoved
9381                     + " windows but added " + i);
9382         }
9383     }
9384
9385     private final void assignLayersLocked() {
9386         int N = mWindows.size();
9387         int curBaseLayer = 0;
9388         int curLayer = 0;
9389         int i;
9390
9391         for (i=0; i<N; i++) {
9392             WindowState w = (WindowState)mWindows.get(i);
9393             if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
9394                     || (i > 0 && w.mIsWallpaper)) {
9395                 curLayer += WINDOW_LAYER_MULTIPLIER;
9396                 w.mLayer = curLayer;
9397             } else {
9398                 curBaseLayer = curLayer = w.mBaseLayer;
9399                 w.mLayer = curLayer;
9400             }
9401             if (w.mTargetAppToken != null) {
9402                 w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment;
9403             } else if (w.mAppToken != null) {
9404                 w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment;
9405             } else {
9406                 w.mAnimLayer = w.mLayer;
9407             }
9408             if (w.mIsImWindow) {
9409                 w.mAnimLayer += mInputMethodAnimLayerAdjustment;
9410             } else if (w.mIsWallpaper) {
9411                 w.mAnimLayer += mWallpaperAnimLayerAdjustment;
9412             }
9413             if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
9414                     + w.mAnimLayer);
9415             //System.out.println(
9416             //    "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
9417         }
9418     }
9419
9420     private boolean mInLayout = false;
9421     private final void performLayoutAndPlaceSurfacesLocked() {
9422         if (mInLayout) {
9423             if (DEBUG) {
9424                 throw new RuntimeException("Recursive call!");
9425             }
9426             Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout");
9427             return;
9428         }
9429
9430         if (mWaitingForConfig) {
9431             // Our configuration has changed (most likely rotation), but we
9432             // don't yet have the complete configuration to report to
9433             // applications.  Don't do any window layout until we have it.
9434             return;
9435         }
9436         
9437         boolean recoveringMemory = false;
9438         if (mForceRemoves != null) {
9439             recoveringMemory = true;
9440             // Wait a little it for things to settle down, and off we go.
9441             for (int i=0; i<mForceRemoves.size(); i++) {
9442                 WindowState ws = mForceRemoves.get(i);
9443                 Slog.i(TAG, "Force removing: " + ws);
9444                 removeWindowInnerLocked(ws.mSession, ws);
9445             }
9446             mForceRemoves = null;
9447             Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
9448             Object tmp = new Object();
9449             synchronized (tmp) {
9450                 try {
9451                     tmp.wait(250);
9452                 } catch (InterruptedException e) {
9453                 }
9454             }
9455         }
9456
9457         mInLayout = true;
9458         try {
9459             performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
9460
9461             int i = mPendingRemove.size()-1;
9462             if (i >= 0) {
9463                 while (i >= 0) {
9464                     WindowState w = mPendingRemove.get(i);
9465                     removeWindowInnerLocked(w.mSession, w);
9466                     i--;
9467                 }
9468                 mPendingRemove.clear();
9469
9470                 mInLayout = false;
9471                 assignLayersLocked();
9472                 mLayoutNeeded = true;
9473                 performLayoutAndPlaceSurfacesLocked();
9474
9475             } else {
9476                 mInLayout = false;
9477                 if (mLayoutNeeded) {
9478                     requestAnimationLocked(0);
9479                 }
9480             }
9481         } catch (RuntimeException e) {
9482             mInLayout = false;
9483             Slog.e(TAG, "Unhandled exception while layout out windows", e);
9484         }
9485     }
9486
9487     private final int performLayoutLockedInner() {
9488         if (!mLayoutNeeded) {
9489             return 0;
9490         }
9491         
9492         mLayoutNeeded = false;
9493         
9494         final int dw = mDisplay.getWidth();
9495         final int dh = mDisplay.getHeight();
9496
9497         final int N = mWindows.size();
9498         int i;
9499
9500         if (DEBUG_LAYOUT) Slog.v(TAG, "performLayout: needed="
9501                 + mLayoutNeeded + " dw=" + dw + " dh=" + dh);
9502         
9503         mPolicy.beginLayoutLw(dw, dh);
9504
9505         int seq = mLayoutSeq+1;
9506         if (seq < 0) seq = 0;
9507         mLayoutSeq = seq;
9508         
9509         // First perform layout of any root windows (not attached
9510         // to another window).
9511         int topAttached = -1;
9512         for (i = N-1; i >= 0; i--) {
9513             WindowState win = (WindowState) mWindows.get(i);
9514
9515             // Don't do layout of a window if it is not visible, or
9516             // soon won't be visible, to avoid wasting time and funky
9517             // changes while a window is animating away.
9518             final AppWindowToken atoken = win.mAppToken;
9519             final boolean gone = win.mViewVisibility == View.GONE
9520                     || !win.mRelayoutCalled
9521                     || win.mRootToken.hidden
9522                     || (atoken != null && atoken.hiddenRequested)
9523                     || win.mAttachedHidden
9524                     || win.mExiting || win.mDestroying;
9525
9526             if (!win.mLayoutAttached) {
9527                 if (DEBUG_LAYOUT) Slog.v(TAG, "First pass " + win
9528                         + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
9529                         + " mLayoutAttached=" + win.mLayoutAttached);
9530                 if (DEBUG_LAYOUT && gone) Slog.v(TAG, "  (mViewVisibility="
9531                         + win.mViewVisibility + " mRelayoutCalled="
9532                         + win.mRelayoutCalled + " hidden="
9533                         + win.mRootToken.hidden + " hiddenRequested="
9534                         + (atoken != null && atoken.hiddenRequested)
9535                         + " mAttachedHidden=" + win.mAttachedHidden);
9536             }
9537             
9538             // If this view is GONE, then skip it -- keep the current
9539             // frame, and let the caller know so they can ignore it
9540             // if they want.  (We do the normal layout for INVISIBLE
9541             // windows, since that means "perform layout as normal,
9542             // just don't display").
9543             if (!gone || !win.mHaveFrame) {
9544                 if (!win.mLayoutAttached) {
9545                     mPolicy.layoutWindowLw(win, win.mAttrs, null);
9546                     win.mLayoutSeq = seq;
9547                     if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
9548                             + win.mFrame + " mContainingFrame="
9549                             + win.mContainingFrame + " mDisplayFrame="
9550                             + win.mDisplayFrame);
9551                 } else {
9552                     if (topAttached < 0) topAttached = i;
9553                 }
9554             }
9555         }
9556
9557         // Now perform layout of attached windows, which usually
9558         // depend on the position of the window they are attached to.
9559         // XXX does not deal with windows that are attached to windows
9560         // that are themselves attached.
9561         for (i = topAttached; i >= 0; i--) {
9562             WindowState win = (WindowState) mWindows.get(i);
9563
9564             // If this view is GONE, then skip it -- keep the current
9565             // frame, and let the caller know so they can ignore it
9566             // if they want.  (We do the normal layout for INVISIBLE
9567             // windows, since that means "perform layout as normal,
9568             // just don't display").
9569             if (win.mLayoutAttached) {
9570                 if (DEBUG_LAYOUT) Slog.v(TAG, "Second pass " + win
9571                         + " mHaveFrame=" + win.mHaveFrame
9572                         + " mViewVisibility=" + win.mViewVisibility
9573                         + " mRelayoutCalled=" + win.mRelayoutCalled);
9574                 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
9575                         || !win.mHaveFrame) {
9576                     mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
9577                     win.mLayoutSeq = seq;
9578                     if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
9579                             + win.mFrame + " mContainingFrame="
9580                             + win.mContainingFrame + " mDisplayFrame="
9581                             + win.mDisplayFrame);
9582                 }
9583             }
9584         }
9585
9586         return mPolicy.finishLayoutLw();
9587     }
9588
9589     private final void performLayoutAndPlaceSurfacesLockedInner(
9590             boolean recoveringMemory) {
9591         final long currentTime = SystemClock.uptimeMillis();
9592         final int dw = mDisplay.getWidth();
9593         final int dh = mDisplay.getHeight();
9594
9595         int i;
9596
9597         if (mFocusMayChange) {
9598             mFocusMayChange = false;
9599             updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
9600         }
9601         
9602         if (mFxSession == null) {
9603             mFxSession = new SurfaceSession();
9604         }
9605
9606         if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
9607
9608         // Initialize state of exiting tokens.
9609         for (i=mExitingTokens.size()-1; i>=0; i--) {
9610             mExitingTokens.get(i).hasVisible = false;
9611         }
9612
9613         // Initialize state of exiting applications.
9614         for (i=mExitingAppTokens.size()-1; i>=0; i--) {
9615             mExitingAppTokens.get(i).hasVisible = false;
9616         }
9617
9618         boolean orientationChangeComplete = true;
9619         Session holdScreen = null;
9620         float screenBrightness = -1;
9621         float buttonBrightness = -1;
9622         boolean focusDisplayed = false;
9623         boolean animating = false;
9624
9625         Surface.openTransaction();
9626         try {
9627             boolean wallpaperForceHidingChanged = false;
9628             int repeats = 0;
9629             int changes = 0;
9630             
9631             do {
9632                 repeats++;
9633                 if (repeats > 6) {
9634                     Slog.w(TAG, "Animation repeat aborted after too many iterations");
9635                     mLayoutNeeded = false;
9636                     break;
9637                 }
9638                 
9639                 if ((changes&(WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER
9640                         | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG
9641                         | WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT)) != 0) {
9642                     if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
9643                         if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
9644                             assignLayersLocked();
9645                             mLayoutNeeded = true;
9646                         }
9647                     }
9648                     if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
9649                         if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
9650                         if (updateOrientationFromAppTokensLocked()) {
9651                             mLayoutNeeded = true;
9652                             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9653                         }
9654                     }
9655                     if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9656                         mLayoutNeeded = true;
9657                     }
9658                 }
9659                 
9660                 // FIRST LOOP: Perform a layout, if needed.
9661                 if (repeats < 4) {
9662                     changes = performLayoutLockedInner();
9663                     if (changes != 0) {
9664                         continue;
9665                     }
9666                 } else {
9667                     Slog.w(TAG, "Layout repeat skipped after too many iterations");
9668                     changes = 0;
9669                 }
9670                 
9671                 final int transactionSequence = ++mTransactionSequence;
9672
9673                 // Update animations of all applications, including those
9674                 // associated with exiting/removed apps
9675                 boolean tokensAnimating = false;
9676                 final int NAT = mAppTokens.size();
9677                 for (i=0; i<NAT; i++) {
9678                     if (mAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
9679                         tokensAnimating = true;
9680                     }
9681                 }
9682                 final int NEAT = mExitingAppTokens.size();
9683                 for (i=0; i<NEAT; i++) {
9684                     if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
9685                         tokensAnimating = true;
9686                     }
9687                 }
9688
9689                 // SECOND LOOP: Execute animations and update visibility of windows.
9690                 
9691                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq="
9692                         + transactionSequence + " tokensAnimating="
9693                         + tokensAnimating);
9694                         
9695                 animating = tokensAnimating;
9696
9697                 boolean tokenMayBeDrawn = false;
9698                 boolean wallpaperMayChange = false;
9699                 boolean forceHiding = false;
9700
9701                 mPolicy.beginAnimationLw(dw, dh);
9702
9703                 final int N = mWindows.size();
9704
9705                 for (i=N-1; i>=0; i--) {
9706                     WindowState w = (WindowState)mWindows.get(i);
9707
9708                     final WindowManager.LayoutParams attrs = w.mAttrs;
9709
9710                     if (w.mSurface != null) {
9711                         // Execute animation.
9712                         if (w.commitFinishDrawingLocked(currentTime)) {
9713                             if ((w.mAttrs.flags
9714                                     & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
9715                                 if (DEBUG_WALLPAPER) Slog.v(TAG,
9716                                         "First draw done in potential wallpaper target " + w);
9717                                 wallpaperMayChange = true;
9718                             }
9719                         }
9720
9721                         boolean wasAnimating = w.mAnimating;
9722                         if (w.stepAnimationLocked(currentTime, dw, dh)) {
9723                             animating = true;
9724                             //w.dump("  ");
9725                         }
9726                         if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
9727                             wallpaperMayChange = true;
9728                         }
9729
9730                         if (mPolicy.doesForceHide(w, attrs)) {
9731                             if (!wasAnimating && animating) {
9732                                 if (DEBUG_VISIBILITY) Slog.v(TAG,
9733                                         "Animation done that could impact force hide: "
9734                                         + w);
9735                                 wallpaperForceHidingChanged = true;
9736                                 mFocusMayChange = true;
9737                             } else if (w.isReadyForDisplay() && w.mAnimation == null) {
9738                                 forceHiding = true;
9739                             }
9740                         } else if (mPolicy.canBeForceHidden(w, attrs)) {
9741                             boolean changed;
9742                             if (forceHiding) {
9743                                 changed = w.hideLw(false, false);
9744                                 if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
9745                                         "Now policy hidden: " + w);
9746                             } else {
9747                                 changed = w.showLw(false, false);
9748                                 if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
9749                                         "Now policy shown: " + w);
9750                                 if (changed) {
9751                                     if (wallpaperForceHidingChanged
9752                                             && w.isVisibleNow() /*w.isReadyForDisplay()*/) {
9753                                         // Assume we will need to animate.  If
9754                                         // we don't (because the wallpaper will
9755                                         // stay with the lock screen), then we will
9756                                         // clean up later.
9757                                         Animation a = mPolicy.createForceHideEnterAnimation();
9758                                         if (a != null) {
9759                                             w.setAnimation(a);
9760                                         }
9761                                     }
9762                                     if (mCurrentFocus == null ||
9763                                             mCurrentFocus.mLayer < w.mLayer) {
9764                                         // We are showing on to of the current
9765                                         // focus, so re-evaluate focus to make
9766                                         // sure it is correct.
9767                                         mFocusMayChange = true;
9768                                     }
9769                                 }
9770                             }
9771                             if (changed && (attrs.flags
9772                                     & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
9773                                 wallpaperMayChange = true;
9774                             }
9775                         }
9776
9777                         mPolicy.animatingWindowLw(w, attrs);
9778                     }
9779
9780                     final AppWindowToken atoken = w.mAppToken;
9781                     if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
9782                         if (atoken.lastTransactionSequence != transactionSequence) {
9783                             atoken.lastTransactionSequence = transactionSequence;
9784                             atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9785                             atoken.startingDisplayed = false;
9786                         }
9787                         if ((w.isOnScreen() || w.mAttrs.type
9788                                 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
9789                                 && !w.mExiting && !w.mDestroying) {
9790                             if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
9791                                 Slog.v(TAG, "Eval win " + w + ": isDrawn="
9792                                         + w.isDrawnLw()
9793                                         + ", isAnimating=" + w.isAnimating());
9794                                 if (!w.isDrawnLw()) {
9795                                     Slog.v(TAG, "Not displayed: s=" + w.mSurface
9796                                             + " pv=" + w.mPolicyVisibility
9797                                             + " dp=" + w.mDrawPending
9798                                             + " cdp=" + w.mCommitDrawPending
9799                                             + " ah=" + w.mAttachedHidden
9800                                             + " th=" + atoken.hiddenRequested
9801                                             + " a=" + w.mAnimating);
9802                                 }
9803                             }
9804                             if (w != atoken.startingWindow) {
9805                                 if (!atoken.freezingScreen || !w.mAppFreezing) {
9806                                     atoken.numInterestingWindows++;
9807                                     if (w.isDrawnLw()) {
9808                                         atoken.numDrawnWindows++;
9809                                         if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
9810                                                 "tokenMayBeDrawn: " + atoken
9811                                                 + " freezingScreen=" + atoken.freezingScreen
9812                                                 + " mAppFreezing=" + w.mAppFreezing);
9813                                         tokenMayBeDrawn = true;
9814                                     }
9815                                 }
9816                             } else if (w.isDrawnLw()) {
9817                                 atoken.startingDisplayed = true;
9818                             }
9819                         }
9820                     } else if (w.mReadyToShow) {
9821                         w.performShowLocked();
9822                     }
9823                 }
9824
9825                 changes |= mPolicy.finishAnimationLw();
9826
9827                 if (tokenMayBeDrawn) {
9828                     // See if any windows have been drawn, so they (and others
9829                     // associated with them) can now be shown.
9830                     final int NT = mTokenList.size();
9831                     for (i=0; i<NT; i++) {
9832                         AppWindowToken wtoken = mTokenList.get(i).appWindowToken;
9833                         if (wtoken == null) {
9834                             continue;
9835                         }
9836                         if (wtoken.freezingScreen) {
9837                             int numInteresting = wtoken.numInterestingWindows;
9838                             if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
9839                                 if (DEBUG_VISIBILITY) Slog.v(TAG,
9840                                         "allDrawn: " + wtoken
9841                                         + " interesting=" + numInteresting
9842                                         + " drawn=" + wtoken.numDrawnWindows);
9843                                 wtoken.showAllWindowsLocked();
9844                                 unsetAppFreezingScreenLocked(wtoken, false, true);
9845                                 orientationChangeComplete = true;
9846                             }
9847                         } else if (!wtoken.allDrawn) {
9848                             int numInteresting = wtoken.numInterestingWindows;
9849                             if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
9850                                 if (DEBUG_VISIBILITY) Slog.v(TAG,
9851                                         "allDrawn: " + wtoken
9852                                         + " interesting=" + numInteresting
9853                                         + " drawn=" + wtoken.numDrawnWindows);
9854                                 wtoken.allDrawn = true;
9855                                 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
9856
9857                                 // We can now show all of the drawn windows!
9858                                 if (!mOpeningApps.contains(wtoken)) {
9859                                     wtoken.showAllWindowsLocked();
9860                                 }
9861                             }
9862                         }
9863                     }
9864                 }
9865
9866                 // If we are ready to perform an app transition, check through
9867                 // all of the app tokens to be shown and see if they are ready
9868                 // to go.
9869                 if (mAppTransitionReady) {
9870                     int NN = mOpeningApps.size();
9871                     boolean goodToGo = true;
9872                     if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
9873                             "Checking " + NN + " opening apps (frozen="
9874                             + mDisplayFrozen + " timeout="
9875                             + mAppTransitionTimeout + ")...");
9876                     if (!mDisplayFrozen && !mAppTransitionTimeout) {
9877                         // If the display isn't frozen, wait to do anything until
9878                         // all of the apps are ready.  Otherwise just go because
9879                         // we'll unfreeze the display when everyone is ready.
9880                         for (i=0; i<NN && goodToGo; i++) {
9881                             AppWindowToken wtoken = mOpeningApps.get(i);
9882                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
9883                                     "Check opening app" + wtoken + ": allDrawn="
9884                                     + wtoken.allDrawn + " startingDisplayed="
9885                                     + wtoken.startingDisplayed);
9886                             if (!wtoken.allDrawn && !wtoken.startingDisplayed
9887                                     && !wtoken.startingMoved) {
9888                                 goodToGo = false;
9889                             }
9890                         }
9891                     }
9892                     if (goodToGo) {
9893                         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
9894                         int transit = mNextAppTransition;
9895                         if (mSkipAppTransitionAnimation) {
9896                             transit = WindowManagerPolicy.TRANSIT_UNSET;
9897                         }
9898                         mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
9899                         mAppTransitionReady = false;
9900                         mAppTransitionRunning = true;
9901                         mAppTransitionTimeout = false;
9902                         mStartingIconInTransition = false;
9903                         mSkipAppTransitionAnimation = false;
9904
9905                         mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
9906
9907                         // If there are applications waiting to come to the
9908                         // top of the stack, now is the time to move their windows.
9909                         // (Note that we don't do apps going to the bottom
9910                         // here -- we want to keep their windows in the old
9911                         // Z-order until the animation completes.)
9912                         if (mToTopApps.size() > 0) {
9913                             NN = mAppTokens.size();
9914                             for (i=0; i<NN; i++) {
9915                                 AppWindowToken wtoken = mAppTokens.get(i);
9916                                 if (wtoken.sendingToTop) {
9917                                     wtoken.sendingToTop = false;
9918                                     moveAppWindowsLocked(wtoken, NN, false);
9919                                 }
9920                             }
9921                             mToTopApps.clear();
9922                         }
9923
9924                         WindowState oldWallpaper = mWallpaperTarget;
9925
9926                         adjustWallpaperWindowsLocked();
9927                         wallpaperMayChange = false;
9928
9929                         // The top-most window will supply the layout params,
9930                         // and we will determine it below.
9931                         LayoutParams animLp = null;
9932                         AppWindowToken animToken = null;
9933                         int bestAnimLayer = -1;
9934
9935                         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
9936                                 "New wallpaper target=" + mWallpaperTarget
9937                                 + ", lower target=" + mLowerWallpaperTarget
9938                                 + ", upper target=" + mUpperWallpaperTarget);
9939                         int foundWallpapers = 0;
9940                         // Do a first pass through the tokens for two
9941                         // things:
9942                         // (1) Determine if both the closing and opening
9943                         // app token sets are wallpaper targets, in which
9944                         // case special animations are needed
9945                         // (since the wallpaper needs to stay static
9946                         // behind them).
9947                         // (2) Find the layout params of the top-most
9948                         // application window in the tokens, which is
9949                         // what will control the animation theme.
9950                         final int NC = mClosingApps.size();
9951                         NN = NC + mOpeningApps.size();
9952                         for (i=0; i<NN; i++) {
9953                             AppWindowToken wtoken;
9954                             int mode;
9955                             if (i < NC) {
9956                                 wtoken = mClosingApps.get(i);
9957                                 mode = 1;
9958                             } else {
9959                                 wtoken = mOpeningApps.get(i-NC);
9960                                 mode = 2;
9961                             }
9962                             if (mLowerWallpaperTarget != null) {
9963                                 if (mLowerWallpaperTarget.mAppToken == wtoken
9964                                         || mUpperWallpaperTarget.mAppToken == wtoken) {
9965                                     foundWallpapers |= mode;
9966                                 }
9967                             }
9968                             if (wtoken.appFullscreen) {
9969                                 WindowState ws = wtoken.findMainWindow();
9970                                 if (ws != null) {
9971                                     // If this is a compatibility mode
9972                                     // window, we will always use its anim.
9973                                     if ((ws.mAttrs.flags&FLAG_COMPATIBLE_WINDOW) != 0) {
9974                                         animLp = ws.mAttrs;
9975                                         animToken = ws.mAppToken;
9976                                         bestAnimLayer = Integer.MAX_VALUE;
9977                                     } else if (ws.mLayer > bestAnimLayer) {
9978                                         animLp = ws.mAttrs;
9979                                         animToken = ws.mAppToken;
9980                                         bestAnimLayer = ws.mLayer;
9981                                     }
9982                                 }
9983                             }
9984                         }
9985
9986                         if (foundWallpapers == 3) {
9987                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
9988                                     "Wallpaper animation!");
9989                             switch (transit) {
9990                                 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
9991                                 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
9992                                 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
9993                                     transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN;
9994                                     break;
9995                                 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
9996                                 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
9997                                 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
9998                                     transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE;
9999                                     break;
10000                             }
10001                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
10002                                     "New transit: " + transit);
10003                         } else if (oldWallpaper != null) {
10004                             // We are transitioning from an activity with
10005                             // a wallpaper to one without.
10006                             transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE;
10007                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
10008                                     "New transit away from wallpaper: " + transit);
10009                         } else if (mWallpaperTarget != null) {
10010                             // We are transitioning from an activity without
10011                             // a wallpaper to now showing the wallpaper
10012                             transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN;
10013                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
10014                                     "New transit into wallpaper: " + transit);
10015                         }
10016
10017                         if ((transit&WindowManagerPolicy.TRANSIT_ENTER_MASK) != 0) {
10018                             mLastEnterAnimToken = animToken;
10019                             mLastEnterAnimParams = animLp;
10020                         } else if (mLastEnterAnimParams != null) {
10021                             animLp = mLastEnterAnimParams;
10022                             mLastEnterAnimToken = null;
10023                             mLastEnterAnimParams = null;
10024                         }
10025
10026                         // If all closing windows are obscured, then there is
10027                         // no need to do an animation.  This is the case, for
10028                         // example, when this transition is being done behind
10029                         // the lock screen.
10030                         if (!mPolicy.allowAppAnimationsLw()) {
10031                             animLp = null;
10032                         }
10033                         
10034                         NN = mOpeningApps.size();
10035                         for (i=0; i<NN; i++) {
10036                             AppWindowToken wtoken = mOpeningApps.get(i);
10037                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
10038                                     "Now opening app" + wtoken);
10039                             wtoken.reportedVisible = false;
10040                             wtoken.inPendingTransaction = false;
10041                             wtoken.animation = null;
10042                             setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
10043                             wtoken.updateReportedVisibilityLocked();
10044                             wtoken.waitingToShow = false;
10045                             wtoken.showAllWindowsLocked();
10046                         }
10047                         NN = mClosingApps.size();
10048                         for (i=0; i<NN; i++) {
10049                             AppWindowToken wtoken = mClosingApps.get(i);
10050                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
10051                                     "Now closing app" + wtoken);
10052                             wtoken.inPendingTransaction = false;
10053                             wtoken.animation = null;
10054                             setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
10055                             wtoken.updateReportedVisibilityLocked();
10056                             wtoken.waitingToHide = false;
10057                             // Force the allDrawn flag, because we want to start
10058                             // this guy's animations regardless of whether it's
10059                             // gotten drawn.
10060                             wtoken.allDrawn = true;
10061                         }
10062
10063                         mNextAppTransitionPackage = null;
10064
10065                         mOpeningApps.clear();
10066                         mClosingApps.clear();
10067
10068                         // This has changed the visibility of windows, so perform
10069                         // a new layout to get them all up-to-date.
10070                         changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
10071                         mLayoutNeeded = true;
10072                         if (!moveInputMethodWindowsIfNeededLocked(true)) {
10073                             assignLayersLocked();
10074                         }
10075                         updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
10076                         mFocusMayChange = false;
10077                     }
10078                 }
10079
10080                 int adjResult = 0;
10081
10082                 if (!animating && mAppTransitionRunning) {
10083                     // We have finished the animation of an app transition.  To do
10084                     // this, we have delayed a lot of operations like showing and
10085                     // hiding apps, moving apps in Z-order, etc.  The app token list
10086                     // reflects the correct Z-order, but the window list may now
10087                     // be out of sync with it.  So here we will just rebuild the
10088                     // entire app window list.  Fun!
10089                     mAppTransitionRunning = false;
10090                     // Clear information about apps that were moving.
10091                     mToBottomApps.clear();
10092
10093                     rebuildAppWindowListLocked();
10094                     changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
10095                     adjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED;
10096                     moveInputMethodWindowsIfNeededLocked(false);
10097                     wallpaperMayChange = true;
10098                     // Since the window list has been rebuilt, focus might
10099                     // have to be recomputed since the actual order of windows
10100                     // might have changed again.
10101                     mFocusMayChange = true;
10102                 }
10103
10104                 if (wallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) {
10105                     // At this point, there was a window with a wallpaper that
10106                     // was force hiding other windows behind it, but now it
10107                     // is going away.  This may be simple -- just animate
10108                     // away the wallpaper and its window -- or it may be
10109                     // hard -- the wallpaper now needs to be shown behind
10110                     // something that was hidden.
10111                     WindowState oldWallpaper = mWallpaperTarget;
10112                     if (mLowerWallpaperTarget != null
10113                             && mLowerWallpaperTarget.mAppToken != null) {
10114                         if (DEBUG_WALLPAPER) Slog.v(TAG,
10115                                 "wallpaperForceHiding changed with lower="
10116                                 + mLowerWallpaperTarget);
10117                         if (DEBUG_WALLPAPER) Slog.v(TAG,
10118                                 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden +
10119                                 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested);
10120                         if (mLowerWallpaperTarget.mAppToken.hidden) {
10121                             // The lower target has become hidden before we
10122                             // actually started the animation...  let's completely
10123                             // re-evaluate everything.
10124                             mLowerWallpaperTarget = mUpperWallpaperTarget = null;
10125                             changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
10126                         }
10127                     }
10128                     adjResult |= adjustWallpaperWindowsLocked();
10129                     wallpaperMayChange = false;
10130                     wallpaperForceHidingChanged = false;
10131                     if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper
10132                             + " NEW: " + mWallpaperTarget
10133                             + " LOWER: " + mLowerWallpaperTarget);
10134                     if (mLowerWallpaperTarget == null) {
10135                         // Whoops, we don't need a special wallpaper animation.
10136                         // Clear them out.
10137                         forceHiding = false;
10138                         for (i=N-1; i>=0; i--) {
10139                             WindowState w = (WindowState)mWindows.get(i);
10140                             if (w.mSurface != null) {
10141                                 final WindowManager.LayoutParams attrs = w.mAttrs;
10142                                 if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) {
10143                                     if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows");
10144                                     forceHiding = true;
10145                                 } else if (mPolicy.canBeForceHidden(w, attrs)) {
10146                                     if (!w.mAnimating) {
10147                                         // We set the animation above so it
10148                                         // is not yet running.
10149                                         w.clearAnimation();
10150                                     }
10151                                 }
10152                             }
10153                         }
10154                     }
10155                 }
10156
10157                 if (wallpaperMayChange) {
10158                     if (DEBUG_WALLPAPER) Slog.v(TAG,
10159                             "Wallpaper may change!  Adjusting");
10160                     adjResult |= adjustWallpaperWindowsLocked();
10161                 }
10162
10163                 if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
10164                     if (DEBUG_WALLPAPER) Slog.v(TAG,
10165                             "Wallpaper layer changed: assigning layers + relayout");
10166                     changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
10167                     assignLayersLocked();
10168                 } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
10169                     if (DEBUG_WALLPAPER) Slog.v(TAG,
10170                             "Wallpaper visibility changed: relayout");
10171                     changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
10172                 }
10173
10174                 if (mFocusMayChange) {
10175                     mFocusMayChange = false;
10176                     if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES)) {
10177                         changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
10178                         adjResult = 0;
10179                     }
10180                 }
10181
10182                 if (mLayoutNeeded) {
10183                     changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
10184                 }
10185
10186                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
10187                         + Integer.toHexString(changes));
10188                 
10189             } while (changes != 0);
10190
10191             // THIRD LOOP: Update the surfaces of all windows.
10192
10193             final boolean someoneLosingFocus = mLosingFocus.size() != 0;
10194
10195             boolean obscured = false;
10196             boolean blurring = false;
10197             boolean dimming = false;
10198             boolean covered = false;
10199             boolean syswin = false;
10200             boolean backgroundFillerShown = false;
10201
10202             final int N = mWindows.size();
10203
10204             for (i=N-1; i>=0; i--) {
10205                 WindowState w = (WindowState)mWindows.get(i);
10206
10207                 boolean displayed = false;
10208                 final WindowManager.LayoutParams attrs = w.mAttrs;
10209                 final int attrFlags = attrs.flags;
10210
10211                 if (w.mSurface != null) {
10212                     // XXX NOTE: The logic here could be improved.  We have
10213                     // the decision about whether to resize a window separated
10214                     // from whether to hide the surface.  This can cause us to
10215                     // resize a surface even if we are going to hide it.  You
10216                     // can see this by (1) holding device in landscape mode on
10217                     // home screen; (2) tapping browser icon (device will rotate
10218                     // to landscape; (3) tap home.  The wallpaper will be resized
10219                     // in step 2 but then immediately hidden, causing us to
10220                     // have to resize and then redraw it again in step 3.  It
10221                     // would be nice to figure out how to avoid this, but it is
10222                     // difficult because we do need to resize surfaces in some
10223                     // cases while they are hidden such as when first showing a
10224                     // window.
10225                     
10226                     w.computeShownFrameLocked();
10227                     if (localLOGV) Slog.v(
10228                             TAG, "Placing surface #" + i + " " + w.mSurface
10229                             + ": new=" + w.mShownFrame + ", old="
10230                             + w.mLastShownFrame);
10231
10232                     boolean resize;
10233                     int width, height;
10234                     if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
10235                         resize = w.mLastRequestedWidth != w.mRequestedWidth ||
10236                         w.mLastRequestedHeight != w.mRequestedHeight;
10237                         // for a scaled surface, we just want to use
10238                         // the requested size.
10239                         width  = w.mRequestedWidth;
10240                         height = w.mRequestedHeight;
10241                         w.mLastRequestedWidth = width;
10242                         w.mLastRequestedHeight = height;
10243                         w.mLastShownFrame.set(w.mShownFrame);
10244                         try {
10245                             if (SHOW_TRANSACTIONS) logSurface(w,
10246                                     "POS " + w.mShownFrame.left
10247                                     + ", " + w.mShownFrame.top, null);
10248                             w.mSurfaceX = w.mShownFrame.left;
10249                             w.mSurfaceY = w.mShownFrame.top;
10250                             w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
10251                         } catch (RuntimeException e) {
10252                             Slog.w(TAG, "Error positioning surface in " + w, e);
10253                             if (!recoveringMemory) {
10254                                 reclaimSomeSurfaceMemoryLocked(w, "position");
10255                             }
10256                         }
10257                     } else {
10258                         resize = !w.mLastShownFrame.equals(w.mShownFrame);
10259                         width = w.mShownFrame.width();
10260                         height = w.mShownFrame.height();
10261                         w.mLastShownFrame.set(w.mShownFrame);
10262                     }
10263
10264                     if (resize) {
10265                         if (width < 1) width = 1;
10266                         if (height < 1) height = 1;
10267                         if (w.mSurface != null) {
10268                             try {
10269                                 if (SHOW_TRANSACTIONS) logSurface(w,
10270                                         "POS " + w.mShownFrame.left + ","
10271                                         + w.mShownFrame.top + " SIZE "
10272                                         + w.mShownFrame.width() + "x"
10273                                         + w.mShownFrame.height(), null);
10274                                 w.mSurfaceResized = true;
10275                                 w.mSurfaceW = width;
10276                                 w.mSurfaceH = height;
10277                                 w.mSurface.setSize(width, height);
10278                                 w.mSurfaceX = w.mShownFrame.left;
10279                                 w.mSurfaceY = w.mShownFrame.top;
10280                                 w.mSurface.setPosition(w.mShownFrame.left,
10281                                         w.mShownFrame.top);
10282                             } catch (RuntimeException e) {
10283                                 // If something goes wrong with the surface (such
10284                                 // as running out of memory), don't take down the
10285                                 // entire system.
10286                                 Slog.e(TAG, "Failure updating surface of " + w
10287                                         + "size=(" + width + "x" + height
10288                                         + "), pos=(" + w.mShownFrame.left
10289                                         + "," + w.mShownFrame.top + ")", e);
10290                                 if (!recoveringMemory) {
10291                                     reclaimSomeSurfaceMemoryLocked(w, "size");
10292                                 }
10293                             }
10294                         }
10295                     }
10296                     if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
10297                         w.mContentInsetsChanged =
10298                             !w.mLastContentInsets.equals(w.mContentInsets);
10299                         w.mVisibleInsetsChanged =
10300                             !w.mLastVisibleInsets.equals(w.mVisibleInsets);
10301                         boolean configChanged =
10302                             w.mConfiguration != mCurConfiguration
10303                             && (w.mConfiguration == null
10304                                     || mCurConfiguration.diff(w.mConfiguration) != 0);
10305                         if (DEBUG_CONFIGURATION && configChanged) {
10306                             Slog.v(TAG, "Win " + w + " config changed: "
10307                                     + mCurConfiguration);
10308                         }
10309                         if (localLOGV) Slog.v(TAG, "Resizing " + w
10310                                 + ": configChanged=" + configChanged
10311                                 + " last=" + w.mLastFrame + " frame=" + w.mFrame);
10312                         if (!w.mLastFrame.equals(w.mFrame)
10313                                 || w.mContentInsetsChanged
10314                                 || w.mVisibleInsetsChanged
10315                                 || w.mSurfaceResized
10316                                 || configChanged) {
10317                             w.mLastFrame.set(w.mFrame);
10318                             w.mLastContentInsets.set(w.mContentInsets);
10319                             w.mLastVisibleInsets.set(w.mVisibleInsets);
10320                             // If the screen is currently frozen, then keep
10321                             // it frozen until this window draws at its new
10322                             // orientation.
10323                             if (mDisplayFrozen) {
10324                                 if (DEBUG_ORIENTATION) Slog.v(TAG,
10325                                         "Resizing while display frozen: " + w);
10326                                 w.mOrientationChanging = true;
10327                                 if (!mWindowsFreezingScreen) {
10328                                     mWindowsFreezingScreen = true;
10329                                     // XXX should probably keep timeout from
10330                                     // when we first froze the display.
10331                                     mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
10332                                     mH.sendMessageDelayed(mH.obtainMessage(
10333                                             H.WINDOW_FREEZE_TIMEOUT), 2000);
10334                                 }
10335                             }
10336                             // If the orientation is changing, then we need to
10337                             // hold off on unfreezing the display until this
10338                             // window has been redrawn; to do that, we need
10339                             // to go through the process of getting informed
10340                             // by the application when it has finished drawing.
10341                             if (w.mOrientationChanging) {
10342                                 if (DEBUG_ORIENTATION) Slog.v(TAG,
10343                                         "Orientation start waiting for draw in "
10344                                         + w + ", surface " + w.mSurface);
10345                                 w.mDrawPending = true;
10346                                 w.mCommitDrawPending = false;
10347                                 w.mReadyToShow = false;
10348                                 if (w.mAppToken != null) {
10349                                     w.mAppToken.allDrawn = false;
10350                                 }
10351                             }
10352                             if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
10353                                     "Resizing window " + w + " to " + w.mFrame);
10354                             mResizingWindows.add(w);
10355                         } else if (w.mOrientationChanging) {
10356                             if (!w.mDrawPending && !w.mCommitDrawPending) {
10357                                 if (DEBUG_ORIENTATION) Slog.v(TAG,
10358                                         "Orientation not waiting for draw in "
10359                                         + w + ", surface " + w.mSurface);
10360                                 w.mOrientationChanging = false;
10361                             }
10362                         }
10363                     }
10364
10365                     if (w.mAttachedHidden || !w.isReadyForDisplay()) {
10366                         if (!w.mLastHidden) {
10367                             //dump();
10368                             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Window hiding: waitingToShow="
10369                                     + w.mRootToken.waitingToShow + " polvis="
10370                                     + w.mPolicyVisibility + " atthid="
10371                                     + w.mAttachedHidden + " tokhid="
10372                                     + w.mRootToken.hidden + " vis="
10373                                     + w.mViewVisibility);
10374                             w.mLastHidden = true;
10375                             if (SHOW_TRANSACTIONS) logSurface(w,
10376                                     "HIDE (performLayout)", null);
10377                             if (w.mSurface != null) {
10378                                 w.mSurfaceShown = false;
10379                                 try {
10380                                     w.mSurface.hide();
10381                                 } catch (RuntimeException e) {
10382                                     Slog.w(TAG, "Exception hiding surface in " + w);
10383                                 }
10384                             }
10385                             mKeyWaiter.releasePendingPointerLocked(w.mSession);
10386                         }
10387                         // If we are waiting for this window to handle an
10388                         // orientation change, well, it is hidden, so
10389                         // doesn't really matter.  Note that this does
10390                         // introduce a potential glitch if the window
10391                         // becomes unhidden before it has drawn for the
10392                         // new orientation.
10393                         if (w.mOrientationChanging) {
10394                             w.mOrientationChanging = false;
10395                             if (DEBUG_ORIENTATION) Slog.v(TAG,
10396                                     "Orientation change skips hidden " + w);
10397                         }
10398                     } else if (w.mLastLayer != w.mAnimLayer
10399                             || w.mLastAlpha != w.mShownAlpha
10400                             || w.mLastDsDx != w.mDsDx
10401                             || w.mLastDtDx != w.mDtDx
10402                             || w.mLastDsDy != w.mDsDy
10403                             || w.mLastDtDy != w.mDtDy
10404                             || w.mLastHScale != w.mHScale
10405                             || w.mLastVScale != w.mVScale
10406                             || w.mLastHidden) {
10407                         displayed = true;
10408                         w.mLastAlpha = w.mShownAlpha;
10409                         w.mLastLayer = w.mAnimLayer;
10410                         w.mLastDsDx = w.mDsDx;
10411                         w.mLastDtDx = w.mDtDx;
10412                         w.mLastDsDy = w.mDsDy;
10413                         w.mLastDtDy = w.mDtDy;
10414                         w.mLastHScale = w.mHScale;
10415                         w.mLastVScale = w.mVScale;
10416                         if (SHOW_TRANSACTIONS) logSurface(w,
10417                                 "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer
10418                                 + " matrix=[" + (w.mDsDx*w.mHScale)
10419                                 + "," + (w.mDtDx*w.mVScale)
10420                                 + "][" + (w.mDsDy*w.mHScale)
10421                                 + "," + (w.mDtDy*w.mVScale) + "]", null);
10422                         if (w.mSurface != null) {
10423                             try {
10424                                 w.mSurfaceAlpha = w.mShownAlpha;
10425                                 w.mSurface.setAlpha(w.mShownAlpha);
10426                                 w.mSurfaceLayer = w.mAnimLayer;
10427                                 w.mSurface.setLayer(w.mAnimLayer);
10428                                 w.mSurface.setMatrix(
10429                                         w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
10430                                         w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
10431                             } catch (RuntimeException e) {
10432                                 Slog.w(TAG, "Error updating surface in " + w, e);
10433                                 if (!recoveringMemory) {
10434                                     reclaimSomeSurfaceMemoryLocked(w, "update");
10435                                 }
10436                             }
10437                         }
10438
10439                         if (w.mLastHidden && !w.mDrawPending
10440                                 && !w.mCommitDrawPending
10441                                 && !w.mReadyToShow) {
10442                             if (SHOW_TRANSACTIONS) logSurface(w,
10443                                     "SHOW (performLayout)", null);
10444                             if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w
10445                                     + " during relayout");
10446                             if (showSurfaceRobustlyLocked(w)) {
10447                                 w.mHasDrawn = true;
10448                                 w.mLastHidden = false;
10449                             } else {
10450                                 w.mOrientationChanging = false;
10451                             }
10452                         }
10453                         if (w.mSurface != null) {
10454                             w.mToken.hasVisible = true;
10455                         }
10456                     } else {
10457                         displayed = true;
10458                     }
10459
10460                     if (displayed) {
10461                         if (!covered) {
10462                             if (attrs.width == LayoutParams.MATCH_PARENT
10463                                     && attrs.height == LayoutParams.MATCH_PARENT) {
10464                                 covered = true;
10465                             }
10466                         }
10467                         if (w.mOrientationChanging) {
10468                             if (w.mDrawPending || w.mCommitDrawPending) {
10469                                 orientationChangeComplete = false;
10470                                 if (DEBUG_ORIENTATION) Slog.v(TAG,
10471                                         "Orientation continue waiting for draw in " + w);
10472                             } else {
10473                                 w.mOrientationChanging = false;
10474                                 if (DEBUG_ORIENTATION) Slog.v(TAG,
10475                                         "Orientation change complete in " + w);
10476                             }
10477                         }
10478                         w.mToken.hasVisible = true;
10479                     }
10480                 } else if (w.mOrientationChanging) {
10481                     if (DEBUG_ORIENTATION) Slog.v(TAG,
10482                             "Orientation change skips hidden " + w);
10483                     w.mOrientationChanging = false;
10484                 }
10485
10486                 final boolean canBeSeen = w.isDisplayedLw();
10487
10488                 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) {
10489                     focusDisplayed = true;
10490                 }
10491
10492                 final boolean obscuredChanged = w.mObscured != obscured;
10493
10494                 // Update effect.
10495                 if (!(w.mObscured=obscured)) {
10496                     if (w.mSurface != null) {
10497                         if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
10498                             holdScreen = w.mSession;
10499                         }
10500                         if (!syswin && w.mAttrs.screenBrightness >= 0
10501                                 && screenBrightness < 0) {
10502                             screenBrightness = w.mAttrs.screenBrightness;
10503                         }
10504                         if (!syswin && w.mAttrs.buttonBrightness >= 0
10505                                 && buttonBrightness < 0) {
10506                             buttonBrightness = w.mAttrs.buttonBrightness;
10507                         }
10508                         if (canBeSeen
10509                                 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
10510                                  || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD
10511                                  || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) {
10512                             syswin = true;
10513                         }
10514                     }
10515
10516                     boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
10517                     if (opaqueDrawn && w.isFullscreen(dw, dh)) {
10518                         // This window completely covers everything behind it,
10519                         // so we want to leave all of them as unblurred (for
10520                         // performance reasons).
10521                         obscured = true;
10522                     } else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) {
10523                         if (SHOW_TRANSACTIONS) Slog.d(TAG, "showing background filler");
10524                         // This window is in compatibility mode, and needs background filler.
10525                         obscured = true;
10526                         if (mBackgroundFillerSurface == null) {
10527                             try {
10528                                 mBackgroundFillerSurface = new Surface(mFxSession, 0,
10529                                         "BackGroundFiller",
10530                                         0, dw, dh,
10531                                         PixelFormat.OPAQUE,
10532                                         Surface.FX_SURFACE_NORMAL);
10533                             } catch (Exception e) {
10534                                 Slog.e(TAG, "Exception creating filler surface", e);
10535                             }
10536                         }
10537                         try {
10538                             mBackgroundFillerSurface.setPosition(0, 0);
10539                             mBackgroundFillerSurface.setSize(dw, dh);
10540                             // Using the same layer as Dim because they will never be shown at the
10541                             // same time.
10542                             mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1);
10543                             mBackgroundFillerSurface.show();
10544                         } catch (RuntimeException e) {
10545                             Slog.e(TAG, "Exception showing filler surface");
10546                         }
10547                         backgroundFillerShown = true;
10548                         mBackgroundFillerShown = true;
10549                     } else if (canBeSeen && !obscured &&
10550                             (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
10551                         if (localLOGV) Slog.v(TAG, "Win " + w
10552                                 + ": blurring=" + blurring
10553                                 + " obscured=" + obscured
10554                                 + " displayed=" + displayed);
10555                         if ((attrFlags&FLAG_DIM_BEHIND) != 0) {
10556                             if (!dimming) {
10557                                 //Slog.i(TAG, "DIM BEHIND: " + w);
10558                                 dimming = true;
10559                                 if (mDimAnimator == null) {
10560                                     mDimAnimator = new DimAnimator(mFxSession);
10561                                 }
10562                                 mDimAnimator.show(dw, dh);
10563                                 mDimAnimator.updateParameters(w, currentTime);
10564                             }
10565                         }
10566                         if ((attrFlags&FLAG_BLUR_BEHIND) != 0) {
10567                             if (!blurring) {
10568                                 //Slog.i(TAG, "BLUR BEHIND: " + w);
10569                                 blurring = true;
10570                                 if (mBlurSurface == null) {
10571                                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  BLUR "
10572                                             + mBlurSurface + ": CREATE");
10573                                     try {
10574                                         mBlurSurface = new Surface(mFxSession, 0,
10575                                                 "BlurSurface",
10576                                                 -1, 16, 16,
10577                                                 PixelFormat.OPAQUE,
10578                                                 Surface.FX_SURFACE_BLUR);
10579                                     } catch (Exception e) {
10580                                         Slog.e(TAG, "Exception creating Blur surface", e);
10581                                     }
10582                                 }
10583                                 if (mBlurSurface != null) {
10584                                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  BLUR "
10585                                             + mBlurSurface + ": pos=(0,0) (" +
10586                                             dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
10587                                     mBlurSurface.setPosition(0, 0);
10588                                     mBlurSurface.setSize(dw, dh);
10589                                     mBlurSurface.setLayer(w.mAnimLayer-2);
10590                                     if (!mBlurShown) {
10591                                         try {
10592                                             if (SHOW_TRANSACTIONS) Slog.i(TAG, "  BLUR "
10593                                                     + mBlurSurface + ": SHOW");
10594                                             mBlurSurface.show();
10595                                         } catch (RuntimeException e) {
10596                                             Slog.w(TAG, "Failure showing blur surface", e);
10597                                         }
10598                                         mBlurShown = true;
10599                                     }
10600                                 }
10601                             }
10602                         }
10603                     }
10604                 }
10605
10606                 if (obscuredChanged && mWallpaperTarget == w) {
10607                     // This is the wallpaper target and its obscured state
10608                     // changed... make sure the current wallaper's visibility
10609                     // has been updated accordingly.
10610                     updateWallpaperVisibilityLocked();
10611                 }
10612             }
10613
10614             if (backgroundFillerShown == false && mBackgroundFillerShown) {
10615                 mBackgroundFillerShown = false;
10616                 if (SHOW_TRANSACTIONS) Slog.d(TAG, "hiding background filler");
10617                 try {
10618                     mBackgroundFillerSurface.hide();
10619                 } catch (RuntimeException e) {
10620                     Slog.e(TAG, "Exception hiding filler surface", e);
10621                 }
10622             }
10623
10624             if (mDimAnimator != null && mDimAnimator.mDimShown) {
10625                 animating |= mDimAnimator.updateSurface(dimming, currentTime,
10626                         mDisplayFrozen || !mPolicy.isScreenOn());
10627             }
10628
10629             if (!blurring && mBlurShown) {
10630                 if (SHOW_TRANSACTIONS) Slog.i(TAG, "  BLUR " + mBlurSurface
10631                         + ": HIDE");
10632                 try {
10633                     mBlurSurface.hide();
10634                 } catch (IllegalArgumentException e) {
10635                     Slog.w(TAG, "Illegal argument exception hiding blur surface");
10636                 }
10637                 mBlurShown = false;
10638             }
10639
10640             if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
10641         } catch (RuntimeException e) {
10642             Slog.e(TAG, "Unhandled exception in Window Manager", e);
10643         }
10644
10645         Surface.closeTransaction();
10646
10647         if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
10648                 "With display frozen, orientationChangeComplete="
10649                 + orientationChangeComplete);
10650         if (orientationChangeComplete) {
10651             if (mWindowsFreezingScreen) {
10652                 mWindowsFreezingScreen = false;
10653                 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
10654             }
10655             stopFreezingDisplayLocked();
10656         }
10657
10658         i = mResizingWindows.size();
10659         if (i > 0) {
10660             do {
10661                 i--;
10662                 WindowState win = mResizingWindows.get(i);
10663                 try {
10664                     if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
10665                             "Reporting new frame to " + win + ": " + win.mFrame);
10666                     int diff = 0;
10667                     boolean configChanged =
10668                         win.mConfiguration != mCurConfiguration
10669                         && (win.mConfiguration == null
10670                                 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0);
10671                     if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
10672                             && configChanged) {
10673                         Slog.i(TAG, "Sending new config to window " + win + ": "
10674                                 + win.mFrame.width() + "x" + win.mFrame.height()
10675                                 + " / " + mCurConfiguration + " / 0x"
10676                                 + Integer.toHexString(diff));
10677                     }
10678                     win.mConfiguration = mCurConfiguration;
10679                     win.mClient.resized(win.mFrame.width(),
10680                             win.mFrame.height(), win.mLastContentInsets,
10681                             win.mLastVisibleInsets, win.mDrawPending,
10682                             configChanged ? win.mConfiguration : null);
10683                     win.mContentInsetsChanged = false;
10684                     win.mVisibleInsetsChanged = false;
10685                     win.mSurfaceResized = false;
10686                 } catch (RemoteException e) {
10687                     win.mOrientationChanging = false;
10688                 }
10689             } while (i > 0);
10690             mResizingWindows.clear();
10691         }
10692
10693         // Destroy the surface of any windows that are no longer visible.
10694         boolean wallpaperDestroyed = false;
10695         i = mDestroySurface.size();
10696         if (i > 0) {
10697             do {
10698                 i--;
10699                 WindowState win = mDestroySurface.get(i);
10700                 win.mDestroying = false;
10701                 if (mInputMethodWindow == win) {
10702                     mInputMethodWindow = null;
10703                 }
10704                 if (win == mWallpaperTarget) {
10705                     wallpaperDestroyed = true;
10706                 }
10707                 win.destroySurfaceLocked();
10708             } while (i > 0);
10709             mDestroySurface.clear();
10710         }
10711
10712         // Time to remove any exiting tokens?
10713         for (i=mExitingTokens.size()-1; i>=0; i--) {
10714             WindowToken token = mExitingTokens.get(i);
10715             if (!token.hasVisible) {
10716                 mExitingTokens.remove(i);
10717                 if (token.windowType == TYPE_WALLPAPER) {
10718                     mWallpaperTokens.remove(token);
10719                 }
10720             }
10721         }
10722
10723         // Time to remove any exiting applications?
10724         for (i=mExitingAppTokens.size()-1; i>=0; i--) {
10725             AppWindowToken token = mExitingAppTokens.get(i);
10726             if (!token.hasVisible && !mClosingApps.contains(token)) {
10727                 // Make sure there is no animation running on this token,
10728                 // so any windows associated with it will be removed as
10729                 // soon as their animations are complete
10730                 token.animation = null;
10731                 token.animating = false;
10732                 mAppTokens.remove(token);
10733                 mExitingAppTokens.remove(i);
10734                 if (mLastEnterAnimToken == token) {
10735                     mLastEnterAnimToken = null;
10736                     mLastEnterAnimParams = null;
10737                 }
10738             }
10739         }
10740
10741         boolean needRelayout = false;
10742
10743         if (!animating && mAppTransitionRunning) {
10744             // We have finished the animation of an app transition.  To do
10745             // this, we have delayed a lot of operations like showing and
10746             // hiding apps, moving apps in Z-order, etc.  The app token list
10747             // reflects the correct Z-order, but the window list may now
10748             // be out of sync with it.  So here we will just rebuild the
10749             // entire app window list.  Fun!
10750             mAppTransitionRunning = false;
10751             needRelayout = true;
10752             rebuildAppWindowListLocked();
10753             assignLayersLocked();
10754             // Clear information about apps that were moving.
10755             mToBottomApps.clear();
10756         }
10757
10758         if (focusDisplayed) {
10759             mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
10760         }
10761         if (wallpaperDestroyed) {
10762             needRelayout = adjustWallpaperWindowsLocked() != 0;
10763         }
10764         if (needRelayout) {
10765             requestAnimationLocked(0);
10766         } else if (animating) {
10767             requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
10768         }
10769         
10770         if (DEBUG_FREEZE) Slog.v(TAG, "Layout: mDisplayFrozen=" + mDisplayFrozen
10771                 + " holdScreen=" + holdScreen);
10772         if (!mDisplayFrozen) {
10773             mQueue.setHoldScreenLocked(holdScreen != null);
10774             if (screenBrightness < 0 || screenBrightness > 1.0f) {
10775                 mPowerManager.setScreenBrightnessOverride(-1);
10776             } else {
10777                 mPowerManager.setScreenBrightnessOverride((int)
10778                         (screenBrightness * Power.BRIGHTNESS_ON));
10779             }
10780             if (buttonBrightness < 0 || buttonBrightness > 1.0f) {
10781                 mPowerManager.setButtonBrightnessOverride(-1);
10782             } else {
10783                 mPowerManager.setButtonBrightnessOverride((int)
10784                         (buttonBrightness * Power.BRIGHTNESS_ON));
10785             }
10786             if (holdScreen != mHoldingScreenOn) {
10787                 mHoldingScreenOn = holdScreen;
10788                 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen);
10789                 mH.sendMessage(m);
10790             }
10791         }
10792
10793         if (mTurnOnScreen) {
10794             if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
10795             mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
10796                     LocalPowerManager.BUTTON_EVENT, true);
10797             mTurnOnScreen = false;
10798         }
10799         
10800         // Check to see if we are now in a state where the screen should
10801         // be enabled, because the window obscured flags have changed.
10802         enableScreenIfNeededLocked();
10803     }
10804
10805     void requestAnimationLocked(long delay) {
10806         if (!mAnimationPending) {
10807             mAnimationPending = true;
10808             mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay);
10809         }
10810     }
10811
10812     /**
10813      * Have the surface flinger show a surface, robustly dealing with
10814      * error conditions.  In particular, if there is not enough memory
10815      * to show the surface, then we will try to get rid of other surfaces
10816      * in order to succeed.
10817      *
10818      * @return Returns true if the surface was successfully shown.
10819      */
10820     boolean showSurfaceRobustlyLocked(WindowState win) {
10821         try {
10822             if (win.mSurface != null) {
10823                 win.mSurfaceShown = true;
10824                 win.mSurface.show();
10825                 if (win.mTurnOnScreen) {
10826                     if (DEBUG_VISIBILITY) Slog.v(TAG,
10827                             "Show surface turning screen on: " + win);
10828                     win.mTurnOnScreen = false;
10829                     mTurnOnScreen = true;
10830                 }
10831             }
10832             return true;
10833         } catch (RuntimeException e) {
10834             Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win);
10835         }
10836
10837         reclaimSomeSurfaceMemoryLocked(win, "show");
10838
10839         return false;
10840     }
10841
10842     void reclaimSomeSurfaceMemoryLocked(WindowState win, String operation) {
10843         final Surface surface = win.mSurface;
10844
10845         EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, win.toString(),
10846                 win.mSession.mPid, operation);
10847
10848         if (mForceRemoves == null) {
10849             mForceRemoves = new ArrayList<WindowState>();
10850         }
10851
10852         long callingIdentity = Binder.clearCallingIdentity();
10853         try {
10854             // There was some problem...   first, do a sanity check of the
10855             // window list to make sure we haven't left any dangling surfaces
10856             // around.
10857             int N = mWindows.size();
10858             boolean leakedSurface = false;
10859             Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
10860             for (int i=0; i<N; i++) {
10861                 WindowState ws = (WindowState)mWindows.get(i);
10862                 if (ws.mSurface != null) {
10863                     if (!mSessions.contains(ws.mSession)) {
10864                         Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
10865                                 + ws + " surface=" + ws.mSurface
10866                                 + " token=" + win.mToken
10867                                 + " pid=" + ws.mSession.mPid
10868                                 + " uid=" + ws.mSession.mUid);
10869                         ws.mSurface.destroy();
10870                         ws.mSurfaceShown = false;
10871                         ws.mSurface = null;
10872                         mForceRemoves.add(ws);
10873                         i--;
10874                         N--;
10875                         leakedSurface = true;
10876                     } else if (win.mAppToken != null && win.mAppToken.clientHidden) {
10877                         Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
10878                                 + ws + " surface=" + ws.mSurface
10879                                 + " token=" + win.mAppToken);
10880                         ws.mSurface.destroy();
10881                         ws.mSurfaceShown = false;
10882                         ws.mSurface = null;
10883                         leakedSurface = true;
10884                     }
10885                 }
10886             }
10887
10888             boolean killedApps = false;
10889             if (!leakedSurface) {
10890                 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
10891                 SparseIntArray pidCandidates = new SparseIntArray();
10892                 for (int i=0; i<N; i++) {
10893                     WindowState ws = (WindowState)mWindows.get(i);
10894                     if (ws.mSurface != null) {
10895                         pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid);
10896                     }
10897                 }
10898                 if (pidCandidates.size() > 0) {
10899                     int[] pids = new int[pidCandidates.size()];
10900                     for (int i=0; i<pids.length; i++) {
10901                         pids[i] = pidCandidates.keyAt(i);
10902                     }
10903                     try {
10904                         if (mActivityManager.killPids(pids, "Free memory")) {
10905                             killedApps = true;
10906                         }
10907                     } catch (RemoteException e) {
10908                     }
10909                 }
10910             }
10911
10912             if (leakedSurface || killedApps) {
10913                 // We managed to reclaim some memory, so get rid of the trouble
10914                 // surface and ask the app to request another one.
10915                 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
10916                 if (surface != null) {
10917                     surface.destroy();
10918                     win.mSurfaceShown = false;
10919                     win.mSurface = null;
10920                 }
10921
10922                 try {
10923                     win.mClient.dispatchGetNewSurface();
10924                 } catch (RemoteException e) {
10925                 }
10926             }
10927         } finally {
10928             Binder.restoreCallingIdentity(callingIdentity);
10929         }
10930     }
10931
10932     private boolean updateFocusedWindowLocked(int mode) {
10933         WindowState newFocus = computeFocusedWindowLocked();
10934         if (mCurrentFocus != newFocus) {
10935             // This check makes sure that we don't already have the focus
10936             // change message pending.
10937             mH.removeMessages(H.REPORT_FOCUS_CHANGE);
10938             mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
10939             if (localLOGV) Slog.v(
10940                 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
10941             final WindowState oldFocus = mCurrentFocus;
10942             mCurrentFocus = newFocus;
10943             mLosingFocus.remove(newFocus);
10944
10945             final WindowState imWindow = mInputMethodWindow;
10946             if (newFocus != imWindow && oldFocus != imWindow) {
10947                 if (moveInputMethodWindowsIfNeededLocked(
10948                         mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
10949                         mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
10950                     mLayoutNeeded = true;
10951                 }
10952                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
10953                     performLayoutLockedInner();
10954                 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
10955                     // Client will do the layout, but we need to assign layers
10956                     // for handleNewWindowLocked() below.
10957                     assignLayersLocked();
10958                 }
10959             }
10960
10961             if (newFocus != null && mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
10962                 mKeyWaiter.handleNewWindowLocked(newFocus);
10963             }
10964             return true;
10965         }
10966         return false;
10967     }
10968
10969     private WindowState computeFocusedWindowLocked() {
10970         WindowState result = null;
10971         WindowState win;
10972
10973         int i = mWindows.size() - 1;
10974         int nextAppIndex = mAppTokens.size()-1;
10975         WindowToken nextApp = nextAppIndex >= 0
10976             ? mAppTokens.get(nextAppIndex) : null;
10977
10978         while (i >= 0) {
10979             win = (WindowState)mWindows.get(i);
10980
10981             if (localLOGV || DEBUG_FOCUS) Slog.v(
10982                 TAG, "Looking for focus: " + i
10983                 + " = " + win
10984                 + ", flags=" + win.mAttrs.flags
10985                 + ", canReceive=" + win.canReceiveKeys());
10986
10987             AppWindowToken thisApp = win.mAppToken;
10988
10989             // If this window's application has been removed, just skip it.
10990             if (thisApp != null && thisApp.removed) {
10991                 i--;
10992                 continue;
10993             }
10994
10995             // If there is a focused app, don't allow focus to go to any
10996             // windows below it.  If this is an application window, step
10997             // through the app tokens until we find its app.
10998             if (thisApp != null && nextApp != null && thisApp != nextApp
10999                     && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
11000                 int origAppIndex = nextAppIndex;
11001                 while (nextAppIndex > 0) {
11002                     if (nextApp == mFocusedApp) {
11003                         // Whoops, we are below the focused app...  no focus
11004                         // for you!
11005                         if (localLOGV || DEBUG_FOCUS) Slog.v(
11006                             TAG, "Reached focused app: " + mFocusedApp);
11007                         return null;
11008                     }
11009                     nextAppIndex--;
11010                     nextApp = mAppTokens.get(nextAppIndex);
11011                     if (nextApp == thisApp) {
11012                         break;
11013                     }
11014                 }
11015                 if (thisApp != nextApp) {
11016                     // Uh oh, the app token doesn't exist!  This shouldn't
11017                     // happen, but if it does we can get totally hosed...
11018                     // so restart at the original app.
11019                     nextAppIndex = origAppIndex;
11020                     nextApp = mAppTokens.get(nextAppIndex);
11021                 }
11022             }
11023
11024             // Dispatch to this window if it is wants key events.
11025             if (win.canReceiveKeys()) {
11026                 if (DEBUG_FOCUS) Slog.v(
11027                         TAG, "Found focus @ " + i + " = " + win);
11028                 result = win;
11029                 break;
11030             }
11031
11032             i--;
11033         }
11034
11035         return result;
11036     }
11037
11038     private void startFreezingDisplayLocked() {
11039         if (mDisplayFrozen) {
11040             // Freezing the display also suspends key event delivery, to
11041             // keep events from going astray while the display is reconfigured.
11042             // If someone has changed orientation again while the screen is
11043             // still frozen, the events will continue to be blocked while the
11044             // successive orientation change is processed.  To prevent spurious
11045             // ANRs, we reset the event dispatch timeout in this case.
11046             synchronized (mKeyWaiter) {
11047                 mKeyWaiter.mWasFrozen = true;
11048             }
11049             return;
11050         }
11051
11052         mScreenFrozenLock.acquire();
11053
11054         long now = SystemClock.uptimeMillis();
11055         //Slog.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now);
11056         if (mFreezeGcPending != 0) {
11057             if (now > (mFreezeGcPending+1000)) {
11058                 //Slog.i(TAG, "Gc!  " + now + " > " + (mFreezeGcPending+1000));
11059                 mH.removeMessages(H.FORCE_GC);
11060                 Runtime.getRuntime().gc();
11061                 mFreezeGcPending = now;
11062             }
11063         } else {
11064             mFreezeGcPending = now;
11065         }
11066
11067         if (DEBUG_FREEZE) Slog.v(TAG, "*** FREEZING DISPLAY", new RuntimeException());
11068         
11069         mDisplayFrozen = true;
11070         if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
11071             mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
11072             mNextAppTransitionPackage = null;
11073             mAppTransitionReady = true;
11074         }
11075
11076         if (PROFILE_ORIENTATION) {
11077             File file = new File("/data/system/frozen");
11078             Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
11079         }
11080         Surface.freezeDisplay(0);
11081     }
11082
11083     private void stopFreezingDisplayLocked() {
11084         if (!mDisplayFrozen) {
11085             return;
11086         }
11087
11088         if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) {
11089             return;
11090         }
11091         
11092         if (DEBUG_FREEZE) Slog.v(TAG, "*** UNFREEZING DISPLAY", new RuntimeException());
11093         
11094         mDisplayFrozen = false;
11095         mH.removeMessages(H.APP_FREEZE_TIMEOUT);
11096         if (PROFILE_ORIENTATION) {
11097             Debug.stopMethodTracing();
11098         }
11099         Surface.unfreezeDisplay(0);
11100
11101         // Reset the key delivery timeout on unfreeze, too.  We force a wakeup here
11102         // too because regular key delivery processing should resume immediately.
11103         synchronized (mKeyWaiter) {
11104             mKeyWaiter.mWasFrozen = true;
11105             mKeyWaiter.notifyAll();
11106         }
11107
11108         // While the display is frozen we don't re-compute the orientation
11109         // to avoid inconsistent states.  However, something interesting
11110         // could have actually changed during that time so re-evaluate it
11111         // now to catch that.
11112         if (updateOrientationFromAppTokensLocked()) {
11113             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
11114         }
11115
11116         // A little kludge: a lot could have happened while the
11117         // display was frozen, so now that we are coming back we
11118         // do a gc so that any remote references the system
11119         // processes holds on others can be released if they are
11120         // no longer needed.
11121         mH.removeMessages(H.FORCE_GC);
11122         mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
11123                 2000);
11124
11125         mScreenFrozenLock.release();
11126     }
11127
11128     @Override
11129     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
11130         if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
11131                 != PackageManager.PERMISSION_GRANTED) {
11132             pw.println("Permission Denial: can't dump WindowManager from from pid="
11133                     + Binder.getCallingPid()
11134                     + ", uid=" + Binder.getCallingUid());
11135             return;
11136         }
11137
11138         pw.println("Input State:");
11139         mQueue.dump(pw, "  ");
11140         pw.println(" ");
11141         
11142         synchronized(mWindowMap) {
11143             pw.println("Current Window Manager state:");
11144             for (int i=mWindows.size()-1; i>=0; i--) {
11145                 WindowState w = (WindowState)mWindows.get(i);
11146                 pw.print("  Window #"); pw.print(i); pw.print(' ');
11147                         pw.print(w); pw.println(":");
11148                 w.dump(pw, "    ");
11149             }
11150             if (mInputMethodDialogs.size() > 0) {
11151                 pw.println(" ");
11152                 pw.println("  Input method dialogs:");
11153                 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
11154                     WindowState w = mInputMethodDialogs.get(i);
11155                     pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
11156                 }
11157             }
11158             if (mPendingRemove.size() > 0) {
11159                 pw.println(" ");
11160                 pw.println("  Remove pending for:");
11161                 for (int i=mPendingRemove.size()-1; i>=0; i--) {
11162                     WindowState w = mPendingRemove.get(i);
11163                     pw.print("  Remove #"); pw.print(i); pw.print(' ');
11164                             pw.print(w); pw.println(":");
11165                     w.dump(pw, "    ");
11166                 }
11167             }
11168             if (mForceRemoves != null && mForceRemoves.size() > 0) {
11169                 pw.println(" ");
11170                 pw.println("  Windows force removing:");
11171                 for (int i=mForceRemoves.size()-1; i>=0; i--) {
11172                     WindowState w = mForceRemoves.get(i);
11173                     pw.print("  Removing #"); pw.print(i); pw.print(' ');
11174                             pw.print(w); pw.println(":");
11175                     w.dump(pw, "    ");
11176                 }
11177             }
11178             if (mDestroySurface.size() > 0) {
11179                 pw.println(" ");
11180                 pw.println("  Windows waiting to destroy their surface:");
11181                 for (int i=mDestroySurface.size()-1; i>=0; i--) {
11182                     WindowState w = mDestroySurface.get(i);
11183                     pw.print("  Destroy #"); pw.print(i); pw.print(' ');
11184                             pw.print(w); pw.println(":");
11185                     w.dump(pw, "    ");
11186                 }
11187             }
11188             if (mLosingFocus.size() > 0) {
11189                 pw.println(" ");
11190                 pw.println("  Windows losing focus:");
11191                 for (int i=mLosingFocus.size()-1; i>=0; i--) {
11192                     WindowState w = mLosingFocus.get(i);
11193                     pw.print("  Losing #"); pw.print(i); pw.print(' ');
11194                             pw.print(w); pw.println(":");
11195                     w.dump(pw, "    ");
11196                 }
11197             }
11198             if (mResizingWindows.size() > 0) {
11199                 pw.println(" ");
11200                 pw.println("  Windows waiting to resize:");
11201                 for (int i=mResizingWindows.size()-1; i>=0; i--) {
11202                     WindowState w = mResizingWindows.get(i);
11203                     pw.print("  Resizing #"); pw.print(i); pw.print(' ');
11204                             pw.print(w); pw.println(":");
11205                     w.dump(pw, "    ");
11206                 }
11207             }
11208             if (mSessions.size() > 0) {
11209                 pw.println(" ");
11210                 pw.println("  All active sessions:");
11211                 Iterator<Session> it = mSessions.iterator();
11212                 while (it.hasNext()) {
11213                     Session s = it.next();
11214                     pw.print("  Session "); pw.print(s); pw.println(':');
11215                     s.dump(pw, "    ");
11216                 }
11217             }
11218             if (mTokenMap.size() > 0) {
11219                 pw.println(" ");
11220                 pw.println("  All tokens:");
11221                 Iterator<WindowToken> it = mTokenMap.values().iterator();
11222                 while (it.hasNext()) {
11223                     WindowToken token = it.next();
11224                     pw.print("  Token "); pw.print(token.token); pw.println(':');
11225                     token.dump(pw, "    ");
11226                 }
11227             }
11228             if (mTokenList.size() > 0) {
11229                 pw.println(" ");
11230                 pw.println("  Window token list:");
11231                 for (int i=0; i<mTokenList.size(); i++) {
11232                     pw.print("  #"); pw.print(i); pw.print(": ");
11233                             pw.println(mTokenList.get(i));
11234                 }
11235             }
11236             if (mWallpaperTokens.size() > 0) {
11237                 pw.println(" ");
11238                 pw.println("  Wallpaper tokens:");
11239                 for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
11240                     WindowToken token = mWallpaperTokens.get(i);
11241                     pw.print("  Wallpaper #"); pw.print(i);
11242                             pw.print(' '); pw.print(token); pw.println(':');
11243                     token.dump(pw, "    ");
11244                 }
11245             }
11246             if (mAppTokens.size() > 0) {
11247                 pw.println(" ");
11248                 pw.println("  Application tokens in Z order:");
11249                 for (int i=mAppTokens.size()-1; i>=0; i--) {
11250                     pw.print("  App #"); pw.print(i); pw.print(": ");
11251                             pw.println(mAppTokens.get(i));
11252                 }
11253             }
11254             if (mFinishedStarting.size() > 0) {
11255                 pw.println(" ");
11256                 pw.println("  Finishing start of application tokens:");
11257                 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
11258                     WindowToken token = mFinishedStarting.get(i);
11259                     pw.print("  Finished Starting #"); pw.print(i);
11260                             pw.print(' '); pw.print(token); pw.println(':');
11261                     token.dump(pw, "    ");
11262                 }
11263             }
11264             if (mExitingTokens.size() > 0) {
11265                 pw.println(" ");
11266                 pw.println("  Exiting tokens:");
11267                 for (int i=mExitingTokens.size()-1; i>=0; i--) {
11268                     WindowToken token = mExitingTokens.get(i);
11269                     pw.print("  Exiting #"); pw.print(i);
11270                             pw.print(' '); pw.print(token); pw.println(':');
11271                     token.dump(pw, "    ");
11272                 }
11273             }
11274             if (mExitingAppTokens.size() > 0) {
11275                 pw.println(" ");
11276                 pw.println("  Exiting application tokens:");
11277                 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
11278                     WindowToken token = mExitingAppTokens.get(i);
11279                     pw.print("  Exiting App #"); pw.print(i);
11280                             pw.print(' '); pw.print(token); pw.println(':');
11281                     token.dump(pw, "    ");
11282                 }
11283             }
11284             pw.println(" ");
11285             pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
11286             pw.print("  mLastFocus="); pw.println(mLastFocus);
11287             pw.print("  mFocusedApp="); pw.println(mFocusedApp);
11288             pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
11289             pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
11290             pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
11291             if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) {
11292                 pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
11293                 pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
11294             }
11295             pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
11296             pw.print("  mInTouchMode="); pw.print(mInTouchMode);
11297                     pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
11298             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
11299                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
11300             pw.print("  mLayoutNeeded="); pw.print(mLayoutNeeded);
11301                     pw.print(" mBlurShown="); pw.println(mBlurShown);
11302             if (mDimAnimator != null) {
11303                 mDimAnimator.printTo(pw);
11304             } else {
11305                 pw.println( "  no DimAnimator ");
11306             }
11307             pw.print("  mInputMethodAnimLayerAdjustment=");
11308                     pw.print(mInputMethodAnimLayerAdjustment);
11309                     pw.print("  mWallpaperAnimLayerAdjustment=");
11310                     pw.println(mWallpaperAnimLayerAdjustment);
11311             pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
11312                     pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
11313             pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
11314                     pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
11315                     pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
11316                     pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig);
11317             pw.print("  mRotation="); pw.print(mRotation);
11318                     pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
11319                     pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
11320             pw.print("  mAnimationPending="); pw.print(mAnimationPending);
11321                     pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
11322                     pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale);
11323             pw.print("  mNextAppTransition=0x");
11324                     pw.print(Integer.toHexString(mNextAppTransition));
11325                     pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady);
11326                     pw.print(", mAppTransitionRunning="); pw.print(mAppTransitionRunning);
11327                     pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout);
11328             if (mNextAppTransitionPackage != null) {
11329                 pw.print("  mNextAppTransitionPackage=");
11330                     pw.print(mNextAppTransitionPackage);
11331                     pw.print(", mNextAppTransitionEnter=0x");
11332                     pw.print(Integer.toHexString(mNextAppTransitionEnter));
11333                     pw.print(", mNextAppTransitionExit=0x");
11334                     pw.print(Integer.toHexString(mNextAppTransitionExit));
11335             }
11336             pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
11337                     pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
11338             if (mLastEnterAnimToken != null || mLastEnterAnimToken != null) {
11339                 pw.print("  mLastEnterAnimToken="); pw.print(mLastEnterAnimToken);
11340                         pw.print(", mLastEnterAnimParams="); pw.println(mLastEnterAnimParams);
11341             }
11342             if (mOpeningApps.size() > 0) {
11343                 pw.print("  mOpeningApps="); pw.println(mOpeningApps);
11344             }
11345             if (mClosingApps.size() > 0) {
11346                 pw.print("  mClosingApps="); pw.println(mClosingApps);
11347             }
11348             if (mToTopApps.size() > 0) {
11349                 pw.print("  mToTopApps="); pw.println(mToTopApps);
11350             }
11351             if (mToBottomApps.size() > 0) {
11352                 pw.print("  mToBottomApps="); pw.println(mToBottomApps);
11353             }
11354             pw.print("  DisplayWidth="); pw.print(mDisplay.getWidth());
11355                     pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight());
11356             pw.println("  KeyWaiter state:");
11357             pw.print("    mLastWin="); pw.print(mKeyWaiter.mLastWin);
11358                     pw.print(" mLastBinder="); pw.println(mKeyWaiter.mLastBinder);
11359             pw.print("    mFinished="); pw.print(mKeyWaiter.mFinished);
11360                     pw.print(" mGotFirstWindow="); pw.print(mKeyWaiter.mGotFirstWindow);
11361                     pw.print(" mEventDispatching="); pw.print(mKeyWaiter.mEventDispatching);
11362                     pw.print(" mTimeToSwitch="); pw.println(mKeyWaiter.mTimeToSwitch);
11363         }
11364     }
11365
11366     public void monitor() {
11367         synchronized (mWindowMap) { }
11368         synchronized (mKeyguardTokenWatcher) { }
11369         synchronized (mKeyWaiter) { }
11370     }
11371
11372     public void virtualKeyFeedback(KeyEvent event) {
11373         mPolicy.keyFeedbackFromInput(event);
11374     }
11375
11376     /**
11377      * DimAnimator class that controls the dim animation. This holds the surface and
11378      * all state used for dim animation.
11379      */
11380     private static class DimAnimator {
11381         Surface mDimSurface;
11382         boolean mDimShown = false;
11383         float mDimCurrentAlpha;
11384         float mDimTargetAlpha;
11385         float mDimDeltaPerMs;
11386         long mLastDimAnimTime;
11387         
11388         int mLastDimWidth, mLastDimHeight;
11389
11390         DimAnimator (SurfaceSession session) {
11391             if (mDimSurface == null) {
11392                 if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM "
11393                         + mDimSurface + ": CREATE");
11394                 try {
11395                     mDimSurface = new Surface(session, 0,
11396                             "DimSurface",
11397                             -1, 16, 16, PixelFormat.OPAQUE,
11398                             Surface.FX_SURFACE_DIM);
11399                     mDimSurface.setAlpha(0.0f);
11400                 } catch (Exception e) {
11401                     Slog.e(TAG, "Exception creating Dim surface", e);
11402                 }
11403             }
11404         }
11405
11406         /**
11407          * Show the dim surface.
11408          */
11409         void show(int dw, int dh) {
11410             if (!mDimShown) {
11411                 if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
11412                         dw + "x" + dh + ")");
11413                 mDimShown = true;
11414                 try {
11415                     mLastDimWidth = dw;
11416                     mLastDimHeight = dh;
11417                     mDimSurface.setPosition(0, 0);
11418                     mDimSurface.setSize(dw, dh);
11419                     mDimSurface.show();
11420                 } catch (RuntimeException e) {
11421                     Slog.w(TAG, "Failure showing dim surface", e);
11422                 }
11423             } else if (mLastDimWidth != dw || mLastDimHeight != dh) {
11424                 mLastDimWidth = dw;
11425                 mLastDimHeight = dh;
11426                 mDimSurface.setSize(dw, dh);
11427             }
11428         }
11429
11430         /**
11431          * Set's the dim surface's layer and update dim parameters that will be used in
11432          * {@link updateSurface} after all windows are examined.
11433          */
11434         void updateParameters(WindowState w, long currentTime) {
11435             mDimSurface.setLayer(w.mAnimLayer-1);
11436
11437             final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
11438             if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM " + mDimSurface
11439                     + ": layer=" + (w.mAnimLayer-1) + " target=" + target);
11440             if (mDimTargetAlpha != target) {
11441                 // If the desired dim level has changed, then
11442                 // start an animation to it.
11443                 mLastDimAnimTime = currentTime;
11444                 long duration = (w.mAnimating && w.mAnimation != null)
11445                         ? w.mAnimation.computeDurationHint()
11446                         : DEFAULT_DIM_DURATION;
11447                 if (target > mDimTargetAlpha) {
11448                     // This is happening behind the activity UI,
11449                     // so we can make it run a little longer to
11450                     // give a stronger impression without disrupting
11451                     // the user.
11452                     duration *= DIM_DURATION_MULTIPLIER;
11453                 }
11454                 if (duration < 1) {
11455                     // Don't divide by zero
11456                     duration = 1;
11457                 }
11458                 mDimTargetAlpha = target;
11459                 mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
11460             }
11461         }
11462
11463         /**
11464          * Updating the surface's alpha. Returns true if the animation continues, or returns
11465          * false when the animation is finished and the dim surface is hidden.
11466          */
11467         boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
11468             if (!dimming) {
11469                 if (mDimTargetAlpha != 0) {
11470                     mLastDimAnimTime = currentTime;
11471                     mDimTargetAlpha = 0;
11472                     mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION;
11473                 }
11474             }
11475
11476             boolean animating = false;
11477             if (mLastDimAnimTime != 0) {
11478                 mDimCurrentAlpha += mDimDeltaPerMs
11479                         * (currentTime-mLastDimAnimTime);
11480                 boolean more = true;
11481                 if (displayFrozen) {
11482                     // If the display is frozen, there is no reason to animate.
11483                     more = false;
11484                 } else if (mDimDeltaPerMs > 0) {
11485                     if (mDimCurrentAlpha > mDimTargetAlpha) {
11486                         more = false;
11487                     }
11488                 } else if (mDimDeltaPerMs < 0) {
11489                     if (mDimCurrentAlpha < mDimTargetAlpha) {
11490                         more = false;
11491                     }
11492                 } else {
11493                     more = false;
11494                 }
11495
11496                 // Do we need to continue animating?
11497                 if (more) {
11498                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM "
11499                             + mDimSurface + ": alpha=" + mDimCurrentAlpha);
11500                     mLastDimAnimTime = currentTime;
11501                     mDimSurface.setAlpha(mDimCurrentAlpha);
11502                     animating = true;
11503                 } else {
11504                     mDimCurrentAlpha = mDimTargetAlpha;
11505                     mLastDimAnimTime = 0;
11506                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM "
11507                             + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
11508                     mDimSurface.setAlpha(mDimCurrentAlpha);
11509                     if (!dimming) {
11510                         if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM " + mDimSurface
11511                                 + ": HIDE");
11512                         try {
11513                             mDimSurface.hide();
11514                         } catch (RuntimeException e) {
11515                             Slog.w(TAG, "Illegal argument exception hiding dim surface");
11516                         }
11517                         mDimShown = false;
11518                     }
11519                 }
11520             }
11521             return animating;
11522         }
11523
11524         public void printTo(PrintWriter pw) {
11525             pw.print("  mDimShown="); pw.print(mDimShown);
11526             pw.print(" current="); pw.print(mDimCurrentAlpha);
11527             pw.print(" target="); pw.print(mDimTargetAlpha);
11528             pw.print(" delta="); pw.print(mDimDeltaPerMs);
11529             pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
11530         }
11531     }
11532
11533     /**
11534      * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
11535      * This is used for opening/closing transition for apps in compatible mode.
11536      */
11537     private static class FadeInOutAnimation extends Animation {
11538         int mWidth;
11539         boolean mFadeIn;
11540
11541         public FadeInOutAnimation(boolean fadeIn) {
11542             setInterpolator(new AccelerateInterpolator());
11543             setDuration(DEFAULT_FADE_IN_OUT_DURATION);
11544             mFadeIn = fadeIn;
11545         }
11546
11547         @Override
11548         protected void applyTransformation(float interpolatedTime, Transformation t) {
11549             float x = interpolatedTime;
11550             if (!mFadeIn) {
11551                 x = 1.0f - x; // reverse the interpolation for fade out
11552             }
11553             if (x < 0.5) {
11554                 // move the window out of the screen.
11555                 t.getMatrix().setTranslate(mWidth, 0);
11556             } else {
11557                 t.getMatrix().setTranslate(0, 0);// show
11558                 t.setAlpha((x - 0.5f) * 2);
11559             }
11560         }
11561
11562         @Override
11563         public void initialize(int width, int height, int parentWidth, int parentHeight) {
11564             // width is the screen width {@see AppWindowToken#stepAnimatinoLocked}
11565             mWidth = width;
11566         }
11567
11568         @Override
11569         public int getZAdjustment() {
11570             return Animation.ZORDER_TOP;
11571         }
11572     }
11573 }