OSDN Git Service

Merge "Add task to list before looking it up." into klp-dev
[android-x86/frameworks-base.git] / services / java / com / android / server / wm / 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.wm;
18
19 import static android.view.WindowManager.LayoutParams.*;
20
21 import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
22
23 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
24
25 import android.app.AppOpsManager;
26 import android.util.TimeUtils;
27 import android.view.IWindowId;
28
29 import com.android.internal.app.IBatteryStats;
30 import com.android.internal.policy.PolicyManager;
31 import com.android.internal.policy.impl.PhoneWindowManager;
32 import com.android.internal.util.FastPrintWriter;
33 import com.android.internal.view.IInputContext;
34 import com.android.internal.view.IInputMethodClient;
35 import com.android.internal.view.IInputMethodManager;
36 import com.android.internal.view.WindowManagerPolicyThread;
37 import com.android.server.AttributeCache;
38 import com.android.server.EventLogTags;
39 import com.android.server.UiThread;
40 import com.android.server.Watchdog;
41 import com.android.server.am.BatteryStatsService;
42 import com.android.server.display.DisplayManagerService;
43 import com.android.server.input.InputManagerService;
44 import com.android.server.power.PowerManagerService;
45 import com.android.server.power.ShutdownThread;
46
47 import android.Manifest;
48 import android.app.ActivityManager.StackBoxInfo;
49 import android.app.ActivityManagerNative;
50 import android.app.IActivityManager;
51 import android.app.StatusBarManager;
52 import android.app.admin.DevicePolicyManager;
53 import android.animation.ValueAnimator;
54 import android.content.BroadcastReceiver;
55 import android.content.Context;
56 import android.content.Intent;
57 import android.content.IntentFilter;
58 import android.content.pm.ActivityInfo;
59 import android.content.pm.PackageManager;
60 import android.content.res.CompatibilityInfo;
61 import android.content.res.Configuration;
62 import android.graphics.Bitmap;
63 import android.graphics.Bitmap.Config;
64 import android.graphics.Canvas;
65 import android.graphics.Matrix;
66 import android.graphics.PixelFormat;
67 import android.graphics.Point;
68 import android.graphics.Rect;
69 import android.graphics.RectF;
70 import android.graphics.Region;
71 import android.hardware.display.DisplayManager;
72 import android.os.Binder;
73 import android.os.Bundle;
74 import android.os.Debug;
75 import android.os.Handler;
76 import android.os.IBinder;
77 import android.os.IRemoteCallback;
78 import android.os.Looper;
79 import android.os.Message;
80 import android.os.Parcel;
81 import android.os.ParcelFileDescriptor;
82 import android.os.PowerManager;
83 import android.os.Process;
84 import android.os.RemoteException;
85 import android.os.ServiceManager;
86 import android.os.StrictMode;
87 import android.os.SystemClock;
88 import android.os.SystemProperties;
89 import android.os.Trace;
90 import android.os.WorkSource;
91 import android.provider.Settings;
92 import android.util.DisplayMetrics;
93 import android.util.EventLog;
94 import android.util.FloatMath;
95 import android.util.Log;
96 import android.util.SparseArray;
97 import android.util.Pair;
98 import android.util.Slog;
99 import android.util.SparseIntArray;
100 import android.util.TypedValue;
101 import android.view.Choreographer;
102 import android.view.Display;
103 import android.view.DisplayInfo;
104 import android.view.Gravity;
105 import android.view.IApplicationToken;
106 import android.view.IInputFilter;
107 import android.view.IMagnificationCallbacks;
108 import android.view.IOnKeyguardExitResult;
109 import android.view.IRotationWatcher;
110 import android.view.IWindow;
111 import android.view.IWindowManager;
112 import android.view.IWindowSession;
113 import android.view.InputChannel;
114 import android.view.InputDevice;
115 import android.view.InputEvent;
116 import android.view.InputEventReceiver;
117 import android.view.KeyEvent;
118 import android.view.MagnificationSpec;
119 import android.view.MotionEvent;
120 import android.view.Surface.OutOfResourcesException;
121 import android.view.Surface;
122 import android.view.SurfaceControl;
123 import android.view.SurfaceSession;
124 import android.view.View;
125 import android.view.ViewTreeObserver;
126 import android.view.WindowManager;
127 import android.view.WindowManagerGlobal;
128 import android.view.WindowManagerPolicy;
129 import android.view.WindowManager.LayoutParams;
130 import android.view.WindowManagerPolicy.FakeWindow;
131 import android.view.WindowManagerPolicy.PointerEventListener;
132 import android.view.animation.Animation;
133 import android.view.animation.AnimationUtils;
134 import android.view.animation.Transformation;
135
136 import java.io.BufferedWriter;
137 import java.io.DataInputStream;
138 import java.io.File;
139 import java.io.FileDescriptor;
140 import java.io.FileInputStream;
141 import java.io.FileNotFoundException;
142 import java.io.IOException;
143 import java.io.OutputStream;
144 import java.io.OutputStreamWriter;
145 import java.io.PrintWriter;
146 import java.io.StringWriter;
147 import java.net.Socket;
148 import java.text.DateFormat;
149 import java.util.ArrayList;
150 import java.util.Date;
151 import java.util.HashMap;
152 import java.util.HashSet;
153 import java.util.Iterator;
154 import java.util.List;
155
156 /** {@hide} */
157 public class WindowManagerService extends IWindowManager.Stub
158         implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs,
159                 DisplayManagerService.WindowManagerFuncs, DisplayManager.DisplayListener {
160     static final String TAG = "WindowManager";
161     static final boolean DEBUG = false;
162     static final boolean DEBUG_ADD_REMOVE = false;
163     static final boolean DEBUG_FOCUS = false;
164     static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false;
165     static final boolean DEBUG_ANIM = false;
166     static final boolean DEBUG_LAYOUT = false;
167     static final boolean DEBUG_RESIZE = false;
168     static final boolean DEBUG_LAYERS = false;
169     static final boolean DEBUG_INPUT = false;
170     static final boolean DEBUG_INPUT_METHOD = false;
171     static final boolean DEBUG_VISIBILITY = false;
172     static final boolean DEBUG_WINDOW_MOVEMENT = false;
173     static final boolean DEBUG_TOKEN_MOVEMENT = false;
174     static final boolean DEBUG_ORIENTATION = false;
175     static final boolean DEBUG_APP_ORIENTATION = false;
176     static final boolean DEBUG_CONFIGURATION = false;
177     static final boolean DEBUG_APP_TRANSITIONS = false;
178     static final boolean DEBUG_STARTING_WINDOW = false;
179     static final boolean DEBUG_REORDER = false;
180     static final boolean DEBUG_WALLPAPER = false;
181     static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
182     static final boolean DEBUG_DRAG = false;
183     static final boolean DEBUG_SCREEN_ON = false;
184     static final boolean DEBUG_SCREENSHOT = false;
185     static final boolean DEBUG_BOOT = false;
186     static final boolean DEBUG_LAYOUT_REPEATS = true;
187     static final boolean DEBUG_SURFACE_TRACE = false;
188     static final boolean DEBUG_WINDOW_TRACE = false;
189     static final boolean DEBUG_TASK_MOVEMENT = false;
190     static final boolean DEBUG_STACK = true;
191     static final boolean SHOW_SURFACE_ALLOC = false;
192     static final boolean SHOW_TRANSACTIONS = false;
193     static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
194     static final boolean HIDE_STACK_CRAWLS = true;
195     static final int LAYOUT_REPEAT_THRESHOLD = 4;
196
197     static final boolean PROFILE_ORIENTATION = false;
198     static final boolean localLOGV = DEBUG;
199
200     /** How much to multiply the policy's type layer, to reserve room
201      * for multiple windows of the same type and Z-ordering adjustment
202      * with TYPE_LAYER_OFFSET. */
203     static final int TYPE_LAYER_MULTIPLIER = 10000;
204
205     /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
206      * or below others in the same layer. */
207     static final int TYPE_LAYER_OFFSET = 1000;
208
209     /** How much to increment the layer for each window, to reserve room
210      * for effect surfaces between them.
211      */
212     static final int WINDOW_LAYER_MULTIPLIER = 5;
213
214     /**
215      * Dim surface layer is immediately below target window.
216      */
217     static final int LAYER_OFFSET_DIM = 1;
218
219     /**
220      * Blur surface layer is immediately below dim layer.
221      */
222     static final int LAYER_OFFSET_BLUR = 2;
223
224     /**
225      * FocusedStackFrame layer is immediately above focused window.
226      */
227     static final int LAYER_OFFSET_FOCUSED_STACK = 1;
228
229     /**
230      * Animation thumbnail is as far as possible below the window above
231      * the thumbnail (or in other words as far as possible above the window
232      * below it).
233      */
234     static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1;
235
236     /**
237      * Layer at which to put the rotation freeze snapshot.
238      */
239     static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1;
240
241     /**
242      * Layer at which to put the mask for emulated screen sizes.
243      */
244     static final int MASK_LAYER = TYPE_LAYER_MULTIPLIER * 200;
245
246     /** The maximum length we will accept for a loaded animation duration:
247      * this is 10 seconds.
248      */
249     static final int MAX_ANIMATION_DURATION = 10*1000;
250
251     /** Amount of time (in milliseconds) to animate the fade-in-out transition for
252      * compatible windows.
253      */
254     static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
255
256     /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
257     static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
258
259     /** Amount of time (in milliseconds) to delay before declaring a starting window leaked. */
260     static final int STARTING_WINDOW_TIMEOUT_DURATION = 10000;
261
262     /**
263      * If true, the window manager will do its own custom freezing and general
264      * management of the screen during rotation.
265      */
266     static final boolean CUSTOM_SCREEN_ROTATION = true;
267
268     // Maximum number of milliseconds to wait for input devices to be enumerated before
269     // proceding with safe mode detection.
270     private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
271
272     // Default input dispatching timeout in nanoseconds.
273     static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
274
275     /** Minimum value for createStack and resizeStack weight value */
276     public static final float STACK_WEIGHT_MIN = 0.2f;
277
278     /** Maximum value for createStack and resizeStack weight value */
279     public static final float STACK_WEIGHT_MAX = 0.8f;
280
281     static final int UPDATE_FOCUS_NORMAL = 0;
282     static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
283     static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
284     static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
285
286     private static final String SYSTEM_SECURE = "ro.secure";
287     private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
288
289     private static final String DENSITY_OVERRIDE = "ro.config.density_override";
290     private static final String SIZE_OVERRIDE = "ro.config.size_override";
291
292     private static final int MAX_SCREENSHOT_RETRIES = 3;
293
294     final private KeyguardDisableHandler mKeyguardDisableHandler;
295
296     private final boolean mHeadless;
297
298     final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
299         @Override
300         public void onReceive(Context context, Intent intent) {
301             final String action = intent.getAction();
302             if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
303                 mKeyguardDisableHandler.sendEmptyMessage(
304                     KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED);
305             }
306         }
307     };
308
309     // Current user when multi-user is enabled. Don't show windows of non-current user.
310     int mCurrentUserId;
311
312     final Context mContext;
313
314     final boolean mHaveInputMethods;
315
316     final boolean mAllowBootMessages;
317
318     final boolean mLimitedAlphaCompositing;
319
320     final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
321
322     final IActivityManager mActivityManager;
323
324     final IBatteryStats mBatteryStats;
325
326     final AppOpsManager mAppOps;
327
328     final DisplaySettings mDisplaySettings;
329
330     /**
331      * All currently active sessions with clients.
332      */
333     final HashSet<Session> mSessions = new HashSet<Session>();
334
335     /**
336      * Mapping from an IWindow IBinder to the server's Window object.
337      * This is also used as the lock for all of our state.
338      * NOTE: Never call into methods that lock ActivityManagerService while holding this object.
339      */
340     final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
341
342     /**
343      * Mapping from a token IBinder to a WindowToken object.
344      */
345     final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>();
346
347     /**
348      * List of window tokens that have finished starting their application,
349      * and now need to have the policy remove their windows.
350      */
351     final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
352
353     /**
354      * Fake windows added to the window manager.  Note: ordered from top to
355      * bottom, opposite of mWindows.
356      */
357     final ArrayList<FakeWindowImpl> mFakeWindows = new ArrayList<FakeWindowImpl>();
358
359     /**
360      * Windows that are being resized.  Used so we can tell the client about
361      * the resize after closing the transaction in which we resized the
362      * underlying surface.
363      */
364     final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
365
366     /**
367      * Windows whose animations have ended and now must be removed.
368      */
369     final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
370
371     /**
372      * Used when processing mPendingRemove to avoid working on the original array.
373      */
374     WindowState[] mPendingRemoveTmp = new WindowState[20];
375
376     /**
377      * Windows whose surface should be destroyed.
378      */
379     final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
380
381     /**
382      * Windows that have lost input focus and are waiting for the new
383      * focus window to be displayed before they are told about this.
384      */
385     ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
386
387     /**
388      * This is set when we have run out of memory, and will either be an empty
389      * list or contain windows that need to be force removed.
390      */
391     ArrayList<WindowState> mForceRemoves;
392
393     /**
394      * Windows that clients are waiting to have drawn.
395      */
396     ArrayList<Pair<WindowState, IRemoteCallback>> mWaitingForDrawn
397             = new ArrayList<Pair<WindowState, IRemoteCallback>>();
398
399     /**
400      * Windows that have called relayout() while we were running animations,
401      * so we need to tell when the animation is done.
402      */
403     final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>();
404
405     /**
406      * Used when rebuilding window list to keep track of windows that have
407      * been removed.
408      */
409     WindowState[] mRebuildTmp = new WindowState[20];
410
411     IInputMethodManager mInputMethodManager;
412
413     DisplayMagnifier mDisplayMagnifier;
414
415     final SurfaceSession mFxSession;
416     Watermark mWatermark;
417     StrictModeFlash mStrictModeFlash;
418     FocusedStackFrame mFocusedStackFrame;
419
420     int mFocusedStackLayer;
421
422     final float[] mTmpFloats = new float[9];
423     final Rect mTmpContentRect = new Rect();
424
425     boolean mDisplayReady;
426     boolean mSafeMode;
427     boolean mDisplayEnabled = false;
428     boolean mSystemBooted = false;
429     boolean mForceDisplayEnabled = false;
430     boolean mShowingBootMessages = false;
431
432     String mLastANRState;
433
434     /** All DisplayContents in the world, kept here */
435     SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(2);
436
437     int mRotation = 0;
438     int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
439     boolean mAltOrientation = false;
440     ArrayList<IRotationWatcher> mRotationWatchers
441             = new ArrayList<IRotationWatcher>();
442     int mDeferredRotationPauseCount;
443
444     int mSystemDecorLayer = 0;
445     final Rect mScreenRect = new Rect();
446
447     boolean mTraversalScheduled = false;
448     boolean mDisplayFrozen = false;
449     long mDisplayFreezeTime = 0;
450     int mLastDisplayFreezeDuration = 0;
451     Object mLastFinishedFreezeSource = null;
452     boolean mWaitingForConfig = false;
453     boolean mWindowsFreezingScreen = false;
454     boolean mClientFreezingScreen = false;
455     int mAppsFreezingScreen = 0;
456     int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
457
458     int mLayoutSeq = 0;
459
460     int mLastStatusBarVisibility = 0;
461
462     // State while inside of layoutAndPlaceSurfacesLocked().
463     boolean mFocusMayChange;
464
465     Configuration mCurConfiguration = new Configuration();
466
467     // This is held as long as we have the screen frozen, to give us time to
468     // perform a rotation animation when turning off shows the lock screen which
469     // changes the orientation.
470     private final PowerManager.WakeLock mScreenFrozenLock;
471
472     final AppTransition mAppTransition;
473     boolean mStartingIconInTransition = false;
474     boolean mSkipAppTransitionAnimation = false;
475
476     final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
477     final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
478
479     boolean mIsTouchDevice;
480
481     final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
482     final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
483     final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
484     final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
485
486     final H mH = new H();
487
488     final Choreographer mChoreographer = Choreographer.getInstance();
489
490     WindowState mCurrentFocus = null;
491     WindowState mLastFocus = null;
492
493     /** This just indicates the window the input method is on top of, not
494      * necessarily the window its input is going to. */
495     WindowState mInputMethodTarget = null;
496
497     /** If true hold off on modifying the animation layer of mInputMethodTarget */
498     boolean mInputMethodTargetWaitingAnim;
499     int mInputMethodAnimLayerAdjustment;
500
501     WindowState mInputMethodWindow = null;
502     final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
503
504     boolean mHardKeyboardAvailable;
505     boolean mHardKeyboardEnabled;
506     OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
507
508     final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
509
510     // If non-null, this is the currently visible window that is associated
511     // with the wallpaper.
512     WindowState mWallpaperTarget = null;
513     // If non-null, we are in the middle of animating from one wallpaper target
514     // to another, and this is the lower one in Z-order.
515     WindowState mLowerWallpaperTarget = null;
516     // If non-null, we are in the middle of animating from one wallpaper target
517     // to another, and this is the higher one in Z-order.
518     WindowState mUpperWallpaperTarget = null;
519     int mWallpaperAnimLayerAdjustment;
520     float mLastWallpaperX = -1;
521     float mLastWallpaperY = -1;
522     float mLastWallpaperXStep = -1;
523     float mLastWallpaperYStep = -1;
524     // This is set when we are waiting for a wallpaper to tell us it is done
525     // changing its scroll position.
526     WindowState mWaitingOnWallpaper;
527     // The last time we had a timeout when waiting for a wallpaper.
528     long mLastWallpaperTimeoutTime;
529     // We give a wallpaper up to 150ms to finish scrolling.
530     static final long WALLPAPER_TIMEOUT = 150;
531     // Time we wait after a timeout before trying to wait again.
532     static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
533
534     AppWindowToken mFocusedApp = null;
535
536     PowerManagerService mPowerManager;
537
538     float mWindowAnimationScale = 1.0f;
539     float mTransitionAnimationScale = 1.0f;
540     float mAnimatorDurationScale = 1.0f;
541
542     final InputManagerService mInputManager;
543     final DisplayManagerService mDisplayManagerService;
544     final DisplayManager mDisplayManager;
545
546     // Who is holding the screen on.
547     Session mHoldingScreenOn;
548     PowerManager.WakeLock mHoldingScreenWakeLock;
549
550     boolean mTurnOnScreen;
551
552     DragState mDragState = null;
553
554     // For frozen screen animations.
555     int mExitAnimId, mEnterAnimId;
556
557     /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple
558      * methods. */
559     class LayoutFields {
560         static final int SET_UPDATE_ROTATION                = 1 << 0;
561         static final int SET_WALLPAPER_MAY_CHANGE           = 1 << 1;
562         static final int SET_FORCE_HIDING_CHANGED           = 1 << 2;
563         static final int SET_ORIENTATION_CHANGE_COMPLETE    = 1 << 3;
564         static final int SET_TURN_ON_SCREEN                 = 1 << 4;
565         static final int SET_WALLPAPER_ACTION_PENDING       = 1 << 5;
566
567         boolean mWallpaperForceHidingChanged = false;
568         boolean mWallpaperMayChange = false;
569         boolean mOrientationChangeComplete = true;
570         Object mLastWindowFreezeSource = null;
571         private Session mHoldScreen = null;
572         private boolean mObscured = false;
573         private boolean mSyswin = false;
574         private float mScreenBrightness = -1;
575         private float mButtonBrightness = -1;
576         private long mUserActivityTimeout = -1;
577         private boolean mUpdateRotation = false;
578         boolean mWallpaperActionPending = false;
579
580         private static final int DISPLAY_CONTENT_UNKNOWN = 0;
581         private static final int DISPLAY_CONTENT_MIRROR = 1;
582         private static final int DISPLAY_CONTENT_UNIQUE = 2;
583         private int mDisplayHasContent = DISPLAY_CONTENT_UNKNOWN;
584     }
585     final LayoutFields mInnerFields = new LayoutFields();
586
587     boolean mAnimationScheduled;
588
589     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
590      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
591     private int mTransactionSequence;
592
593     /** Only do a maximum of 6 repeated layouts. After that quit */
594     private int mLayoutRepeatCount;
595
596     final WindowAnimator mAnimator;
597
598     SparseArray<Task> mTaskIdToTask = new SparseArray<Task>();
599     SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>();
600
601     private final PointerEventDispatcher mPointerEventDispatcher;
602
603     final class DragInputEventReceiver extends InputEventReceiver {
604         public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
605             super(inputChannel, looper);
606         }
607
608         @Override
609         public void onInputEvent(InputEvent event) {
610             boolean handled = false;
611             try {
612                 if (event instanceof MotionEvent
613                         && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
614                         && mDragState != null) {
615                     final MotionEvent motionEvent = (MotionEvent)event;
616                     boolean endDrag = false;
617                     final float newX = motionEvent.getRawX();
618                     final float newY = motionEvent.getRawY();
619
620                     switch (motionEvent.getAction()) {
621                     case MotionEvent.ACTION_DOWN: {
622                         if (DEBUG_DRAG) {
623                             Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer");
624                         }
625                     } break;
626
627                     case MotionEvent.ACTION_MOVE: {
628                         synchronized (mWindowMap) {
629                             // move the surface and tell the involved window(s) where we are
630                             mDragState.notifyMoveLw(newX, newY);
631                         }
632                     } break;
633
634                     case MotionEvent.ACTION_UP: {
635                         if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at "
636                                 + newX + "," + newY);
637                         synchronized (mWindowMap) {
638                             endDrag = mDragState.notifyDropLw(newX, newY);
639                         }
640                     } break;
641
642                     case MotionEvent.ACTION_CANCEL: {
643                         if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!");
644                         endDrag = true;
645                     } break;
646                     }
647
648                     if (endDrag) {
649                         if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state");
650                         // tell all the windows that the drag has ended
651                         synchronized (mWindowMap) {
652                             mDragState.endDragLw();
653                         }
654                     }
655
656                     handled = true;
657                 }
658             } catch (Exception e) {
659                 Slog.e(TAG, "Exception caught by drag handleMotion", e);
660             } finally {
661                 finishInputEvent(event, handled);
662             }
663         }
664     }
665
666     /**
667      * Whether the UI is currently running in touch mode (not showing
668      * navigational focus because the user is directly pressing the screen).
669      */
670     boolean mInTouchMode = true;
671
672     private ViewServer mViewServer;
673     private final ArrayList<WindowChangeListener> mWindowChangeListeners =
674         new ArrayList<WindowChangeListener>();
675     private boolean mWindowsChanged = false;
676
677     public interface WindowChangeListener {
678         public void windowsChanged();
679         public void focusChanged();
680     }
681
682     final Configuration mTempConfiguration = new Configuration();
683
684     // The desired scaling factor for compatible apps.
685     float mCompatibleScreenScale;
686
687     // If true, only the core apps and services are being launched because the device
688     // is in a special boot mode, such as being encrypted or waiting for a decryption password.
689     // For example, when this flag is true, there will be no wallpaper service.
690     final boolean mOnlyCore;
691
692     public static WindowManagerService main(final Context context,
693             final PowerManagerService pm, final DisplayManagerService dm,
694             final InputManagerService im, final Handler wmHandler,
695             final boolean haveInputMethods, final boolean showBootMsgs,
696             final boolean onlyCore) {
697         final WindowManagerService[] holder = new WindowManagerService[1];
698         wmHandler.runWithScissors(new Runnable() {
699             @Override
700             public void run() {
701                 holder[0] = new WindowManagerService(context, pm, dm, im,
702                         haveInputMethods, showBootMsgs, onlyCore);
703             }
704         }, 0);
705         return holder[0];
706     }
707
708     private void initPolicy(Handler uiHandler) {
709         uiHandler.runWithScissors(new Runnable() {
710             @Override
711             public void run() {
712                 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
713
714                 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
715                 mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer()
716                         * TYPE_LAYER_MULTIPLIER
717                         + TYPE_LAYER_OFFSET;
718             }
719         }, 0);
720     }
721
722     private WindowManagerService(Context context, PowerManagerService pm,
723             DisplayManagerService displayManager, InputManagerService inputManager,
724             boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
725         mContext = context;
726         mHaveInputMethods = haveInputMethods;
727         mAllowBootMessages = showBootMsgs;
728         mOnlyCore = onlyCore;
729         mLimitedAlphaCompositing = context.getResources().getBoolean(
730                 com.android.internal.R.bool.config_sf_limitedAlpha);
731         mInputManager = inputManager; // Must be before createDisplayContentLocked.
732         mDisplayManagerService = displayManager;
733         mHeadless = displayManager.isHeadless();
734         mDisplaySettings = new DisplaySettings(context);
735         mDisplaySettings.readSettingsLocked();
736
737         mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG));
738
739         mFxSession = new SurfaceSession();
740         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
741         mDisplayManager.registerDisplayListener(this, null);
742         Display[] displays = mDisplayManager.getDisplays();
743         for (Display display : displays) {
744             createDisplayContentLocked(display);
745         }
746
747         mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
748
749         mPowerManager = pm;
750         mPowerManager.setPolicy(mPolicy);
751         PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
752         mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
753         mScreenFrozenLock.setReferenceCounted(false);
754
755         mAppTransition = new AppTransition(context, mH);
756
757         mActivityManager = ActivityManagerNative.getDefault();
758         mBatteryStats = BatteryStatsService.getService();
759         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
760         mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null,
761                 new AppOpsManager.OnOpChangedInternalListener() {
762                     @Override
763                     public void onOpChanged(int op, String packageName) {
764                         updateAppOpsState();
765                     }
766                 }
767         );
768
769         // Get persisted window scale setting
770         mWindowAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
771                 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
772         mTransitionAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
773                 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
774         setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
775                 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale));
776
777         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
778         IntentFilter filter = new IntentFilter();
779         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
780         mContext.registerReceiver(mBroadcastReceiver, filter);
781
782         mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
783                 | PowerManager.ON_AFTER_RELEASE, TAG);
784         mHoldingScreenWakeLock.setReferenceCounted(false);
785
786         mAnimator = new WindowAnimator(this);
787
788         initPolicy(UiThread.getHandler());
789
790         // Add ourself to the Watchdog monitors.
791         Watchdog.getInstance().addMonitor(this);
792
793         SurfaceControl.openTransaction();
794         try {
795             createWatermarkInTransaction();
796             mFocusedStackFrame = new FocusedStackFrame(
797                     getDefaultDisplayContentLocked().getDisplay(), mFxSession);
798         } finally {
799             SurfaceControl.closeTransaction();
800         }
801     }
802
803     public InputMonitor getInputMonitor() {
804         return mInputMonitor;
805     }
806
807     @Override
808     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
809             throws RemoteException {
810         try {
811             return super.onTransact(code, data, reply, flags);
812         } catch (RuntimeException e) {
813             // The window manager only throws security exceptions, so let's
814             // log all others.
815             if (!(e instanceof SecurityException)) {
816                 Slog.wtf(TAG, "Window Manager Crash", e);
817             }
818             throw e;
819         }
820     }
821
822     private void placeWindowAfter(WindowState pos, WindowState window) {
823         final WindowList windows = pos.getWindowList();
824         final int i = windows.indexOf(pos);
825         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
826             TAG, "Adding window " + window + " at "
827             + (i+1) + " of " + windows.size() + " (after " + pos + ")");
828         windows.add(i+1, window);
829         mWindowsChanged = true;
830     }
831
832     private void placeWindowBefore(WindowState pos, WindowState window) {
833         final WindowList windows = pos.getWindowList();
834         int i = windows.indexOf(pos);
835         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
836             TAG, "Adding window " + window + " at "
837             + i + " of " + windows.size() + " (before " + pos + ")");
838         if (i < 0) {
839             Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows);
840             i = 0;
841         }
842         windows.add(i, window);
843         mWindowsChanged = true;
844     }
845
846     //This method finds out the index of a window that has the same app token as
847     //win. used for z ordering the windows in mWindows
848     private int findIdxBasedOnAppTokens(WindowState win) {
849         WindowList windows = win.getWindowList();
850         for(int j = windows.size() - 1; j >= 0; j--) {
851             WindowState wentry = windows.get(j);
852             if(wentry.mAppToken == win.mAppToken) {
853                 return j;
854             }
855         }
856         return -1;
857     }
858
859     /**
860      * Return the list of Windows from the passed token on the given Display.
861      * @param token The token with all the windows.
862      * @param displayContent The display we are interested in.
863      * @return List of windows from token that are on displayContent.
864      */
865     WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) {
866         final WindowList windowList = new WindowList();
867         final int count = token.windows.size();
868         for (int i = 0; i < count; i++) {
869             final WindowState win = token.windows.get(i);
870             if (win.mDisplayContent == displayContent) {
871                 windowList.add(win);
872             }
873         }
874         return windowList;
875     }
876
877     /**
878      * Recursive search through a WindowList and all of its windows' children.
879      * @param targetWin The window to search for.
880      * @param windows The list to search.
881      * @return The index of win in windows or of the window that is an ancestor of win.
882      */
883     private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) {
884         for (int i = windows.size() - 1; i >= 0; i--) {
885             final WindowState w = windows.get(i);
886             if (w == targetWin) {
887                 return i;
888             }
889             if (!w.mChildWindows.isEmpty()) {
890                 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) {
891                     return i;
892                 }
893             }
894         }
895         return -1;
896     }
897
898     private int addAppWindowToListLocked(final WindowState win) {
899         final IWindow client = win.mClient;
900         final WindowToken token = win.mToken;
901         final DisplayContent displayContent = win.mDisplayContent;
902
903         final WindowList windows = win.getWindowList();
904         final int N = windows.size();
905         WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
906         int tokenWindowsPos = 0;
907         int windowListPos = tokenWindowList.size();
908         if (!tokenWindowList.isEmpty()) {
909             // If this application has existing windows, we
910             // simply place the new window on top of them... but
911             // keep the starting window on top.
912             if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
913                 // Base windows go behind everything else.
914                 WindowState lowestWindow = tokenWindowList.get(0);
915                 placeWindowBefore(lowestWindow, win);
916                 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows);
917             } else {
918                 AppWindowToken atoken = win.mAppToken;
919                 WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
920                 if (atoken != null && lastWindow == atoken.startingWindow) {
921                     placeWindowBefore(lastWindow, win);
922                     tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows);
923                 } else {
924                     int newIdx = findIdxBasedOnAppTokens(win);
925                     //there is a window above this one associated with the same
926                     //apptoken note that the window could be a floating window
927                     //that was created later or a window at the top of the list of
928                     //windows associated with this token.
929                     if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
930                             "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " +
931                             N);
932                     windows.add(newIdx + 1, win);
933                     if (newIdx < 0) {
934                         // No window from token found on win's display.
935                         tokenWindowsPos = 0;
936                     } else {
937                         tokenWindowsPos = indexOfWinInWindowList(
938                                 windows.get(newIdx), token.windows) + 1;
939                     }
940                     mWindowsChanged = true;
941                 }
942             }
943             return tokenWindowsPos;
944         }
945
946         // No windows from this token on this display
947         if (localLOGV) Slog.v(TAG, "Figuring out where to add app window " + client.asBinder()
948                 + " (token=" + token + ")");
949         // Figure out where the window should go, based on the
950         // order of applications.
951         WindowState pos = null;
952
953         final ArrayList<Task> tasks = displayContent.getTasks();
954         int taskNdx;
955         int tokenNdx = -1;
956         for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
957             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
958             for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
959                 final AppWindowToken t = tokens.get(tokenNdx);
960                 if (t == token) {
961                     --tokenNdx;
962                     if (tokenNdx < 0) {
963                         --taskNdx;
964                         if (taskNdx >= 0) {
965                             tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1;
966                         }
967                     }
968                     break;
969                 }
970
971                 // We haven't reached the token yet; if this token
972                 // is not going to the bottom and has windows on this display, we can
973                 // use it as an anchor for when we do reach the token.
974                 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
975                 if (!t.sendingToBottom && tokenWindowList.size() > 0) {
976                     pos = tokenWindowList.get(0);
977                 }
978             }
979             if (tokenNdx >= 0) {
980                 // early exit
981                 break;
982             }
983         }
984
985         // We now know the index into the apps.  If we found
986         // an app window above, that gives us the position; else
987         // we need to look some more.
988         if (pos != null) {
989             // Move behind any windows attached to this one.
990             WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
991             if (atoken != null) {
992                 tokenWindowList =
993                         getTokenWindowsOnDisplay(atoken, displayContent);
994                 final int NC = tokenWindowList.size();
995                 if (NC > 0) {
996                     WindowState bottom = tokenWindowList.get(0);
997                     if (bottom.mSubLayer < 0) {
998                         pos = bottom;
999                     }
1000                 }
1001             }
1002             placeWindowBefore(pos, win);
1003             return tokenWindowsPos;
1004         }
1005
1006         // Continue looking down until we find the first
1007         // token that has windows on this display.
1008         for ( ; taskNdx >= 0; --taskNdx) {
1009             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
1010             for ( ; tokenNdx >= 0; --tokenNdx) {
1011                 final AppWindowToken t = tokens.get(tokenNdx);
1012                 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
1013                 final int NW = tokenWindowList.size();
1014                 if (NW > 0) {
1015                     pos = tokenWindowList.get(NW-1);
1016                     break;
1017                 }
1018             }
1019             if (tokenNdx >= 0) {
1020                 // found
1021                 break;
1022             }
1023         }
1024
1025         if (pos != null) {
1026             // Move in front of any windows attached to this
1027             // one.
1028             WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
1029             if (atoken != null) {
1030                 final int NC = atoken.windows.size();
1031                 if (NC > 0) {
1032                     WindowState top = atoken.windows.get(NC-1);
1033                     if (top.mSubLayer >= 0) {
1034                         pos = top;
1035                     }
1036                 }
1037             }
1038             placeWindowAfter(pos, win);
1039             return tokenWindowsPos;
1040         }
1041
1042         // Just search for the start of this layer.
1043         final int myLayer = win.mBaseLayer;
1044         int i;
1045         for (i = 0; i < N; i++) {
1046             WindowState w = windows.get(i);
1047             if (w.mBaseLayer > myLayer) {
1048                 break;
1049             }
1050         }
1051         if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
1052                 "Based on layer: Adding window " + win + " at " + i + " of " + N);
1053         windows.add(i, win);
1054         mWindowsChanged = true;
1055         return tokenWindowsPos;
1056     }
1057
1058     private void addFreeWindowToListLocked(final WindowState win) {
1059         final WindowList windows = win.getWindowList();
1060
1061         // Figure out where window should go, based on layer.
1062         final int myLayer = win.mBaseLayer;
1063         int i;
1064         for (i = windows.size() - 1; i >= 0; i--) {
1065             if (windows.get(i).mBaseLayer <= myLayer) {
1066                 break;
1067             }
1068         }
1069         i++;
1070         if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
1071                 "Free window: Adding window " + win + " at " + i + " of " + windows.size());
1072         windows.add(i, win);
1073         mWindowsChanged = true;
1074     }
1075
1076     private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) {
1077         final WindowToken token = win.mToken;
1078         final DisplayContent displayContent = win.mDisplayContent;
1079         final WindowState attached = win.mAttachedWindow;
1080
1081         WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
1082
1083         // Figure out this window's ordering relative to the window
1084         // it is attached to.
1085         final int NA = tokenWindowList.size();
1086         final int sublayer = win.mSubLayer;
1087         int largestSublayer = Integer.MIN_VALUE;
1088         WindowState windowWithLargestSublayer = null;
1089         int i;
1090         for (i = 0; i < NA; i++) {
1091             WindowState w = tokenWindowList.get(i);
1092             final int wSublayer = w.mSubLayer;
1093             if (wSublayer >= largestSublayer) {
1094                 largestSublayer = wSublayer;
1095                 windowWithLargestSublayer = w;
1096             }
1097             if (sublayer < 0) {
1098                 // For negative sublayers, we go below all windows
1099                 // in the same sublayer.
1100                 if (wSublayer >= sublayer) {
1101                     if (addToToken) {
1102                         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1103                         token.windows.add(i, win);
1104                     }
1105                     placeWindowBefore(wSublayer >= 0 ? attached : w, win);
1106                     break;
1107                 }
1108             } else {
1109                 // For positive sublayers, we go above all windows
1110                 // in the same sublayer.
1111                 if (wSublayer > sublayer) {
1112                     if (addToToken) {
1113                         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1114                         token.windows.add(i, win);
1115                     }
1116                     placeWindowBefore(w, win);
1117                     break;
1118                 }
1119             }
1120         }
1121         if (i >= NA) {
1122             if (addToToken) {
1123                 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1124                 token.windows.add(win);
1125             }
1126             if (sublayer < 0) {
1127                 placeWindowBefore(attached, win);
1128             } else {
1129                 placeWindowAfter(largestSublayer >= 0
1130                                  ? windowWithLargestSublayer
1131                                  : attached,
1132                                  win);
1133             }
1134         }
1135     }
1136
1137     private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) {
1138         if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win +
1139                 " Callers=" + Debug.getCallers(4));
1140         if (win.mAttachedWindow == null) {
1141             final WindowToken token = win.mToken;
1142             int tokenWindowsPos = 0;
1143             if (token.appWindowToken != null) {
1144                 tokenWindowsPos = addAppWindowToListLocked(win);
1145             } else {
1146                 addFreeWindowToListLocked(win);
1147             }
1148             if (addToToken) {
1149                 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1150                 token.windows.add(tokenWindowsPos, win);
1151             }
1152         } else {
1153             addAttachedWindowToListLocked(win, addToToken);
1154         }
1155
1156         if (win.mAppToken != null && addToToken) {
1157             win.mAppToken.allAppWindows.add(win);
1158         }
1159     }
1160
1161     static boolean canBeImeTarget(WindowState w) {
1162         final int fl = w.mAttrs.flags
1163                 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
1164         if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)
1165                 || w.mAttrs.type == TYPE_APPLICATION_STARTING) {
1166             if (DEBUG_INPUT_METHOD) {
1167                 Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
1168                 if (!w.isVisibleOrAdding()) {
1169                     Slog.i(TAG, "  mSurface=" + w.mWinAnimator.mSurfaceControl
1170                             + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility
1171                             + " policyVis=" + w.mPolicyVisibility
1172                             + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
1173                             + " attachHid=" + w.mAttachedHidden
1174                             + " exiting=" + w.mExiting + " destroying=" + w.mDestroying);
1175                     if (w.mAppToken != null) {
1176                         Slog.i(TAG, "  mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
1177                     }
1178                 }
1179             }
1180             return w.isVisibleOrAdding();
1181         }
1182         return false;
1183     }
1184
1185     /**
1186      * Dig through the WindowStates and find the one that the Input Method will target.
1187      * @param willMove
1188      * @return The index+1 in mWindows of the discovered target.
1189      */
1190     int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
1191         // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
1192         // same display. Or even when the current IME/target are not on the same screen as the next
1193         // IME/target. For now only look for input windows on the main screen.
1194         WindowList windows = getDefaultWindowListLocked();
1195         WindowState w = null;
1196         int i;
1197         for (i = windows.size() - 1; i >= 0; --i) {
1198             WindowState win = windows.get(i);
1199
1200             if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i
1201                     + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
1202             if (canBeImeTarget(win)) {
1203                 w = win;
1204                 //Slog.i(TAG, "Putting input method here!");
1205
1206                 // Yet more tricksyness!  If this window is a "starting"
1207                 // window, we do actually want to be on top of it, but
1208                 // it is not -really- where input will go.  So if the caller
1209                 // is not actually looking to move the IME, look down below
1210                 // for a real window to target...
1211                 if (!willMove
1212                         && w.mAttrs.type == TYPE_APPLICATION_STARTING
1213                         && i > 0) {
1214                     WindowState wb = windows.get(i-1);
1215                     if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
1216                         i--;
1217                         w = wb;
1218                     }
1219                 }
1220                 break;
1221             }
1222         }
1223
1224         // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
1225
1226         if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w);
1227
1228         // Now, a special case -- if the last target's window is in the
1229         // process of exiting, and is above the new target, keep on the
1230         // last target to avoid flicker.  Consider for example a Dialog with
1231         // the IME shown: when the Dialog is dismissed, we want to keep
1232         // the IME above it until it is completely gone so it doesn't drop
1233         // behind the dialog or its full-screen scrim.
1234         final WindowState curTarget = mInputMethodTarget;
1235         if (curTarget != null
1236                 && curTarget.isDisplayedLw()
1237                 && curTarget.isClosing()
1238                 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
1239             if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing");
1240             return windows.indexOf(curTarget) + 1;
1241         }
1242
1243         if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
1244                 + w + " willMove=" + willMove);
1245
1246         if (willMove && w != null) {
1247             AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
1248             if (token != null) {
1249
1250                 // Now some fun for dealing with window animations that
1251                 // modify the Z order.  We need to look at all windows below
1252                 // the current target that are in this app, finding the highest
1253                 // visible one in layering.
1254                 WindowState highestTarget = null;
1255                 int highestPos = 0;
1256                 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
1257                     WindowList curWindows = curTarget.getWindowList();
1258                     int pos = curWindows.indexOf(curTarget);
1259                     while (pos >= 0) {
1260                         WindowState win = curWindows.get(pos);
1261                         if (win.mAppToken != token) {
1262                             break;
1263                         }
1264                         if (!win.mRemoved) {
1265                             if (highestTarget == null || win.mWinAnimator.mAnimLayer >
1266                                     highestTarget.mWinAnimator.mAnimLayer) {
1267                                 highestTarget = win;
1268                                 highestPos = pos;
1269                             }
1270                         }
1271                         pos--;
1272                     }
1273                 }
1274
1275                 if (highestTarget != null) {
1276                     if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget
1277                             + " animating=" + highestTarget.mWinAnimator.isAnimating()
1278                             + " layer=" + highestTarget.mWinAnimator.mAnimLayer
1279                             + " new layer=" + w.mWinAnimator.mAnimLayer);
1280
1281                     if (mAppTransition.isTransitionSet()) {
1282                         // If we are currently setting up for an animation,
1283                         // hold everything until we can find out what will happen.
1284                         mInputMethodTargetWaitingAnim = true;
1285                         mInputMethodTarget = highestTarget;
1286                         return highestPos + 1;
1287                     } else if (highestTarget.mWinAnimator.isAnimating() &&
1288                             highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
1289                         // If the window we are currently targeting is involved
1290                         // with an animation, and it is on top of the next target
1291                         // we will be over, then hold off on moving until
1292                         // that is done.
1293                         mInputMethodTargetWaitingAnim = true;
1294                         mInputMethodTarget = highestTarget;
1295                         return highestPos + 1;
1296                     }
1297                 }
1298             }
1299         }
1300
1301         //Slog.i(TAG, "Placing input method @" + (i+1));
1302         if (w != null) {
1303             if (willMove) {
1304                 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to "
1305                         + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
1306                 mInputMethodTarget = w;
1307                 mInputMethodTargetWaitingAnim = false;
1308                 if (w.mAppToken != null) {
1309                     setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment);
1310                 } else {
1311                     setInputMethodAnimLayerAdjustment(0);
1312                 }
1313             }
1314             return i+1;
1315         }
1316         if (willMove) {
1317             if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null."
1318                     + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
1319             mInputMethodTarget = null;
1320             setInputMethodAnimLayerAdjustment(0);
1321         }
1322         return -1;
1323     }
1324
1325     void addInputMethodWindowToListLocked(WindowState win) {
1326         int pos = findDesiredInputMethodWindowIndexLocked(true);
1327         if (pos >= 0) {
1328             win.mTargetAppToken = mInputMethodTarget.mAppToken;
1329             if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
1330                     TAG, "Adding input method window " + win + " at " + pos);
1331             // TODO(multidisplay): IMEs are only supported on the default display.
1332             getDefaultWindowListLocked().add(pos, win);
1333             mWindowsChanged = true;
1334             moveInputMethodDialogsLocked(pos+1);
1335             return;
1336         }
1337         win.mTargetAppToken = null;
1338         addWindowToListInOrderLocked(win, true);
1339         moveInputMethodDialogsLocked(pos);
1340     }
1341
1342     void setInputMethodAnimLayerAdjustment(int adj) {
1343         if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj);
1344         mInputMethodAnimLayerAdjustment = adj;
1345         WindowState imw = mInputMethodWindow;
1346         if (imw != null) {
1347             imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
1348             if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
1349                     + " anim layer: " + imw.mWinAnimator.mAnimLayer);
1350             int wi = imw.mChildWindows.size();
1351             while (wi > 0) {
1352                 wi--;
1353                 WindowState cw = imw.mChildWindows.get(wi);
1354                 cw.mWinAnimator.mAnimLayer = cw.mLayer + adj;
1355                 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw
1356                         + " anim layer: " + cw.mWinAnimator.mAnimLayer);
1357             }
1358         }
1359         int di = mInputMethodDialogs.size();
1360         while (di > 0) {
1361             di --;
1362             imw = mInputMethodDialogs.get(di);
1363             imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
1364             if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
1365                     + " anim layer: " + imw.mWinAnimator.mAnimLayer);
1366         }
1367     }
1368
1369     private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1370         WindowList windows = win.getWindowList();
1371         int wpos = windows.indexOf(win);
1372         if (wpos >= 0) {
1373             if (wpos < interestingPos) interestingPos--;
1374             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
1375             windows.remove(wpos);
1376             mWindowsChanged = true;
1377             int NC = win.mChildWindows.size();
1378             while (NC > 0) {
1379                 NC--;
1380                 WindowState cw = win.mChildWindows.get(NC);
1381                 int cpos = windows.indexOf(cw);
1382                 if (cpos >= 0) {
1383                     if (cpos < interestingPos) interestingPos--;
1384                     if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
1385                             + cpos + ": " + cw);
1386                     windows.remove(cpos);
1387                 }
1388             }
1389         }
1390         return interestingPos;
1391     }
1392
1393     private void reAddWindowToListInOrderLocked(WindowState win) {
1394         addWindowToListInOrderLocked(win, false);
1395         // This is a hack to get all of the child windows added as well
1396         // at the right position.  Child windows should be rare and
1397         // this case should be rare, so it shouldn't be that big a deal.
1398         WindowList windows = win.getWindowList();
1399         int wpos = windows.indexOf(win);
1400         if (wpos >= 0) {
1401             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win);
1402             windows.remove(wpos);
1403             mWindowsChanged = true;
1404             reAddWindowLocked(wpos, win);
1405         }
1406     }
1407
1408     void logWindowList(final WindowList windows, String prefix) {
1409         int N = windows.size();
1410         while (N > 0) {
1411             N--;
1412             Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N));
1413         }
1414     }
1415
1416     void moveInputMethodDialogsLocked(int pos) {
1417         ArrayList<WindowState> dialogs = mInputMethodDialogs;
1418
1419         // TODO(multidisplay): IMEs are only supported on the default display.
1420         WindowList windows = getDefaultWindowListLocked();
1421         final int N = dialogs.size();
1422         if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
1423         for (int i=0; i<N; i++) {
1424             pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1425         }
1426         if (DEBUG_INPUT_METHOD) {
1427             Slog.v(TAG, "Window list w/pos=" + pos);
1428             logWindowList(windows, "  ");
1429         }
1430
1431         if (pos >= 0) {
1432             final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1433             if (pos < windows.size()) {
1434                 WindowState wp = windows.get(pos);
1435                 if (wp == mInputMethodWindow) {
1436                     pos++;
1437                 }
1438             }
1439             if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
1440             for (int i=0; i<N; i++) {
1441                 WindowState win = dialogs.get(i);
1442                 win.mTargetAppToken = targetAppToken;
1443                 pos = reAddWindowLocked(pos, win);
1444             }
1445             if (DEBUG_INPUT_METHOD) {
1446                 Slog.v(TAG, "Final window list:");
1447                 logWindowList(windows, "  ");
1448             }
1449             return;
1450         }
1451         for (int i=0; i<N; i++) {
1452             WindowState win = dialogs.get(i);
1453             win.mTargetAppToken = null;
1454             reAddWindowToListInOrderLocked(win);
1455             if (DEBUG_INPUT_METHOD) {
1456                 Slog.v(TAG, "No IM target, final list:");
1457                 logWindowList(windows, "  ");
1458             }
1459         }
1460     }
1461
1462     boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1463         final WindowState imWin = mInputMethodWindow;
1464         final int DN = mInputMethodDialogs.size();
1465         if (imWin == null && DN == 0) {
1466             return false;
1467         }
1468
1469         // TODO(multidisplay): IMEs are only supported on the default display.
1470         WindowList windows = getDefaultWindowListLocked();
1471
1472         int imPos = findDesiredInputMethodWindowIndexLocked(true);
1473         if (imPos >= 0) {
1474             // In this case, the input method windows are to be placed
1475             // immediately above the window they are targeting.
1476
1477             // First check to see if the input method windows are already
1478             // located here, and contiguous.
1479             final int N = windows.size();
1480             WindowState firstImWin = imPos < N
1481                     ? windows.get(imPos) : null;
1482
1483             // Figure out the actual input method window that should be
1484             // at the bottom of their stack.
1485             WindowState baseImWin = imWin != null
1486                     ? imWin : mInputMethodDialogs.get(0);
1487             if (baseImWin.mChildWindows.size() > 0) {
1488                 WindowState cw = baseImWin.mChildWindows.get(0);
1489                 if (cw.mSubLayer < 0) baseImWin = cw;
1490             }
1491
1492             if (firstImWin == baseImWin) {
1493                 // The windows haven't moved...  but are they still contiguous?
1494                 // First find the top IM window.
1495                 int pos = imPos+1;
1496                 while (pos < N) {
1497                     if (!(windows.get(pos)).mIsImWindow) {
1498                         break;
1499                     }
1500                     pos++;
1501                 }
1502                 pos++;
1503                 // Now there should be no more input method windows above.
1504                 while (pos < N) {
1505                     if ((windows.get(pos)).mIsImWindow) {
1506                         break;
1507                     }
1508                     pos++;
1509                 }
1510                 if (pos >= N) {
1511                     // Z order is good.
1512                     // The IM target window may be changed, so update the mTargetAppToken.
1513                     if (imWin != null) {
1514                         imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1515                     }
1516                     return false;
1517                 }
1518             }
1519
1520             if (imWin != null) {
1521                 if (DEBUG_INPUT_METHOD) {
1522                     Slog.v(TAG, "Moving IM from " + imPos);
1523                     logWindowList(windows, "  ");
1524                 }
1525                 imPos = tmpRemoveWindowLocked(imPos, imWin);
1526                 if (DEBUG_INPUT_METHOD) {
1527                     Slog.v(TAG, "List after removing with new pos " + imPos + ":");
1528                     logWindowList(windows, "  ");
1529                 }
1530                 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1531                 reAddWindowLocked(imPos, imWin);
1532                 if (DEBUG_INPUT_METHOD) {
1533                     Slog.v(TAG, "List after moving IM to " + imPos + ":");
1534                     logWindowList(windows, "  ");
1535                 }
1536                 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1537             } else {
1538                 moveInputMethodDialogsLocked(imPos);
1539             }
1540
1541         } else {
1542             // In this case, the input method windows go in a fixed layer,
1543             // because they aren't currently associated with a focus window.
1544
1545             if (imWin != null) {
1546                 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos);
1547                 tmpRemoveWindowLocked(0, imWin);
1548                 imWin.mTargetAppToken = null;
1549                 reAddWindowToListInOrderLocked(imWin);
1550                 if (DEBUG_INPUT_METHOD) {
1551                     Slog.v(TAG, "List with no IM target:");
1552                     logWindowList(windows, "  ");
1553                 }
1554                 if (DN > 0) moveInputMethodDialogsLocked(-1);
1555             } else {
1556                 moveInputMethodDialogsLocked(-1);
1557             }
1558
1559         }
1560
1561         if (needAssignLayers) {
1562             assignLayersLocked(windows);
1563         }
1564
1565         return true;
1566     }
1567
1568     final boolean isWallpaperVisible(WindowState wallpaperTarget) {
1569         if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
1570                 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
1571                 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
1572                         ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
1573                 + " upper=" + mUpperWallpaperTarget
1574                 + " lower=" + mLowerWallpaperTarget);
1575         return (wallpaperTarget != null
1576                         && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
1577                                 && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
1578                 || mUpperWallpaperTarget != null
1579                 || mLowerWallpaperTarget != null;
1580     }
1581
1582     static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
1583     static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
1584
1585     int adjustWallpaperWindowsLocked() {
1586         mInnerFields.mWallpaperMayChange = false;
1587         boolean targetChanged = false;
1588
1589         // TODO(multidisplay): Wallpapers on main screen only.
1590         final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo();
1591         final int dw = displayInfo.logicalWidth;
1592         final int dh = displayInfo.logicalHeight;
1593
1594         // First find top-most window that has asked to be on top of the
1595         // wallpaper; all wallpapers go behind it.
1596         final WindowList windows = getDefaultWindowListLocked();
1597         int N = windows.size();
1598         WindowState w = null;
1599         WindowState foundW = null;
1600         int foundI = 0;
1601         WindowState topCurW = null;
1602         int topCurI = 0;
1603         int windowDetachedI = -1;
1604         int i = N;
1605         while (i > 0) {
1606             i--;
1607             w = windows.get(i);
1608             if ((w.mAttrs.type == TYPE_WALLPAPER)) {
1609                 if (topCurW == null) {
1610                     topCurW = w;
1611                     topCurI = i;
1612                 }
1613                 continue;
1614             }
1615             topCurW = null;
1616             if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
1617                 // If this window's app token is hidden and not animating,
1618                 // it is of no interest to us.
1619                 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
1620                     if (DEBUG_WALLPAPER) Slog.v(TAG,
1621                             "Skipping hidden and not animating token: " + w);
1622                     continue;
1623                 }
1624             }
1625             if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
1626                     + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
1627             if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isOnScreen()
1628                     && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
1629                 if (DEBUG_WALLPAPER) Slog.v(TAG,
1630                         "Found wallpaper target: #" + i + "=" + w);
1631                 foundW = w;
1632                 foundI = i;
1633                 if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) {
1634                     // The current wallpaper target is animating, so we'll
1635                     // look behind it for another possible target and figure
1636                     // out what is going on below.
1637                     if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
1638                             + ": token animating, looking behind.");
1639                     continue;
1640                 }
1641                 break;
1642             } else if (w == mAnimator.mWindowDetachedWallpaper) {
1643                 windowDetachedI = i;
1644             }
1645         }
1646
1647         if (foundW == null && windowDetachedI >= 0) {
1648             if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
1649                     "Found animating detached wallpaper activity: #" + i + "=" + w);
1650             foundW = w;
1651             foundI = windowDetachedI;
1652         }
1653
1654         if (mWallpaperTarget != foundW
1655                 && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) {
1656             if (DEBUG_WALLPAPER_LIGHT) {
1657                 Slog.v(TAG, "New wallpaper target: " + foundW
1658                         + " oldTarget: " + mWallpaperTarget);
1659             }
1660
1661             mLowerWallpaperTarget = null;
1662             mUpperWallpaperTarget = null;
1663
1664             WindowState oldW = mWallpaperTarget;
1665             mWallpaperTarget = foundW;
1666             targetChanged = true;
1667
1668             // Now what is happening...  if the current and new targets are
1669             // animating, then we are in our super special mode!
1670             if (foundW != null && oldW != null) {
1671                 boolean oldAnim = oldW.isAnimatingLw();
1672                 boolean foundAnim = foundW.isAnimatingLw();
1673                 if (DEBUG_WALLPAPER_LIGHT) {
1674                     Slog.v(TAG, "New animation: " + foundAnim
1675                             + " old animation: " + oldAnim);
1676                 }
1677                 if (foundAnim && oldAnim) {
1678                     int oldI = windows.indexOf(oldW);
1679                     if (DEBUG_WALLPAPER_LIGHT) {
1680                         Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
1681                     }
1682                     if (oldI >= 0) {
1683                         if (DEBUG_WALLPAPER_LIGHT) {
1684                             Slog.v(TAG, "Animating wallpapers: old#" + oldI
1685                                     + "=" + oldW + "; new#" + foundI
1686                                     + "=" + foundW);
1687                         }
1688
1689                         // Set the new target correctly.
1690                         if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
1691                             if (DEBUG_WALLPAPER_LIGHT) {
1692                                 Slog.v(TAG, "Old wallpaper still the target.");
1693                             }
1694                             mWallpaperTarget = oldW;
1695                             foundW = oldW;
1696                             foundI = oldI;
1697                         }
1698                         // Now set the upper and lower wallpaper targets
1699                         // correctly, and make sure that we are positioning
1700                         // the wallpaper below the lower.
1701                         else if (foundI > oldI) {
1702                             // The new target is on top of the old one.
1703                             if (DEBUG_WALLPAPER_LIGHT) {
1704                                 Slog.v(TAG, "Found target above old target.");
1705                             }
1706                             mUpperWallpaperTarget = foundW;
1707                             mLowerWallpaperTarget = oldW;
1708                             foundW = oldW;
1709                             foundI = oldI;
1710                         } else {
1711                             // The new target is below the old one.
1712                             if (DEBUG_WALLPAPER_LIGHT) {
1713                                 Slog.v(TAG, "Found target below old target.");
1714                             }
1715                             mUpperWallpaperTarget = oldW;
1716                             mLowerWallpaperTarget = foundW;
1717                         }
1718                     }
1719                 }
1720             }
1721
1722         } else if (mLowerWallpaperTarget != null) {
1723             // Is it time to stop animating?
1724             if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
1725                 if (DEBUG_WALLPAPER_LIGHT) {
1726                     Slog.v(TAG, "No longer animating wallpaper targets!");
1727                 }
1728                 mLowerWallpaperTarget = null;
1729                 mUpperWallpaperTarget = null;
1730                 mWallpaperTarget = foundW;
1731                 targetChanged = true;
1732             }
1733         }
1734
1735         boolean visible = foundW != null;
1736         if (visible) {
1737             // The window is visible to the compositor...  but is it visible
1738             // to the user?  That is what the wallpaper cares about.
1739             visible = isWallpaperVisible(foundW);
1740             if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
1741
1742             // If the wallpaper target is animating, we may need to copy
1743             // its layer adjustment.  Only do this if we are not transfering
1744             // between two wallpaper targets.
1745             mWallpaperAnimLayerAdjustment =
1746                     (mLowerWallpaperTarget == null && foundW.mAppToken != null)
1747                     ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0;
1748
1749             final int maxLayer = mPolicy.getMaxWallpaperLayer()
1750                     * TYPE_LAYER_MULTIPLIER
1751                     + TYPE_LAYER_OFFSET;
1752
1753             // Now w is the window we are supposed to be behind...  but we
1754             // need to be sure to also be behind any of its attached windows,
1755             // AND any starting window associated with it, AND below the
1756             // maximum layer the policy allows for wallpapers.
1757             while (foundI > 0) {
1758                 WindowState wb = windows.get(foundI-1);
1759                 if (wb.mBaseLayer < maxLayer &&
1760                         wb.mAttachedWindow != foundW &&
1761                         (foundW.mAttachedWindow == null ||
1762                                 wb.mAttachedWindow != foundW.mAttachedWindow) &&
1763                         (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
1764                                 foundW.mToken == null || wb.mToken != foundW.mToken)) {
1765                     // This window is not related to the previous one in any
1766                     // interesting way, so stop here.
1767                     break;
1768                 }
1769                 foundW = wb;
1770                 foundI--;
1771             }
1772         } else {
1773             if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
1774         }
1775
1776         if (foundW == null && topCurW != null) {
1777             // There is no wallpaper target, so it goes at the bottom.
1778             // We will assume it is the same place as last time, if known.
1779             foundW = topCurW;
1780             foundI = topCurI+1;
1781         } else {
1782             // Okay i is the position immediately above the wallpaper.  Look at
1783             // what is below it for later.
1784             foundW = foundI > 0 ? windows.get(foundI-1) : null;
1785         }
1786
1787         if (visible) {
1788             if (mWallpaperTarget.mWallpaperX >= 0) {
1789                 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
1790                 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
1791             }
1792             if (mWallpaperTarget.mWallpaperY >= 0) {
1793                 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
1794                 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
1795             }
1796         }
1797
1798         // Start stepping backwards from here, ensuring that our wallpaper windows
1799         // are correctly placed.
1800         int changed = 0;
1801         int curTokenIndex = mWallpaperTokens.size();
1802         while (curTokenIndex > 0) {
1803             curTokenIndex--;
1804             WindowToken token = mWallpaperTokens.get(curTokenIndex);
1805             if (token.hidden == visible) {
1806                 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
1807                         "Wallpaper token " + token + " hidden=" + !visible);
1808                 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
1809                 token.hidden = !visible;
1810                 // Need to do a layout to ensure the wallpaper now has the
1811                 // correct size.
1812                 getDefaultDisplayContentLocked().layoutNeeded = true;
1813             }
1814
1815             int curWallpaperIndex = token.windows.size();
1816             while (curWallpaperIndex > 0) {
1817                 curWallpaperIndex--;
1818                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1819
1820                 if (visible) {
1821                     updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
1822                 }
1823
1824                 // First, make sure the client has the current visibility
1825                 // state.
1826                 dispatchWallpaperVisibility(wallpaper, visible);
1827
1828                 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
1829                 if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
1830                         + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
1831
1832                 // First, if this window is at the current index, then all
1833                 // is well.
1834                 if (wallpaper == foundW) {
1835                     foundI--;
1836                     foundW = foundI > 0
1837                             ? windows.get(foundI-1) : null;
1838                     continue;
1839                 }
1840
1841                 // The window didn't match...  the current wallpaper window,
1842                 // wherever it is, is in the wrong place, so make sure it is
1843                 // not in the list.
1844                 int oldIndex = windows.indexOf(wallpaper);
1845                 if (oldIndex >= 0) {
1846                     if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
1847                             + oldIndex + ": " + wallpaper);
1848                     windows.remove(oldIndex);
1849                     mWindowsChanged = true;
1850                     if (oldIndex < foundI) {
1851                         foundI--;
1852                     }
1853                 }
1854
1855                 // Now stick it in.
1856                 if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
1857                     Slog.v(TAG, "Moving wallpaper " + wallpaper
1858                             + " from " + oldIndex + " to " + 0);
1859                 }
1860
1861                 windows.add(0, wallpaper);
1862                 mWindowsChanged = true;
1863                 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
1864             }
1865         }
1866
1867         /*
1868         final TaskStack targetStack =
1869                 mWallpaperTarget == null ? null : mWallpaperTarget.getStack();
1870         if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 &&
1871                 targetStack != null && !targetStack.isHomeStack()) {
1872             // If the wallpaper target is not on the home stack then make sure that all windows
1873             // from other non-home stacks are above the wallpaper.
1874             for (i = foundI - 1; i >= 0; --i) {
1875                 WindowState win = windows.get(i);
1876                 if (!win.isVisibleLw()) {
1877                     continue;
1878                 }
1879                 final TaskStack winStack = win.getStack();
1880                 if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) {
1881                     windows.remove(i);
1882                     windows.add(foundI + 1, win);
1883                 }
1884             }
1885         }
1886         */
1887
1888         if (targetChanged && DEBUG_WALLPAPER_LIGHT) {
1889             Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget
1890                     + " lower=" + mLowerWallpaperTarget + " upper="
1891                     + mUpperWallpaperTarget);
1892         }
1893
1894         return changed;
1895     }
1896
1897     void setWallpaperAnimLayerAdjustmentLocked(int adj) {
1898         if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
1899                 "Setting wallpaper layer adj to " + adj);
1900         mWallpaperAnimLayerAdjustment = adj;
1901         int curTokenIndex = mWallpaperTokens.size();
1902         while (curTokenIndex > 0) {
1903             curTokenIndex--;
1904             WindowToken token = mWallpaperTokens.get(curTokenIndex);
1905             int curWallpaperIndex = token.windows.size();
1906             while (curWallpaperIndex > 0) {
1907                 curWallpaperIndex--;
1908                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1909                 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj;
1910                 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win "
1911                         + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
1912             }
1913         }
1914     }
1915
1916     boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
1917             boolean sync) {
1918         boolean changed = false;
1919         boolean rawChanged = false;
1920         float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
1921         float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
1922         int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
1923         int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
1924         changed = wallpaperWin.mXOffset != offset;
1925         if (changed) {
1926             if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
1927                     + wallpaperWin + " x: " + offset);
1928             wallpaperWin.mXOffset = offset;
1929         }
1930         if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
1931             wallpaperWin.mWallpaperX = wpx;
1932             wallpaperWin.mWallpaperXStep = wpxs;
1933             rawChanged = true;
1934         }
1935
1936         float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
1937         float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
1938         int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
1939         offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
1940         if (wallpaperWin.mYOffset != offset) {
1941             if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
1942                     + wallpaperWin + " y: " + offset);
1943             changed = true;
1944             wallpaperWin.mYOffset = offset;
1945         }
1946         if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
1947             wallpaperWin.mWallpaperY = wpy;
1948             wallpaperWin.mWallpaperYStep = wpys;
1949             rawChanged = true;
1950         }
1951
1952         if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
1953                     WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
1954             try {
1955                 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
1956                         + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
1957                         + " y=" + wallpaperWin.mWallpaperY);
1958                 if (sync) {
1959                     mWaitingOnWallpaper = wallpaperWin;
1960                 }
1961                 wallpaperWin.mClient.dispatchWallpaperOffsets(
1962                         wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
1963                         wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
1964                 if (sync) {
1965                     if (mWaitingOnWallpaper != null) {
1966                         long start = SystemClock.uptimeMillis();
1967                         if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
1968                                 < start) {
1969                             try {
1970                                 if (DEBUG_WALLPAPER) Slog.v(TAG,
1971                                         "Waiting for offset complete...");
1972                                 mWindowMap.wait(WALLPAPER_TIMEOUT);
1973                             } catch (InterruptedException e) {
1974                             }
1975                             if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
1976                             if ((start+WALLPAPER_TIMEOUT)
1977                                     < SystemClock.uptimeMillis()) {
1978                                 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
1979                                         + wallpaperWin);
1980                                 mLastWallpaperTimeoutTime = start;
1981                             }
1982                         }
1983                         mWaitingOnWallpaper = null;
1984                     }
1985                 }
1986             } catch (RemoteException e) {
1987             }
1988         }
1989
1990         return changed;
1991     }
1992
1993     void wallpaperOffsetsComplete(IBinder window) {
1994         synchronized (mWindowMap) {
1995             if (mWaitingOnWallpaper != null &&
1996                     mWaitingOnWallpaper.mClient.asBinder() == window) {
1997                 mWaitingOnWallpaper = null;
1998                 mWindowMap.notifyAll();
1999             }
2000         }
2001     }
2002
2003     void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
2004         final DisplayContent displayContent = changingTarget.mDisplayContent;
2005         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2006         final int dw = displayInfo.logicalWidth;
2007         final int dh = displayInfo.logicalHeight;
2008
2009         WindowState target = mWallpaperTarget;
2010         if (target != null) {
2011             if (target.mWallpaperX >= 0) {
2012                 mLastWallpaperX = target.mWallpaperX;
2013             } else if (changingTarget.mWallpaperX >= 0) {
2014                 mLastWallpaperX = changingTarget.mWallpaperX;
2015             }
2016             if (target.mWallpaperY >= 0) {
2017                 mLastWallpaperY = target.mWallpaperY;
2018             } else if (changingTarget.mWallpaperY >= 0) {
2019                 mLastWallpaperY = changingTarget.mWallpaperY;
2020             }
2021         }
2022
2023         int curTokenIndex = mWallpaperTokens.size();
2024         while (curTokenIndex > 0) {
2025             curTokenIndex--;
2026             WindowToken token = mWallpaperTokens.get(curTokenIndex);
2027             int curWallpaperIndex = token.windows.size();
2028             while (curWallpaperIndex > 0) {
2029                 curWallpaperIndex--;
2030                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
2031                 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
2032                     WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
2033                     winAnimator.computeShownFrameLocked();
2034                     // No need to lay out the windows - we can just set the wallpaper position
2035                     // directly.
2036                     winAnimator.setWallpaperOffset(wallpaper.mShownFrame);
2037                     // We only want to be synchronous with one wallpaper.
2038                     sync = false;
2039                 }
2040             }
2041         }
2042     }
2043
2044     /**
2045      * Check wallpaper for visiblity change and notify window if so.
2046      * @param wallpaper The wallpaper to test and notify.
2047      * @param visible Current visibility.
2048      */
2049     void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) {
2050         if (wallpaper.mWallpaperVisible != visible) {
2051             wallpaper.mWallpaperVisible = visible;
2052             try {
2053                 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
2054                         "Updating vis of wallpaper " + wallpaper
2055                         + ": " + visible + " from:\n" + Debug.getCallers(4, "  "));
2056                 wallpaper.mClient.dispatchAppVisibility(visible);
2057             } catch (RemoteException e) {
2058             }
2059         }
2060     }
2061
2062     void updateWallpaperVisibilityLocked() {
2063         final boolean visible = isWallpaperVisible(mWallpaperTarget);
2064         final DisplayContent displayContent = mWallpaperTarget.mDisplayContent;
2065         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2066         final int dw = displayInfo.logicalWidth;
2067         final int dh = displayInfo.logicalHeight;
2068
2069         int curTokenIndex = mWallpaperTokens.size();
2070         while (curTokenIndex > 0) {
2071             curTokenIndex--;
2072             WindowToken token = mWallpaperTokens.get(curTokenIndex);
2073             if (token.hidden == visible) {
2074                 token.hidden = !visible;
2075                 // Need to do a layout to ensure the wallpaper now has the
2076                 // correct size.
2077                 getDefaultDisplayContentLocked().layoutNeeded = true;
2078             }
2079
2080             int curWallpaperIndex = token.windows.size();
2081             while (curWallpaperIndex > 0) {
2082                 curWallpaperIndex--;
2083                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
2084                 if (visible) {
2085                     updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
2086                 }
2087
2088                 dispatchWallpaperVisibility(wallpaper, visible);
2089             }
2090         }
2091     }
2092
2093     public int addWindow(Session session, IWindow client, int seq,
2094             WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
2095             Rect outContentInsets, InputChannel outInputChannel) {
2096         int[] appOp = new int[1];
2097         int res = mPolicy.checkAddPermission(attrs, appOp);
2098         if (res != WindowManagerGlobal.ADD_OKAY) {
2099             return res;
2100         }
2101
2102         boolean reportNewConfig = false;
2103         WindowState attachedWindow = null;
2104         WindowState win = null;
2105         long origId;
2106         final int type = attrs.type;
2107
2108         synchronized(mWindowMap) {
2109             if (!mDisplayReady) {
2110                 throw new IllegalStateException("Display has not been initialialized");
2111             }
2112
2113             final DisplayContent displayContent = getDisplayContentLocked(displayId);
2114             if (displayContent == null) {
2115                 Slog.w(TAG, "Attempted to add window to a display that does not exist: "
2116                         + displayId + ".  Aborting.");
2117                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2118             }
2119             if (!displayContent.hasAccess(session.mUid)) {
2120                 Slog.w(TAG, "Attempted to add window to a display for which the application "
2121                         + "does not have access: " + displayId + ".  Aborting.");
2122                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2123             }
2124
2125             if (mWindowMap.containsKey(client.asBinder())) {
2126                 Slog.w(TAG, "Window " + client + " is already added");
2127                 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
2128             }
2129
2130             if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
2131                 attachedWindow = windowForClientLocked(null, attrs.token, false);
2132                 if (attachedWindow == null) {
2133                     Slog.w(TAG, "Attempted to add window with token that is not a window: "
2134                           + attrs.token + ".  Aborting.");
2135                     return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
2136                 }
2137                 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
2138                         && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
2139                     Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
2140                             + attrs.token + ".  Aborting.");
2141                     return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
2142                 }
2143             }
2144
2145             if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
2146                 Slog.w(TAG, "Attempted to add private presentation window to a non-private display.  Aborting.");
2147                 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2148             }
2149
2150             boolean addToken = false;
2151             WindowToken token = mTokenMap.get(attrs.token);
2152             if (token == null) {
2153                 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2154                     Slog.w(TAG, "Attempted to add application window with unknown token "
2155                           + attrs.token + ".  Aborting.");
2156                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2157                 }
2158                 if (type == TYPE_INPUT_METHOD) {
2159                     Slog.w(TAG, "Attempted to add input method window with unknown token "
2160                           + attrs.token + ".  Aborting.");
2161                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2162                 }
2163                 if (type == TYPE_WALLPAPER) {
2164                     Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
2165                           + attrs.token + ".  Aborting.");
2166                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2167                 }
2168                 if (type == TYPE_DREAM) {
2169                     Slog.w(TAG, "Attempted to add Dream window with unknown token "
2170                           + attrs.token + ".  Aborting.");
2171                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2172                 }
2173                 token = new WindowToken(this, attrs.token, -1, false);
2174                 addToken = true;
2175             } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2176                 AppWindowToken atoken = token.appWindowToken;
2177                 if (atoken == null) {
2178                     Slog.w(TAG, "Attempted to add window with non-application token "
2179                           + token + ".  Aborting.");
2180                     return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
2181                 } else if (atoken.removed) {
2182                     Slog.w(TAG, "Attempted to add window with exiting application token "
2183                           + token + ".  Aborting.");
2184                     return WindowManagerGlobal.ADD_APP_EXITING;
2185                 }
2186                 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
2187                     // No need for this guy!
2188                     if (localLOGV) Slog.v(
2189                             TAG, "**** NO NEED TO START: " + attrs.getTitle());
2190                     return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
2191                 }
2192             } else if (type == TYPE_INPUT_METHOD) {
2193                 if (token.windowType != TYPE_INPUT_METHOD) {
2194                     Slog.w(TAG, "Attempted to add input method window with bad token "
2195                             + attrs.token + ".  Aborting.");
2196                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2197                 }
2198             } else if (type == TYPE_WALLPAPER) {
2199                 if (token.windowType != TYPE_WALLPAPER) {
2200                     Slog.w(TAG, "Attempted to add wallpaper window with bad token "
2201                             + attrs.token + ".  Aborting.");
2202                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2203                 }
2204             } else if (type == TYPE_DREAM) {
2205                 if (token.windowType != TYPE_DREAM) {
2206                     Slog.w(TAG, "Attempted to add Dream window with bad token "
2207                             + attrs.token + ".  Aborting.");
2208                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2209                 }
2210             }
2211
2212             win = new WindowState(this, session, client, token,
2213                     attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
2214             if (win.mDeathRecipient == null) {
2215                 // Client has apparently died, so there is no reason to
2216                 // continue.
2217                 Slog.w(TAG, "Adding window client " + client.asBinder()
2218                         + " that is dead, aborting.");
2219                 return WindowManagerGlobal.ADD_APP_EXITING;
2220             }
2221
2222             mPolicy.adjustWindowParamsLw(win.mAttrs);
2223             win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
2224
2225             res = mPolicy.prepareAddWindowLw(win, attrs);
2226             if (res != WindowManagerGlobal.ADD_OKAY) {
2227                 return res;
2228             }
2229
2230             if (outInputChannel != null && (attrs.inputFeatures
2231                     & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
2232                 String name = win.makeInputChannelName();
2233                 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
2234                 win.setInputChannel(inputChannels[0]);
2235                 inputChannels[1].transferTo(outInputChannel);
2236
2237                 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
2238             }
2239
2240             // From now on, no exceptions or errors allowed!
2241
2242             res = WindowManagerGlobal.ADD_OKAY;
2243
2244             origId = Binder.clearCallingIdentity();
2245
2246             if (addToken) {
2247                 mTokenMap.put(attrs.token, token);
2248             }
2249             win.attach();
2250             mWindowMap.put(client.asBinder(), win);
2251             if (win.mAppOp != AppOpsManager.OP_NONE) {
2252                 if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage())
2253                         != AppOpsManager.MODE_ALLOWED) {
2254                     win.setAppOpVisibilityLw(false);
2255                 }
2256             }
2257
2258             if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
2259                 token.appWindowToken.startingWindow = win;
2260                 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken
2261                         + " startingWindow=" + win);
2262                 Message m = mH.obtainMessage(H.REMOVE_STARTING_TIMEOUT, token.appWindowToken);
2263                 mH.sendMessageDelayed(m, STARTING_WINDOW_TIMEOUT_DURATION);
2264             }
2265
2266             boolean imMayMove = true;
2267
2268             if (type == TYPE_INPUT_METHOD) {
2269                 win.mGivenInsetsPending = true;
2270                 mInputMethodWindow = win;
2271                 addInputMethodWindowToListLocked(win);
2272                 imMayMove = false;
2273             } else if (type == TYPE_INPUT_METHOD_DIALOG) {
2274                 mInputMethodDialogs.add(win);
2275                 addWindowToListInOrderLocked(win, true);
2276                 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
2277                 imMayMove = false;
2278             } else {
2279                 addWindowToListInOrderLocked(win, true);
2280                 if (type == TYPE_WALLPAPER) {
2281                     mLastWallpaperTimeoutTime = 0;
2282                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2283                 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2284                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2285                 } else if (mWallpaperTarget != null
2286                         && mWallpaperTarget.mLayer >= win.mBaseLayer) {
2287                     // If there is currently a wallpaper being shown, and
2288                     // the base layer of the new window is below the current
2289                     // layer of the target window, then adjust the wallpaper.
2290                     // This is to avoid a new window being placed between the
2291                     // wallpaper and its target.
2292                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2293                 }
2294             }
2295
2296             win.mWinAnimator.mEnterAnimationPending = true;
2297
2298             if (displayContent.isDefaultDisplay) {
2299                 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
2300             } else {
2301                 outContentInsets.setEmpty();
2302             }
2303
2304             if (mInTouchMode) {
2305                 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
2306             }
2307             if (win.mAppToken == null || !win.mAppToken.clientHidden) {
2308                 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
2309             }
2310
2311             mInputMonitor.setUpdateInputWindowsNeededLw();
2312
2313             boolean focusChanged = false;
2314             if (win.canReceiveKeys()) {
2315                 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
2316                         false /*updateInputWindows*/);
2317                 if (focusChanged) {
2318                     imMayMove = false;
2319                 }
2320             }
2321
2322             if (imMayMove) {
2323                 moveInputMethodWindowsIfNeededLocked(false);
2324             }
2325
2326             assignLayersLocked(displayContent.getWindowList());
2327             // Don't do layout here, the window must call
2328             // relayout to be displayed, so we'll do it there.
2329
2330             if (focusChanged) {
2331                 finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/);
2332             }
2333             mInputMonitor.updateInputWindowsLw(false /*force*/);
2334
2335             if (localLOGV) Slog.v(
2336                 TAG, "New client " + client.asBinder()
2337                 + ": window=" + win);
2338
2339             if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
2340                 reportNewConfig = true;
2341             }
2342         }
2343
2344         if (reportNewConfig) {
2345             sendNewConfiguration();
2346         }
2347
2348         Binder.restoreCallingIdentity(origId);
2349
2350         return res;
2351     }
2352
2353     public void removeWindow(Session session, IWindow client) {
2354         synchronized(mWindowMap) {
2355             WindowState win = windowForClientLocked(session, client, false);
2356             if (win == null) {
2357                 return;
2358             }
2359             removeWindowLocked(session, win);
2360         }
2361     }
2362
2363     public void removeWindowLocked(Session session, WindowState win) {
2364         if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2365             if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win);
2366             removeStartingWindowTimeout(win.mAppToken);
2367         }
2368
2369         if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v(
2370                 TAG, "Remove " + win + " client="
2371                 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder()))
2372                 + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers="
2373                 + Debug.getCallers(4));
2374
2375         final long origId = Binder.clearCallingIdentity();
2376
2377         win.disposeInputChannel();
2378
2379         if (DEBUG_APP_TRANSITIONS) Slog.v(
2380                 TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl
2381                 + " mExiting=" + win.mExiting
2382                 + " isAnimating=" + win.mWinAnimator.isAnimating()
2383                 + " app-animation="
2384                 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
2385                 + " inPendingTransaction="
2386                 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
2387                 + " mDisplayFrozen=" + mDisplayFrozen);
2388         // Visibility of the removed window. Will be used later to update orientation later on.
2389         boolean wasVisible = false;
2390         // First, see if we need to run an animation.  If we do, we have
2391         // to hold off on removing the window until the animation is done.
2392         // If the display is frozen, just remove immediately, since the
2393         // animation wouldn't be seen.
2394         if (win.mHasSurface && okToDisplay()) {
2395             // If we are not currently running the exit animation, we
2396             // need to see about starting one.
2397             wasVisible = win.isWinVisibleLw();
2398             if (wasVisible) {
2399
2400                 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2401                 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2402                     transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2403                 }
2404                 // Try starting an animation.
2405                 if (win.mWinAnimator.applyAnimationLocked(transit, false)) {
2406                     win.mExiting = true;
2407                 }
2408                 //TODO (multidisplay): Magnification is supported only for the default display.
2409                 if (mDisplayMagnifier != null
2410                         && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
2411                     mDisplayMagnifier.onWindowTransitionLocked(win, transit);
2412                 }
2413             }
2414             if (win.mExiting || win.mWinAnimator.isAnimating()) {
2415                 // The exit animation is running... wait for it!
2416                 //Slog.i(TAG, "*** Running exit animation...");
2417                 win.mExiting = true;
2418                 win.mRemoveOnExit = true;
2419                 win.mDisplayContent.layoutNeeded = true;
2420                 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
2421                         false /*updateInputWindows*/);
2422                 performLayoutAndPlaceSurfacesLocked();
2423                 if (win.mAppToken != null) {
2424                     win.mAppToken.updateReportedVisibilityLocked();
2425                 }
2426                 //dump();
2427                 Binder.restoreCallingIdentity(origId);
2428                 return;
2429             }
2430         }
2431
2432         removeWindowInnerLocked(session, win);
2433         // Removing a visible window will effect the computed orientation
2434         // So just update orientation if needed.
2435         if (wasVisible && updateOrientationFromAppTokensLocked(false)) {
2436             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
2437         }
2438         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
2439         Binder.restoreCallingIdentity(origId);
2440     }
2441
2442     private void removeWindowInnerLocked(Session session, WindowState win) {
2443         if (win.mRemoved) {
2444             // Nothing to do.
2445             return;
2446         }
2447
2448         for (int i=win.mChildWindows.size()-1; i>=0; i--) {
2449             WindowState cwin = win.mChildWindows.get(i);
2450             Slog.w(TAG, "Force-removing child win " + cwin + " from container "
2451                     + win);
2452             removeWindowInnerLocked(cwin.mSession, cwin);
2453         }
2454
2455         win.mRemoved = true;
2456
2457         if (mInputMethodTarget == win) {
2458             moveInputMethodWindowsIfNeededLocked(false);
2459         }
2460
2461         if (false) {
2462             RuntimeException e = new RuntimeException("here");
2463             e.fillInStackTrace();
2464             Slog.w(TAG, "Removing window " + win, e);
2465         }
2466
2467         mPolicy.removeWindowLw(win);
2468         win.removeLocked();
2469
2470         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win);
2471         mWindowMap.remove(win.mClient.asBinder());
2472         if (win.mAppOp != AppOpsManager.OP_NONE) {
2473             mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
2474         }
2475
2476         final WindowList windows = win.getWindowList();
2477         windows.remove(win);
2478         mPendingRemove.remove(win);
2479         mResizingWindows.remove(win);
2480         mWindowsChanged = true;
2481         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
2482
2483         if (mInputMethodWindow == win) {
2484             mInputMethodWindow = null;
2485         } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2486             mInputMethodDialogs.remove(win);
2487         }
2488
2489         final WindowToken token = win.mToken;
2490         final AppWindowToken atoken = win.mAppToken;
2491         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token);
2492         token.windows.remove(win);
2493         if (atoken != null) {
2494             atoken.allAppWindows.remove(win);
2495         }
2496         if (localLOGV) Slog.v(
2497                 TAG, "**** Removing window " + win + ": count="
2498                 + token.windows.size());
2499         if (token.windows.size() == 0) {
2500             if (!token.explicit) {
2501                 mTokenMap.remove(token.token);
2502             } else if (atoken != null) {
2503                 atoken.firstWindowDrawn = false;
2504             }
2505         }
2506
2507         if (atoken != null) {
2508             if (atoken.startingWindow == win) {
2509                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling startingWindow " + win);
2510                 removeStartingWindowTimeout(atoken);
2511                 atoken.startingWindow = null;
2512             } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2513                 // If this is the last window and we had requested a starting
2514                 // transition window, well there is no point now.
2515                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling last startingWindow");
2516                 atoken.startingData = null;
2517             } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2518                 // If this is the last window except for a starting transition
2519                 // window, we need to get rid of the starting transition.
2520                 scheduleRemoveStartingWindow(atoken);
2521             }
2522         }
2523
2524         if (win.mAttrs.type == TYPE_WALLPAPER) {
2525             mLastWallpaperTimeoutTime = 0;
2526             getDefaultDisplayContentLocked().pendingLayoutChanges |=
2527                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2528         } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2529             getDefaultDisplayContentLocked().pendingLayoutChanges |=
2530                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2531         }
2532
2533         if (!mInLayout) {
2534             assignLayersLocked(windows);
2535             win.mDisplayContent.layoutNeeded = true;
2536             performLayoutAndPlaceSurfacesLocked();
2537             if (win.mAppToken != null) {
2538                 win.mAppToken.updateReportedVisibilityLocked();
2539             }
2540         }
2541
2542         mInputMonitor.updateInputWindowsLw(true /*force*/);
2543     }
2544
2545     public void updateAppOpsState() {
2546         synchronized(mWindowMap) {
2547             final int numDisplays = mDisplayContents.size();
2548             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
2549                 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
2550                 final int numWindows = windows.size();
2551                 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
2552                     final WindowState win = windows.get(winNdx);
2553                     if (win.mAppOp != AppOpsManager.OP_NONE) {
2554                         final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
2555                                 win.getOwningPackage());
2556                         win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED);
2557                     }
2558                 }
2559             }
2560         }
2561     }
2562
2563     static void logSurface(WindowState w, String msg, RuntimeException where) {
2564         String str = "  SURFACE " + msg + ": " + w;
2565         if (where != null) {
2566             Slog.i(TAG, str, where);
2567         } else {
2568             Slog.i(TAG, str);
2569         }
2570     }
2571
2572     static void logSurface(SurfaceControl s, String title, String msg, RuntimeException where) {
2573         String str = "  SURFACE " + s + ": " + msg + " / " + title;
2574         if (where != null) {
2575             Slog.i(TAG, str, where);
2576         } else {
2577             Slog.i(TAG, str);
2578         }
2579     }
2580
2581     void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2582         long origId = Binder.clearCallingIdentity();
2583         try {
2584             synchronized (mWindowMap) {
2585                 WindowState w = windowForClientLocked(session, client, false);
2586                 if ((w != null) && w.mHasSurface) {
2587                     w.mWinAnimator.setTransparentRegionHintLocked(region);
2588                 }
2589             }
2590         } finally {
2591             Binder.restoreCallingIdentity(origId);
2592         }
2593     }
2594
2595     void setInsetsWindow(Session session, IWindow client,
2596             int touchableInsets, Rect contentInsets,
2597             Rect visibleInsets, Region touchableRegion) {
2598         long origId = Binder.clearCallingIdentity();
2599         try {
2600             synchronized (mWindowMap) {
2601                 WindowState w = windowForClientLocked(session, client, false);
2602                 if (w != null) {
2603                     w.mGivenInsetsPending = false;
2604                     w.mGivenContentInsets.set(contentInsets);
2605                     w.mGivenVisibleInsets.set(visibleInsets);
2606                     w.mGivenTouchableRegion.set(touchableRegion);
2607                     w.mTouchableInsets = touchableInsets;
2608                     if (w.mGlobalScale != 1) {
2609                         w.mGivenContentInsets.scale(w.mGlobalScale);
2610                         w.mGivenVisibleInsets.scale(w.mGlobalScale);
2611                         w.mGivenTouchableRegion.scale(w.mGlobalScale);
2612                     }
2613                     w.mDisplayContent.layoutNeeded = true;
2614                     performLayoutAndPlaceSurfacesLocked();
2615                 }
2616             }
2617         } finally {
2618             Binder.restoreCallingIdentity(origId);
2619         }
2620     }
2621
2622     public void getWindowDisplayFrame(Session session, IWindow client,
2623             Rect outDisplayFrame) {
2624         synchronized(mWindowMap) {
2625             WindowState win = windowForClientLocked(session, client, false);
2626             if (win == null) {
2627                 outDisplayFrame.setEmpty();
2628                 return;
2629             }
2630             outDisplayFrame.set(win.mDisplayFrame);
2631         }
2632     }
2633
2634     public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
2635             float xStep, float yStep) {
2636         if (window.mWallpaperX != x || window.mWallpaperY != y)  {
2637             window.mWallpaperX = x;
2638             window.mWallpaperY = y;
2639             window.mWallpaperXStep = xStep;
2640             window.mWallpaperYStep = yStep;
2641             updateWallpaperOffsetLocked(window, true);
2642         }
2643     }
2644
2645     void wallpaperCommandComplete(IBinder window, Bundle result) {
2646         synchronized (mWindowMap) {
2647             if (mWaitingOnWallpaper != null &&
2648                     mWaitingOnWallpaper.mClient.asBinder() == window) {
2649                 mWaitingOnWallpaper = null;
2650                 mWindowMap.notifyAll();
2651             }
2652         }
2653     }
2654
2655     public Bundle sendWindowWallpaperCommandLocked(WindowState window,
2656             String action, int x, int y, int z, Bundle extras, boolean sync) {
2657         if (window == mWallpaperTarget || window == mLowerWallpaperTarget
2658                 || window == mUpperWallpaperTarget) {
2659             boolean doWait = sync;
2660             int curTokenIndex = mWallpaperTokens.size();
2661             while (curTokenIndex > 0) {
2662                 curTokenIndex--;
2663                 WindowToken token = mWallpaperTokens.get(curTokenIndex);
2664                 int curWallpaperIndex = token.windows.size();
2665                 while (curWallpaperIndex > 0) {
2666                     curWallpaperIndex--;
2667                     WindowState wallpaper = token.windows.get(curWallpaperIndex);
2668                     try {
2669                         wallpaper.mClient.dispatchWallpaperCommand(action,
2670                                 x, y, z, extras, sync);
2671                         // We only want to be synchronous with one wallpaper.
2672                         sync = false;
2673                     } catch (RemoteException e) {
2674                     }
2675                 }
2676             }
2677
2678             if (doWait) {
2679                 // XXX Need to wait for result.
2680             }
2681         }
2682
2683         return null;
2684     }
2685
2686     public void setUniverseTransformLocked(WindowState window, float alpha,
2687             float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) {
2688         Transformation transform = window.mWinAnimator.mUniverseTransform;
2689         transform.setAlpha(alpha);
2690         Matrix matrix = transform.getMatrix();
2691         matrix.getValues(mTmpFloats);
2692         mTmpFloats[Matrix.MTRANS_X] = offx;
2693         mTmpFloats[Matrix.MTRANS_Y] = offy;
2694         mTmpFloats[Matrix.MSCALE_X] = dsdx;
2695         mTmpFloats[Matrix.MSKEW_Y] = dtdx;
2696         mTmpFloats[Matrix.MSKEW_X] = dsdy;
2697         mTmpFloats[Matrix.MSCALE_Y] = dtdy;
2698         matrix.setValues(mTmpFloats);
2699         final DisplayInfo displayInfo = window.mDisplayContent.getDisplayInfo();
2700         final RectF dispRect = new RectF(0, 0,
2701                 displayInfo.logicalWidth, displayInfo.logicalHeight);
2702         matrix.mapRect(dispRect);
2703         window.mGivenTouchableRegion.set(0, 0,
2704                 displayInfo.logicalWidth, displayInfo.logicalHeight);
2705         window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top,
2706                 (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE);
2707         window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
2708         window.mDisplayContent.layoutNeeded = true;
2709         performLayoutAndPlaceSurfacesLocked();
2710     }
2711
2712     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle, boolean immediate) {
2713         synchronized (mWindowMap) {
2714             if (mDisplayMagnifier != null) {
2715                 WindowState window = mWindowMap.get(token);
2716                 //TODO (multidisplay): Magnification is supported only for the default display.
2717                 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
2718                     mDisplayMagnifier.onRectangleOnScreenRequestedLocked(rectangle, immediate);
2719                 }
2720             }
2721         }
2722     }
2723
2724     public IWindowId getWindowId(IBinder token) {
2725         synchronized (mWindowMap) {
2726             WindowState window = mWindowMap.get(token);
2727             return window != null ? window.mWindowId : null;
2728         }
2729     }
2730
2731     public int relayoutWindow(Session session, IWindow client, int seq,
2732             WindowManager.LayoutParams attrs, int requestedWidth,
2733             int requestedHeight, int viewVisibility, int flags,
2734             Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
2735             Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
2736         boolean toBeDisplayed = false;
2737         boolean inTouchMode;
2738         boolean configChanged;
2739         boolean surfaceChanged = false;
2740         boolean animating;
2741
2742         // if they don't have this permission, mask out the status bar bits
2743         int systemUiVisibility = 0;
2744         if (attrs != null) {
2745             systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility);
2746             if ((systemUiVisibility & StatusBarManager.DISABLE_MASK) != 0) {
2747                 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
2748                         != PackageManager.PERMISSION_GRANTED) {
2749                     systemUiVisibility &= ~StatusBarManager.DISABLE_MASK;
2750                 }
2751             }
2752         }
2753         long origId = Binder.clearCallingIdentity();
2754
2755         synchronized(mWindowMap) {
2756             WindowState win = windowForClientLocked(session, client, false);
2757             if (win == null) {
2758                 return 0;
2759             }
2760             WindowStateAnimator winAnimator = win.mWinAnimator;
2761             if (win.mRequestedWidth != requestedWidth
2762                     || win.mRequestedHeight != requestedHeight) {
2763                 win.mLayoutNeeded = true;
2764                 win.mRequestedWidth = requestedWidth;
2765                 win.mRequestedHeight = requestedHeight;
2766             }
2767             if (attrs != null && seq == win.mSeq) {
2768                 win.mSystemUiVisibility = systemUiVisibility;
2769             }
2770
2771             if (attrs != null) {
2772                 mPolicy.adjustWindowParamsLw(attrs);
2773             }
2774
2775             winAnimator.mSurfaceDestroyDeferred =
2776                     (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
2777
2778             int attrChanges = 0;
2779             int flagChanges = 0;
2780             if (attrs != null) {
2781                 if (win.mAttrs.type != attrs.type) {
2782                     throw new IllegalArgumentException(
2783                             "Window type can not be changed after the window is added.");
2784                 }
2785                 flagChanges = win.mAttrs.flags ^= attrs.flags;
2786                 attrChanges = win.mAttrs.copyFrom(attrs);
2787                 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
2788                         | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
2789                     win.mLayoutNeeded = true;
2790                 }
2791             }
2792
2793             if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
2794                     + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
2795
2796             win.mEnforceSizeCompat =
2797                     (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
2798
2799             if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2800                 winAnimator.mAlpha = attrs.alpha;
2801             }
2802
2803             final boolean scaledWindow =
2804                 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
2805
2806             if (scaledWindow) {
2807                 // requested{Width|Height} Surface's physical size
2808                 // attrs.{width|height} Size on screen
2809                 win.mHScale = (attrs.width  != requestedWidth)  ?
2810                         (attrs.width  / (float)requestedWidth) : 1.0f;
2811                 win.mVScale = (attrs.height != requestedHeight) ?
2812                         (attrs.height / (float)requestedHeight) : 1.0f;
2813             } else {
2814                 win.mHScale = win.mVScale = 1;
2815             }
2816
2817             boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
2818
2819             final boolean isDefaultDisplay = win.isDefaultDisplay();
2820             boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
2821                     || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
2822                     || (!win.mRelayoutCalled));
2823
2824             boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2825                     && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
2826             wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
2827
2828             win.mRelayoutCalled = true;
2829             final int oldVisibility = win.mViewVisibility;
2830             win.mViewVisibility = viewVisibility;
2831             if (DEBUG_SCREEN_ON) {
2832                 RuntimeException stack = new RuntimeException();
2833                 stack.fillInStackTrace();
2834                 Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility
2835                         + " newVis=" + viewVisibility, stack);
2836             }
2837             if (viewVisibility == View.VISIBLE &&
2838                     (win.mAppToken == null || !win.mAppToken.clientHidden)) {
2839                 toBeDisplayed = !win.isVisibleLw();
2840                 if (win.mExiting) {
2841                     winAnimator.cancelExitAnimationForNextAnimationLocked();
2842                     win.mExiting = false;
2843                 }
2844                 if (win.mDestroying) {
2845                     win.mDestroying = false;
2846                     mDestroySurface.remove(win);
2847                 }
2848                 if (oldVisibility == View.GONE) {
2849                     winAnimator.mEnterAnimationPending = true;
2850                 }
2851                 if (toBeDisplayed) {
2852                     if (win.isDrawnLw() && okToDisplay()) {
2853                         winAnimator.applyEnterAnimationLocked();
2854                     }
2855                     if ((win.mAttrs.flags
2856                             & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
2857                         if (DEBUG_VISIBILITY) Slog.v(TAG,
2858                                 "Relayout window turning screen on: " + win);
2859                         win.mTurnOnScreen = true;
2860                     }
2861                     if (win.isConfigChanged()) {
2862                         if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win
2863                                 + " visible with new config: " + mCurConfiguration);
2864                         outConfig.setTo(mCurConfiguration);
2865                     }
2866                 }
2867                 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
2868                     // To change the format, we need to re-build the surface.
2869                     winAnimator.destroySurfaceLocked();
2870                     toBeDisplayed = true;
2871                     surfaceChanged = true;
2872                 }
2873                 try {
2874                     if (!win.mHasSurface) {
2875                         surfaceChanged = true;
2876                     }
2877                     SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
2878                     if (surfaceControl != null) {
2879                         outSurface.copyFrom(surfaceControl);
2880                         if (SHOW_TRANSACTIONS) Slog.i(TAG,
2881                                 "  OUT SURFACE " + outSurface + ": copied");
2882                     } else {
2883                         // For some reason there isn't a surface.  Clear the
2884                         // caller's object so they see the same state.
2885                         outSurface.release();
2886                     }
2887                 } catch (Exception e) {
2888                     mInputMonitor.updateInputWindowsLw(true /*force*/);
2889
2890                     Slog.w(TAG, "Exception thrown when creating surface for client "
2891                              + client + " (" + win.mAttrs.getTitle() + ")",
2892                              e);
2893                     Binder.restoreCallingIdentity(origId);
2894                     return 0;
2895                 }
2896                 if (toBeDisplayed) {
2897                     focusMayChange = isDefaultDisplay;
2898                 }
2899                 if (win.mAttrs.type == TYPE_INPUT_METHOD
2900                         && mInputMethodWindow == null) {
2901                     mInputMethodWindow = win;
2902                     imMayMove = true;
2903                 }
2904                 if (win.mAttrs.type == TYPE_BASE_APPLICATION
2905                         && win.mAppToken != null
2906                         && win.mAppToken.startingWindow != null) {
2907                     // Special handling of starting window over the base
2908                     // window of the app: propagate lock screen flags to it,
2909                     // to provide the correct semantics while starting.
2910                     final int mask =
2911                         WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
2912                         | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
2913                         | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
2914                     WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
2915                     sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
2916                 }
2917             } else {
2918                 winAnimator.mEnterAnimationPending = false;
2919                 if (winAnimator.mSurfaceControl != null) {
2920                     if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
2921                             + ": mExiting=" + win.mExiting);
2922                     // If we are not currently running the exit animation, we
2923                     // need to see about starting one.
2924                     if (!win.mExiting) {
2925                         surfaceChanged = true;
2926                         // Try starting an animation; if there isn't one, we
2927                         // can destroy the surface right away.
2928                         int transit = WindowManagerPolicy.TRANSIT_EXIT;
2929                         if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2930                             transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2931                         }
2932                         if (win.isWinVisibleLw() &&
2933                                 winAnimator.applyAnimationLocked(transit, false)) {
2934                             focusMayChange = isDefaultDisplay;
2935                             win.mExiting = true;
2936                         } else if (win.mWinAnimator.isAnimating()) {
2937                             // Currently in a hide animation... turn this into
2938                             // an exit.
2939                             win.mExiting = true;
2940                         } else if (win == mWallpaperTarget) {
2941                             // If the wallpaper is currently behind this
2942                             // window, we need to change both of them inside
2943                             // of a transaction to avoid artifacts.
2944                             win.mExiting = true;
2945                             win.mWinAnimator.mAnimating = true;
2946                         } else {
2947                             if (mInputMethodWindow == win) {
2948                                 mInputMethodWindow = null;
2949                             }
2950                             winAnimator.destroySurfaceLocked();
2951                         }
2952                         //TODO (multidisplay): Magnification is supported only for the default
2953                         if (mDisplayMagnifier != null
2954                                 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
2955                             mDisplayMagnifier.onWindowTransitionLocked(win, transit);
2956                         }
2957                     }
2958                 }
2959
2960                 outSurface.release();
2961                 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
2962             }
2963
2964             if (focusMayChange) {
2965                 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2966                 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
2967                         false /*updateInputWindows*/)) {
2968                     imMayMove = false;
2969                 }
2970                 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2971             }
2972
2973             // updateFocusedWindowLocked() already assigned layers so we only need to
2974             // reassign them at this point if the IM window state gets shuffled
2975             if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) {
2976                 // Little hack here -- we -should- be able to rely on the
2977                 // function to return true if the IME has moved and needs
2978                 // its layer recomputed.  However, if the IME was hidden
2979                 // and isn't actually moved in the list, its layer may be
2980                 // out of data so we make sure to recompute it.
2981                 assignLayersLocked(win.getWindowList());
2982             }
2983
2984             if (wallpaperMayMove) {
2985                 getDefaultDisplayContentLocked().pendingLayoutChanges |=
2986                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2987             }
2988
2989             win.mDisplayContent.layoutNeeded = true;
2990             win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
2991             configChanged = updateOrientationFromAppTokensLocked(false);
2992             performLayoutAndPlaceSurfacesLocked();
2993             if (toBeDisplayed && win.mIsWallpaper) {
2994                 DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
2995                 updateWallpaperOffsetLocked(win,
2996                         displayInfo.logicalWidth, displayInfo.logicalHeight, false);
2997             }
2998             if (win.mAppToken != null) {
2999                 win.mAppToken.updateReportedVisibilityLocked();
3000             }
3001             outFrame.set(win.mCompatFrame);
3002             outOverscanInsets.set(win.mOverscanInsets);
3003             outContentInsets.set(win.mContentInsets);
3004             outVisibleInsets.set(win.mVisibleInsets);
3005             if (localLOGV) Slog.v(
3006                 TAG, "Relayout given client " + client.asBinder()
3007                 + ", requestedWidth=" + requestedWidth
3008                 + ", requestedHeight=" + requestedHeight
3009                 + ", viewVisibility=" + viewVisibility
3010                 + "\nRelayout returning frame=" + outFrame
3011                 + ", surface=" + outSurface);
3012
3013             if (localLOGV || DEBUG_FOCUS) Slog.v(
3014                 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
3015
3016             inTouchMode = mInTouchMode;
3017             animating = mAnimator.mAnimating;
3018             if (animating && !mRelayoutWhileAnimating.contains(win)) {
3019                 mRelayoutWhileAnimating.add(win);
3020             }
3021
3022             mInputMonitor.updateInputWindowsLw(true /*force*/);
3023
3024             if (DEBUG_LAYOUT) {
3025                 Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
3026             }
3027         }
3028
3029         if (configChanged) {
3030             sendNewConfiguration();
3031         }
3032
3033         Binder.restoreCallingIdentity(origId);
3034
3035         return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0)
3036                 | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0)
3037                 | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0)
3038                 | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0);
3039     }
3040
3041     public void performDeferredDestroyWindow(Session session, IWindow client) {
3042         long origId = Binder.clearCallingIdentity();
3043
3044         try {
3045             synchronized (mWindowMap) {
3046                 WindowState win = windowForClientLocked(session, client, false);
3047                 if (win == null) {
3048                     return;
3049                 }
3050                 win.mWinAnimator.destroyDeferredSurfaceLocked();
3051             }
3052         } finally {
3053             Binder.restoreCallingIdentity(origId);
3054         }
3055     }
3056
3057     public boolean outOfMemoryWindow(Session session, IWindow client) {
3058         long origId = Binder.clearCallingIdentity();
3059
3060         try {
3061             synchronized (mWindowMap) {
3062                 WindowState win = windowForClientLocked(session, client, false);
3063                 if (win == null) {
3064                     return false;
3065                 }
3066                 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false);
3067             }
3068         } finally {
3069             Binder.restoreCallingIdentity(origId);
3070         }
3071     }
3072
3073     public void finishDrawingWindow(Session session, IWindow client) {
3074         final long origId = Binder.clearCallingIdentity();
3075         try {
3076             synchronized (mWindowMap) {
3077                 WindowState win = windowForClientLocked(session, client, false);
3078                 if (win != null && win.mWinAnimator.finishDrawingLocked()) {
3079                     if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
3080                         getDefaultDisplayContentLocked().pendingLayoutChanges |=
3081                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
3082                     }
3083                     win.mDisplayContent.layoutNeeded = true;
3084                     requestTraversalLocked();
3085                 }
3086             }
3087         } finally {
3088             Binder.restoreCallingIdentity(origId);
3089         }
3090     }
3091
3092     @Override
3093     public void getWindowFrame(IBinder token, Rect outBounds) {
3094         if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
3095                 "getWindowInfo()")) {
3096             throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
3097         }
3098         synchronized (mWindowMap) {
3099             WindowState windowState = mWindowMap.get(token);
3100             if (windowState != null) {
3101                 outBounds.set(windowState.mFrame);
3102             } else {
3103                 outBounds.setEmpty();
3104             }
3105         }
3106     }
3107
3108     @Override
3109     public void setMagnificationSpec(MagnificationSpec spec) {
3110         if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
3111                 "setMagnificationSpec()")) {
3112             throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
3113         }
3114         synchronized (mWindowMap) {
3115             if (mDisplayMagnifier != null) {
3116                 mDisplayMagnifier.setMagnificationSpecLocked(spec);
3117             } else {
3118                 throw new IllegalStateException("Magnification callbacks not set!");
3119             }
3120         }
3121         if (Binder.getCallingPid() != android.os.Process.myPid()) {
3122             spec.recycle();
3123         }
3124     }
3125
3126     @Override
3127     public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
3128         if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
3129                 "getCompatibleMagnificationSpecForWindow()")) {
3130             throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
3131         }
3132         synchronized (mWindowMap) {
3133             WindowState windowState = mWindowMap.get(windowToken);
3134             if (windowState == null) {
3135                 return null;
3136             }
3137             MagnificationSpec spec = null;
3138             if (mDisplayMagnifier != null) {
3139                 spec = mDisplayMagnifier.getMagnificationSpecForWindowLocked(windowState);
3140             }
3141             if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
3142                 return null;
3143             }
3144             spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
3145             spec.scale *= windowState.mGlobalScale;
3146             return spec;
3147         }
3148     }
3149
3150     @Override
3151     public void setMagnificationCallbacks(IMagnificationCallbacks callbacks) {
3152         if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
3153                 "setMagnificationCallbacks()")) {
3154             throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
3155         }
3156         synchronized (mWindowMap) {
3157             if (mDisplayMagnifier == null) {
3158                 mDisplayMagnifier = new DisplayMagnifier(this, callbacks);
3159             } else {
3160                 if (callbacks == null) {
3161                     if (mDisplayMagnifier != null) {
3162                         mDisplayMagnifier.destroyLocked();
3163                         mDisplayMagnifier = null;
3164                     }
3165                 } else {
3166                     throw new IllegalStateException("Magnification callbacks already set!");
3167                 }
3168             }
3169         }
3170     }
3171
3172     private boolean applyAnimationLocked(AppWindowToken atoken,
3173             WindowManager.LayoutParams lp, int transit, boolean enter) {
3174         // Only apply an animation if the display isn't frozen.  If it is
3175         // frozen, there is no reason to animate and it can cause strange
3176         // artifacts when we unfreeze the display if some different animation
3177         // is running.
3178         if (okToDisplay()) {
3179             DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
3180             final int width = displayInfo.appWidth;
3181             final int height = displayInfo.appHeight;
3182             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken="
3183                     + atoken);
3184             Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height);
3185             if (a != null) {
3186                 if (DEBUG_ANIM) {
3187                     RuntimeException e = null;
3188                     if (!HIDE_STACK_CRAWLS) {
3189                         e = new RuntimeException();
3190                         e.fillInStackTrace();
3191                     }
3192                     Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e);
3193                 }
3194                 atoken.mAppAnimator.setAnimation(a, width, height);
3195             }
3196         } else {
3197             atoken.mAppAnimator.clearAnimation();
3198         }
3199
3200         return atoken.mAppAnimator.animation != null;
3201     }
3202
3203     // -------------------------------------------------------------
3204     // Application Window Tokens
3205     // -------------------------------------------------------------
3206
3207     public void validateAppTokens(int stackId, List<TaskGroup> tasks) {
3208         synchronized (mWindowMap) {
3209             int t = tasks.size() - 1;
3210             if (t < 0) {
3211                 Slog.w(TAG, "validateAppTokens: empty task list");
3212                 return;
3213             }
3214
3215             TaskGroup task = tasks.get(0);
3216             int taskId = task.taskId;
3217             Task targetTask = mTaskIdToTask.get(taskId);
3218             DisplayContent displayContent = targetTask.getDisplayContent();
3219             if (displayContent == null) {
3220                 Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId);
3221                 return;
3222             }
3223
3224             final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks();
3225             int taskNdx;
3226             for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) {
3227                 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens;
3228                 task = tasks.get(t);
3229                 List<IApplicationToken> tokens = task.tokens;
3230
3231                 DisplayContent lastDisplayContent = displayContent;
3232                 displayContent = mTaskIdToTask.get(taskId).getDisplayContent();
3233                 if (displayContent != lastDisplayContent) {
3234                     Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!");
3235                     return;
3236                 }
3237
3238                 int tokenNdx;
3239                 int v;
3240                 for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1;
3241                         tokenNdx >= 0 && v >= 0; ) {
3242                     final AppWindowToken atoken = localTokens.get(tokenNdx);
3243                     if (atoken.removed) {
3244                         --tokenNdx;
3245                         continue;
3246                     }
3247                     if (tokens.get(v) != atoken.token) {
3248                         break;
3249                     }
3250                     --tokenNdx;
3251                     v--;
3252                 }
3253
3254                 if (tokenNdx >= 0 || v >= 0) {
3255                     break;
3256                 }
3257             }
3258
3259             if (taskNdx >= 0 || t >= 0) {
3260                 Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks);
3261                 Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + localTasks);
3262                 Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4));
3263             }
3264         }
3265     }
3266
3267     public void validateStackOrder(Integer[] remoteStackIds) {
3268         // TODO:
3269     }
3270
3271     boolean checkCallingPermission(String permission, String func) {
3272         // Quick check: if the calling permission is me, it's all okay.
3273         if (Binder.getCallingPid() == Process.myPid()) {
3274             return true;
3275         }
3276
3277         if (mContext.checkCallingPermission(permission)
3278                 == PackageManager.PERMISSION_GRANTED) {
3279             return true;
3280         }
3281         String msg = "Permission Denial: " + func + " from pid="
3282                 + Binder.getCallingPid()
3283                 + ", uid=" + Binder.getCallingUid()
3284                 + " requires " + permission;
3285         Slog.w(TAG, msg);
3286         return false;
3287     }
3288
3289     boolean okToDisplay() {
3290         return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully();
3291     }
3292
3293     AppWindowToken findAppWindowToken(IBinder token) {
3294         WindowToken wtoken = mTokenMap.get(token);
3295         if (wtoken == null) {
3296             return null;
3297         }
3298         return wtoken.appWindowToken;
3299     }
3300
3301     @Override
3302     public void addWindowToken(IBinder token, int type) {
3303         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3304                 "addWindowToken()")) {
3305             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3306         }
3307
3308         synchronized(mWindowMap) {
3309             WindowToken wtoken = mTokenMap.get(token);
3310             if (wtoken != null) {
3311                 Slog.w(TAG, "Attempted to add existing input method token: " + token);
3312                 return;
3313             }
3314             wtoken = new WindowToken(this, token, type, true);
3315             mTokenMap.put(token, wtoken);
3316             if (type == TYPE_WALLPAPER) {
3317                 mWallpaperTokens.add(wtoken);
3318             }
3319         }
3320     }
3321
3322     @Override
3323     public void removeWindowToken(IBinder token) {
3324         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3325                 "removeWindowToken()")) {
3326             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3327         }
3328
3329         final long origId = Binder.clearCallingIdentity();
3330         synchronized(mWindowMap) {
3331             DisplayContent displayContent = null;
3332             WindowToken wtoken = mTokenMap.remove(token);
3333             if (wtoken != null) {
3334                 boolean delayed = false;
3335                 if (!wtoken.hidden) {
3336                     final int N = wtoken.windows.size();
3337                     boolean changed = false;
3338
3339                     for (int i=0; i<N; i++) {
3340                         WindowState win = wtoken.windows.get(i);
3341                         displayContent = win.mDisplayContent;
3342
3343                         if (win.mWinAnimator.isAnimating()) {
3344                             delayed = true;
3345                         }
3346
3347                         if (win.isVisibleNow()) {
3348                             win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
3349                                     false);
3350                             //TODO (multidisplay): Magnification is supported only for the default
3351                             if (mDisplayMagnifier != null && win.isDefaultDisplay()) {
3352                                 mDisplayMagnifier.onWindowTransitionLocked(win,
3353                                         WindowManagerPolicy.TRANSIT_EXIT);
3354                             }
3355                             changed = true;
3356                             displayContent.layoutNeeded = true;
3357                         }
3358                     }
3359
3360                     wtoken.hidden = true;
3361
3362                     if (changed) {
3363                         performLayoutAndPlaceSurfacesLocked();
3364                         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
3365                                 false /*updateInputWindows*/);
3366                     }
3367
3368                     if (delayed) {
3369                         displayContent.mExitingTokens.add(wtoken);
3370                     } else if (wtoken.windowType == TYPE_WALLPAPER) {
3371                         mWallpaperTokens.remove(wtoken);
3372                     }
3373                 }
3374
3375                 mInputMonitor.updateInputWindowsLw(true /*force*/);
3376             } else {
3377                 Slog.w(TAG, "Attempted to remove non-existing token: " + token);
3378             }
3379         }
3380         Binder.restoreCallingIdentity(origId);
3381     }
3382
3383     private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) {
3384         final TaskStack stack = mStackIdToStack.get(stackId);
3385         if (stack == null) {
3386             throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
3387         }
3388         Task task = new Task(atoken, stack, userId);
3389         mTaskIdToTask.put(taskId, task);
3390         stack.addTask(task, true);
3391         stack.getDisplayContent().moveStack(stack, true);
3392         return task;
3393     }
3394
3395     @Override
3396     public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
3397             int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId) {
3398         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3399                 "addAppToken()")) {
3400             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3401         }
3402
3403         // Get the dispatching timeout here while we are not holding any locks so that it
3404         // can be cached by the AppWindowToken.  The timeout value is used later by the
3405         // input dispatcher in code that does hold locks.  If we did not cache the value
3406         // here we would run the chance of introducing a deadlock between the window manager
3407         // (which holds locks while updating the input dispatcher state) and the activity manager
3408         // (which holds locks while querying the application token).
3409         long inputDispatchingTimeoutNanos;
3410         try {
3411             inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
3412         } catch (RemoteException ex) {
3413             Slog.w(TAG, "Could not get dispatching timeout.", ex);
3414             inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
3415         }
3416
3417         synchronized(mWindowMap) {
3418             AppWindowToken atoken = findAppWindowToken(token.asBinder());
3419             if (atoken != null) {
3420                 Slog.w(TAG, "Attempted to add existing app token: " + token);
3421                 return;
3422             }
3423             atoken = new AppWindowToken(this, token);
3424             atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
3425             atoken.groupId = taskId;
3426             atoken.appFullscreen = fullscreen;
3427             atoken.showWhenLocked = showWhenLocked;
3428             atoken.requestedOrientation = requestedOrientation;
3429             if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
3430                     + " to stack=" + stackId + " task=" + taskId + " at " + addPos);
3431
3432             Task task = mTaskIdToTask.get(taskId);
3433             if (task == null) {
3434                 task = createTask(taskId, stackId, userId, atoken);
3435             } else {
3436                 task.addAppToken(addPos, atoken);
3437             }
3438
3439             mTokenMap.put(token.asBinder(), atoken);
3440
3441             // Application tokens start out hidden.
3442             atoken.hidden = true;
3443             atoken.hiddenRequested = true;
3444
3445             //dump();
3446         }
3447     }
3448
3449     @Override
3450     public void setAppGroupId(IBinder token, int groupId) {
3451         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3452                 "setAppGroupId()")) {
3453             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3454         }
3455
3456         synchronized(mWindowMap) {
3457             final AppWindowToken atoken = findAppWindowToken(token);
3458             if (atoken == null) {
3459                 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
3460                 return;
3461             }
3462             Task oldTask = mTaskIdToTask.get(atoken.groupId);
3463             oldTask.removeAppToken(atoken);
3464
3465             atoken.groupId = groupId;
3466             Task newTask = mTaskIdToTask.get(groupId);
3467             if (newTask == null) {
3468                 newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken);
3469             }
3470             newTask.mAppTokens.add(atoken);
3471         }
3472     }
3473
3474     public int getOrientationFromWindowsLocked() {
3475         if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
3476             // If the display is frozen, some activities may be in the middle
3477             // of restarting, and thus have removed their old window.  If the
3478             // window has the flag to hide the lock screen, then the lock screen
3479             // can re-appear and inflict its own orientation on us.  Keep the
3480             // orientation stable until this all settles down.
3481             return mLastWindowForcedOrientation;
3482         }
3483
3484         // TODO(multidisplay): Change to the correct display.
3485         final WindowList windows = getDefaultWindowListLocked();
3486         int pos = windows.size() - 1;
3487         while (pos >= 0) {
3488             WindowState win = windows.get(pos);
3489             pos--;
3490             if (win.mAppToken != null) {
3491                 // We hit an application window. so the orientation will be determined by the
3492                 // app window. No point in continuing further.
3493                 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3494             }
3495             if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
3496                 continue;
3497             }
3498             int req = win.mAttrs.screenOrientation;
3499             if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
3500                     (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
3501                 continue;
3502             }
3503
3504             if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req);
3505             return (mLastWindowForcedOrientation=req);
3506         }
3507         return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3508     }
3509
3510     public int getOrientationFromAppTokensLocked() {
3511         int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3512         boolean findingBehind = false;
3513         boolean lastFullscreen = false;
3514         // TODO: Multi window.
3515         DisplayContent displayContent = getDefaultDisplayContentLocked();
3516         final ArrayList<Task> tasks = displayContent.getTasks();
3517         for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
3518             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
3519             final int firstToken = tokens.size() - 1;
3520             for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) {
3521                 final AppWindowToken atoken = tokens.get(tokenNdx);
3522
3523                 if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
3524
3525                 // if we're about to tear down this window and not seek for
3526                 // the behind activity, don't use it for orientation
3527                 if (!findingBehind
3528                         && (!atoken.hidden && atoken.hiddenRequested)) {
3529                     if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
3530                             + " -- going to hide");
3531                     continue;
3532                 }
3533
3534                 if (tokenNdx == firstToken) {
3535                     // If we have hit a new Task, and the bottom
3536                     // of the previous group didn't explicitly say to use
3537                     // the orientation behind it, and the last app was
3538                     // full screen, then we'll stick with the
3539                     // user's orientation.
3540                     if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
3541                             && lastFullscreen) {
3542                         if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3543                                 + " -- end of group, return " + lastOrientation);
3544                         return lastOrientation;
3545                     }
3546                 }
3547
3548                 // We ignore any hidden applications on the top.
3549                 if (atoken.hiddenRequested || atoken.willBeHidden) {
3550                     if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
3551                             + " -- hidden on top");
3552                     continue;
3553                 }
3554
3555                 if (tokenNdx == 0) {
3556                     // Last token in this task.
3557                     lastOrientation = atoken.requestedOrientation;
3558                 }
3559
3560                 int or = atoken.requestedOrientation;
3561                 // If this application is fullscreen, and didn't explicitly say
3562                 // to use the orientation behind it, then just take whatever
3563                 // orientation it has and ignores whatever is under it.
3564                 lastFullscreen = atoken.appFullscreen;
3565                 if (lastFullscreen
3566                         && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3567                     if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3568                             + " -- full screen, return " + or);
3569                     return or;
3570                 }
3571                 // If this application has requested an explicit orientation,
3572                 // then use it.
3573                 if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
3574                         && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3575                     if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3576                             + " -- explicitly set, return " + or);
3577                     return or;
3578                 }
3579                 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
3580             }
3581         }
3582         if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation");
3583         return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3584     }
3585
3586     @Override
3587     public Configuration updateOrientationFromAppTokens(
3588             Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3589         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3590                 "updateOrientationFromAppTokens()")) {
3591             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3592         }
3593
3594         Configuration config = null;
3595         long ident = Binder.clearCallingIdentity();
3596
3597         synchronized(mWindowMap) {
3598             config = updateOrientationFromAppTokensLocked(currentConfig,
3599                     freezeThisOneIfNeeded);
3600         }
3601
3602         Binder.restoreCallingIdentity(ident);
3603         return config;
3604     }
3605
3606     private Configuration updateOrientationFromAppTokensLocked(
3607             Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3608         Configuration config = null;
3609
3610         if (updateOrientationFromAppTokensLocked(false)) {
3611             if (freezeThisOneIfNeeded != null) {
3612                 AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
3613                 if (atoken != null) {
3614                     startAppFreezingScreenLocked(atoken, ActivityInfo.CONFIG_ORIENTATION);
3615                 }
3616             }
3617             config = computeNewConfigurationLocked();
3618
3619         } else if (currentConfig != null) {
3620             // No obvious action we need to take, but if our current
3621             // state mismatches the activity manager's, update it,
3622             // disregarding font scale, which should remain set to
3623             // the value of the previous configuration.
3624             mTempConfiguration.setToDefaults();
3625             mTempConfiguration.fontScale = currentConfig.fontScale;
3626             if (computeScreenConfigurationLocked(mTempConfiguration)) {
3627                 if (currentConfig.diff(mTempConfiguration) != 0) {
3628                     mWaitingForConfig = true;
3629                     final DisplayContent displayContent = getDefaultDisplayContentLocked();
3630                     displayContent.layoutNeeded = true;
3631                     int anim[] = new int[2];
3632                     if (displayContent.isDimming()) {
3633                         anim[0] = anim[1] = 0;
3634                     } else {
3635                         mPolicy.selectRotationAnimationLw(anim);
3636                     }
3637                     startFreezingDisplayLocked(false, anim[0], anim[1]);
3638                     config = new Configuration(mTempConfiguration);
3639                 }
3640             }
3641         }
3642
3643         return config;
3644     }
3645
3646     /*
3647      * Determine the new desired orientation of the display, returning
3648      * a non-null new Configuration if it has changed from the current
3649      * orientation.  IF TRUE IS RETURNED SOMEONE MUST CALL
3650      * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3651      * SCREEN.  This will typically be done for you if you call
3652      * sendNewConfiguration().
3653      *
3654      * The orientation is computed from non-application windows first. If none of
3655      * the non-application windows specify orientation, the orientation is computed from
3656      * application tokens.
3657      * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3658      * android.os.IBinder)
3659      */
3660     boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
3661         long ident = Binder.clearCallingIdentity();
3662         try {
3663             int req = getOrientationFromWindowsLocked();
3664             if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
3665                 req = getOrientationFromAppTokensLocked();
3666             }
3667
3668             if (req != mForcedAppOrientation) {
3669                 mForcedAppOrientation = req;
3670                 //send a message to Policy indicating orientation change to take
3671                 //action like disabling/enabling sensors etc.,
3672                 mPolicy.setCurrentOrientationLw(req);
3673                 if (updateRotationUncheckedLocked(inTransaction)) {
3674                     // changed
3675                     return true;
3676                 }
3677             }
3678
3679             return false;
3680         } finally {
3681             Binder.restoreCallingIdentity(ident);
3682         }
3683     }
3684
3685     @Override
3686     public void setNewConfiguration(Configuration config) {
3687         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3688                 "setNewConfiguration()")) {
3689             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3690         }
3691
3692         synchronized(mWindowMap) {
3693             mCurConfiguration = new Configuration(config);
3694             if (mWaitingForConfig) {
3695                 mWaitingForConfig = false;
3696                 mLastFinishedFreezeSource = "new-config";
3697             }
3698             performLayoutAndPlaceSurfacesLocked();
3699         }
3700     }
3701
3702     @Override
3703     public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3704         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3705                 "setAppOrientation()")) {
3706             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3707         }
3708
3709         synchronized(mWindowMap) {
3710             AppWindowToken atoken = findAppWindowToken(token.asBinder());
3711             if (atoken == null) {
3712                 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
3713                 return;
3714             }
3715
3716             atoken.requestedOrientation = requestedOrientation;
3717         }
3718     }
3719
3720     @Override
3721     public int getAppOrientation(IApplicationToken token) {
3722         synchronized(mWindowMap) {
3723             AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3724             if (wtoken == null) {
3725                 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3726             }
3727
3728             return wtoken.requestedOrientation;
3729         }
3730     }
3731
3732     /** Call while in a Surface transaction. */
3733     void setFocusedStackLayer() {
3734         mFocusedStackLayer = 0;
3735         if (mFocusedApp != null) {
3736             final WindowList windows = mFocusedApp.allAppWindows;
3737             for (int i = windows.size() - 1; i >= 0; --i) {
3738                 final WindowState win = windows.get(i);
3739                 final int animLayer = win.mWinAnimator.mAnimLayer;
3740                 if (win.mAttachedWindow == null && win.isVisibleLw() &&
3741                         animLayer > mFocusedStackLayer) {
3742                     mFocusedStackLayer = animLayer + LAYER_OFFSET_FOCUSED_STACK;
3743                 }
3744             }
3745         }
3746         if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedStackFrame to layer=" +
3747                 mFocusedStackLayer);
3748         mFocusedStackFrame.setLayer(mFocusedStackLayer);
3749     }
3750
3751     void setFocusedStackFrame() {
3752         final TaskStack stack;
3753         if (mFocusedApp != null) {
3754             Task task = mTaskIdToTask.get(mFocusedApp.groupId);
3755             stack = task.mStack;
3756             task.getDisplayContent().setTouchExcludeRegion(stack);
3757         } else {
3758             stack = null;
3759         }
3760         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame");
3761         SurfaceControl.openTransaction();
3762         try {
3763             if (stack == null) {
3764                 mFocusedStackFrame.setVisibility(false);
3765             } else {
3766                 final StackBox box = stack.mStackBox;
3767                 final Rect bounds = box.mBounds;
3768                 final boolean multipleStacks = box.mParent != null;
3769                 mFocusedStackFrame.setBounds(bounds);
3770                 mFocusedStackFrame.setVisibility(multipleStacks);
3771             }
3772         } finally {
3773             SurfaceControl.closeTransaction();
3774             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame");
3775         }
3776     }
3777
3778     @Override
3779     public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3780         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3781                 "setFocusedApp()")) {
3782             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3783         }
3784
3785         synchronized(mWindowMap) {
3786             boolean changed = false;
3787             if (token == null) {
3788                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
3789                 changed = mFocusedApp != null;
3790                 mFocusedApp = null;
3791                 if (changed) {
3792                     mInputMonitor.setFocusedAppLw(null);
3793                 }
3794             } else {
3795                 AppWindowToken newFocus = findAppWindowToken(token);
3796                 if (newFocus == null) {
3797                     Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
3798                     return;
3799                 }
3800                 changed = mFocusedApp != newFocus;
3801                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus
3802                         + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
3803                 mFocusedApp = newFocus;
3804                 if (changed) {
3805                     mInputMonitor.setFocusedAppLw(newFocus);
3806                 }
3807             }
3808
3809             if (moveFocusNow && changed) {
3810                 final long origId = Binder.clearCallingIdentity();
3811                 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
3812                 Binder.restoreCallingIdentity(origId);
3813             }
3814         }
3815     }
3816
3817     @Override
3818     public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
3819         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3820                 "prepareAppTransition()")) {
3821             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3822         }
3823
3824         synchronized(mWindowMap) {
3825             if (DEBUG_APP_TRANSITIONS) Slog.v(
3826                     TAG, "Prepare app transition: transit=" + transit
3827                     + " " + mAppTransition
3828                     + " alwaysKeepCurrent=" + alwaysKeepCurrent
3829                     + " Callers=" + Debug.getCallers(3));
3830             if (okToDisplay()) {
3831                 if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) {
3832                     mAppTransition.setAppTransition(transit);
3833                 } else if (!alwaysKeepCurrent) {
3834                     if (transit == AppTransition.TRANSIT_TASK_OPEN
3835                             && mAppTransition.isTransitionEqual(
3836                                     AppTransition.TRANSIT_TASK_CLOSE)) {
3837                         // Opening a new task always supersedes a close for the anim.
3838                         mAppTransition.setAppTransition(transit);
3839                     } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN
3840                             && mAppTransition.isTransitionEqual(
3841                                 AppTransition.TRANSIT_ACTIVITY_CLOSE)) {
3842                         // Opening a new activity always supersedes a close for the anim.
3843                         mAppTransition.setAppTransition(transit);
3844                     }
3845                 }
3846                 mAppTransition.prepare();
3847                 mStartingIconInTransition = false;
3848                 mSkipAppTransitionAnimation = false;
3849                 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
3850                 mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000);
3851             }
3852         }
3853     }
3854
3855     @Override
3856     public int getPendingAppTransition() {
3857         return mAppTransition.getAppTransition();
3858     }
3859
3860     @Override
3861     public void overridePendingAppTransition(String packageName,
3862             int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
3863         synchronized(mWindowMap) {
3864             mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,
3865                     startedCallback);
3866         }
3867     }
3868
3869     @Override
3870     public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
3871             int startHeight) {
3872         synchronized(mWindowMap) {
3873             mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth,
3874                     startHeight);
3875         }
3876     }
3877
3878     @Override
3879     public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
3880             int startY, IRemoteCallback startedCallback, boolean scaleUp) {
3881         synchronized(mWindowMap) {
3882             mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
3883                     startedCallback, scaleUp);
3884         }
3885     }
3886
3887     @Override
3888     public void executeAppTransition() {
3889         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3890                 "executeAppTransition()")) {
3891             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3892         }
3893
3894         synchronized(mWindowMap) {
3895             if (DEBUG_APP_TRANSITIONS) {
3896                 RuntimeException e = new RuntimeException("here");
3897                 e.fillInStackTrace();
3898                 Slog.w(TAG, "Execute app transition: " + mAppTransition, e);
3899             }
3900             if (mAppTransition.isTransitionSet()) {
3901                 mAppTransition.setReady();
3902                 final long origId = Binder.clearCallingIdentity();
3903                 performLayoutAndPlaceSurfacesLocked();
3904                 Binder.restoreCallingIdentity(origId);
3905             }
3906         }
3907     }
3908
3909     @Override
3910     public void setAppStartingWindow(IBinder token, String pkg,
3911             int theme, CompatibilityInfo compatInfo,
3912             CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
3913             int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
3914         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3915                 "setAppStartingWindow()")) {
3916             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3917         }
3918
3919         synchronized(mWindowMap) {
3920             if (DEBUG_STARTING_WINDOW) Slog.v(
3921                     TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg
3922                     + " transferFrom=" + transferFrom);
3923
3924             AppWindowToken wtoken = findAppWindowToken(token);
3925             if (wtoken == null) {
3926                 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
3927                 return;
3928             }
3929
3930             // If the display is frozen, we won't do anything until the
3931             // actual window is displayed so there is no reason to put in
3932             // the starting window.
3933             if (!okToDisplay()) {
3934                 return;
3935             }
3936
3937             if (wtoken.startingData != null) {
3938                 return;
3939             }
3940
3941             if (transferFrom != null) {
3942                 AppWindowToken ttoken = findAppWindowToken(transferFrom);
3943                 if (ttoken != null) {
3944                     WindowState startingWindow = ttoken.startingWindow;
3945                     if (startingWindow != null) {
3946                         if (mStartingIconInTransition) {
3947                             // In this case, the starting icon has already
3948                             // been displayed, so start letting windows get
3949                             // shown immediately without any more transitions.
3950                             mSkipAppTransitionAnimation = true;
3951                         }
3952                         if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
3953                                 "Moving existing starting " + startingWindow + " from " + ttoken
3954                                 + " to " + wtoken);
3955                         final long origId = Binder.clearCallingIdentity();
3956
3957                         // Transfer the starting window over to the new
3958                         // token.
3959                         wtoken.startingData = ttoken.startingData;
3960                         wtoken.startingView = ttoken.startingView;
3961                         wtoken.startingDisplayed = ttoken.startingDisplayed;
3962                         ttoken.startingDisplayed = false;
3963                         wtoken.startingWindow = startingWindow;
3964                         wtoken.reportedVisible = ttoken.reportedVisible;
3965                         ttoken.startingData = null;
3966                         ttoken.startingView = null;
3967                         ttoken.startingWindow = null;
3968                         ttoken.startingMoved = true;
3969                         startingWindow.mToken = wtoken;
3970                         startingWindow.mRootToken = wtoken;
3971                         startingWindow.mAppToken = wtoken;
3972                         startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator;
3973
3974                         if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
3975                             Slog.v(TAG, "Removing starting window: " + startingWindow);
3976                         }
3977                         removeStartingWindowTimeout(ttoken);
3978                         startingWindow.getWindowList().remove(startingWindow);
3979                         mWindowsChanged = true;
3980                         if (DEBUG_ADD_REMOVE) Slog.v(TAG,
3981                                 "Removing starting " + startingWindow + " from " + ttoken);
3982                         ttoken.windows.remove(startingWindow);
3983                         ttoken.allAppWindows.remove(startingWindow);
3984                         addWindowToListInOrderLocked(startingWindow, true);
3985
3986                         // Propagate other interesting state between the
3987                         // tokens.  If the old token is displayed, we should
3988                         // immediately force the new one to be displayed.  If
3989                         // it is animating, we need to move that animation to
3990                         // the new one.
3991                         if (ttoken.allDrawn) {
3992                             wtoken.allDrawn = true;
3993                             wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn;
3994                         }
3995                         if (ttoken.firstWindowDrawn) {
3996                             wtoken.firstWindowDrawn = true;
3997                         }
3998                         if (!ttoken.hidden) {
3999                             wtoken.hidden = false;
4000                             wtoken.hiddenRequested = false;
4001                             wtoken.willBeHidden = false;
4002                         }
4003                         if (wtoken.clientHidden != ttoken.clientHidden) {
4004                             wtoken.clientHidden = ttoken.clientHidden;
4005                             wtoken.sendAppVisibilityToClients();
4006                         }
4007                         final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4008                         final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4009                         if (tAppAnimator.animation != null) {
4010                             wAppAnimator.animation = tAppAnimator.animation;
4011                             wAppAnimator.animating = tAppAnimator.animating;
4012                             wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment;
4013                             tAppAnimator.animation = null;
4014                             tAppAnimator.animLayerAdjustment = 0;
4015                             wAppAnimator.updateLayers();
4016                             tAppAnimator.updateLayers();
4017                         }
4018
4019                         updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4020                                 true /*updateInputWindows*/);
4021                         getDefaultDisplayContentLocked().layoutNeeded = true;
4022                         performLayoutAndPlaceSurfacesLocked();
4023                         Binder.restoreCallingIdentity(origId);
4024                         return;
4025                     } else if (ttoken.startingData != null) {
4026                         // The previous app was getting ready to show a
4027                         // starting window, but hasn't yet done so.  Steal it!
4028                         if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
4029                                 "Moving pending starting from " + ttoken
4030                                 + " to " + wtoken);
4031                         wtoken.startingData = ttoken.startingData;
4032                         ttoken.startingData = null;
4033                         ttoken.startingMoved = true;
4034                         Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4035                         // Note: we really want to do sendMessageAtFrontOfQueue() because we
4036                         // want to process the message ASAP, before any other queued
4037                         // messages.
4038                         mH.sendMessageAtFrontOfQueue(m);
4039                         return;
4040                     }
4041                     final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4042                     final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4043                     if (tAppAnimator.thumbnail != null) {
4044                         // The old token is animating with a thumbnail, transfer
4045                         // that to the new token.
4046                         if (wAppAnimator.thumbnail != null) {
4047                             wAppAnimator.thumbnail.destroy();
4048                         }
4049                         wAppAnimator.thumbnail = tAppAnimator.thumbnail;
4050                         wAppAnimator.thumbnailX = tAppAnimator.thumbnailX;
4051                         wAppAnimator.thumbnailY = tAppAnimator.thumbnailY;
4052                         wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
4053                         wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
4054                         tAppAnimator.thumbnail = null;
4055                     }
4056                 }
4057             }
4058
4059             // There is no existing starting window, and the caller doesn't
4060             // want us to create one, so that's it!
4061             if (!createIfNeeded) {
4062                 return;
4063             }
4064
4065             // If this is a translucent window, then don't
4066             // show a starting window -- the current effect (a full-screen
4067             // opaque starting window that fades away to the real contents
4068             // when it is ready) does not work for this.
4069             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x"
4070                     + Integer.toHexString(theme));
4071             if (theme != 0) {
4072                 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
4073                         com.android.internal.R.styleable.Window, mCurrentUserId);
4074                 if (ent == null) {
4075                     // Whoops!  App doesn't exist.  Um.  Okay.  We'll just
4076                     // pretend like we didn't see that.
4077                     return;
4078                 }
4079                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent="
4080                         + ent.array.getBoolean(
4081                                 com.android.internal.R.styleable.Window_windowIsTranslucent, false)
4082                         + " Floating="
4083                         + ent.array.getBoolean(
4084                                 com.android.internal.R.styleable.Window_windowIsFloating, false)
4085                         + " ShowWallpaper="
4086                         + ent.array.getBoolean(
4087                                 com.android.internal.R.styleable.Window_windowShowWallpaper, false));
4088                 if (ent.array.getBoolean(
4089                         com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
4090                     return;
4091                 }
4092                 if (ent.array.getBoolean(
4093                         com.android.internal.R.styleable.Window_windowIsFloating, false)) {
4094                     return;
4095                 }
4096                 if (ent.array.getBoolean(
4097                         com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
4098                     if (mWallpaperTarget == null) {
4099                         // If this theme is requesting a wallpaper, and the wallpaper
4100                         // is not curently visible, then this effectively serves as
4101                         // an opaque window and our starting window transition animation
4102                         // can still work.  We just need to make sure the starting window
4103                         // is also showing the wallpaper.
4104                         windowFlags |= FLAG_SHOW_WALLPAPER;
4105                     } else {
4106                         return;
4107                     }
4108                 }
4109             }
4110
4111             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData");
4112             mStartingIconInTransition = true;
4113             wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
4114                     labelRes, icon, logo, windowFlags);
4115             Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4116             // Note: we really want to do sendMessageAtFrontOfQueue() because we
4117             // want to process the message ASAP, before any other queued
4118             // messages.
4119             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
4120             mH.sendMessageAtFrontOfQueue(m);
4121         }
4122     }
4123
4124     @Override
4125     public void setAppWillBeHidden(IBinder token) {
4126         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4127                 "setAppWillBeHidden()")) {
4128             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4129         }
4130
4131         AppWindowToken wtoken;
4132
4133         synchronized(mWindowMap) {
4134             wtoken = findAppWindowToken(token);
4135             if (wtoken == null) {
4136                 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
4137                 return;
4138             }
4139             wtoken.willBeHidden = true;
4140         }
4141     }
4142
4143     public void setAppFullscreen(IBinder token, boolean toOpaque) {
4144         AppWindowToken atoken = findAppWindowToken(token);
4145         if (atoken != null) {
4146             atoken.appFullscreen = toOpaque;
4147             requestTraversal();
4148         }
4149     }
4150
4151     boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
4152             boolean visible, int transit, boolean performLayout) {
4153         boolean delayed = false;
4154
4155         if (wtoken.clientHidden == visible) {
4156             wtoken.clientHidden = !visible;
4157             wtoken.sendAppVisibilityToClients();
4158         }
4159
4160         wtoken.willBeHidden = false;
4161         if (wtoken.hidden == visible) {
4162             boolean changed = false;
4163             if (DEBUG_APP_TRANSITIONS) Slog.v(
4164                 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
4165                 + " performLayout=" + performLayout);
4166
4167             boolean runningAppAnimation = false;
4168
4169             if (transit != AppTransition.TRANSIT_UNSET) {
4170                 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
4171                     wtoken.mAppAnimator.animation = null;
4172                 }
4173                 if (applyAnimationLocked(wtoken, lp, transit, visible)) {
4174                     delayed = runningAppAnimation = true;
4175                 }
4176                 WindowState window = wtoken.findMainWindow();
4177                 //TODO (multidisplay): Magnification is supported only for the default display.
4178                 if (window != null && mDisplayMagnifier != null
4179                         && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
4180                     mDisplayMagnifier.onAppWindowTransitionLocked(window, transit);
4181                 }
4182                 changed = true;
4183             }
4184
4185             final int N = wtoken.allAppWindows.size();
4186             for (int i=0; i<N; i++) {
4187                 WindowState win = wtoken.allAppWindows.get(i);
4188                 if (win == wtoken.startingWindow) {
4189                     continue;
4190                 }
4191
4192                 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
4193                 //win.dump("  ");
4194                 if (visible) {
4195                     if (!win.isVisibleNow()) {
4196                         if (!runningAppAnimation) {
4197                             win.mWinAnimator.applyAnimationLocked(
4198                                     WindowManagerPolicy.TRANSIT_ENTER, true);
4199                             //TODO (multidisplay): Magnification is supported only for the default
4200                             if (mDisplayMagnifier != null
4201                                     && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4202                                 mDisplayMagnifier.onWindowTransitionLocked(win,
4203                                         WindowManagerPolicy.TRANSIT_ENTER);
4204                             }
4205                         }
4206                         changed = true;
4207                         win.mDisplayContent.layoutNeeded = true;
4208                     }
4209                 } else if (win.isVisibleNow()) {
4210                     if (!runningAppAnimation) {
4211                         win.mWinAnimator.applyAnimationLocked(
4212                                 WindowManagerPolicy.TRANSIT_EXIT, false);
4213                         //TODO (multidisplay): Magnification is supported only for the default
4214                         if (mDisplayMagnifier != null
4215                                 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4216                             mDisplayMagnifier.onWindowTransitionLocked(win,
4217                                     WindowManagerPolicy.TRANSIT_EXIT);
4218                         }
4219                     }
4220                     changed = true;
4221                     win.mDisplayContent.layoutNeeded = true;
4222                 }
4223             }
4224
4225             wtoken.hidden = wtoken.hiddenRequested = !visible;
4226             if (!visible) {
4227                 unsetAppFreezingScreenLocked(wtoken, true, true);
4228             } else {
4229                 // If we are being set visible, and the starting window is
4230                 // not yet displayed, then make sure it doesn't get displayed.
4231                 WindowState swin = wtoken.startingWindow;
4232                 if (swin != null && !swin.isDrawnLw()) {
4233                     swin.mPolicyVisibility = false;
4234                     swin.mPolicyVisibilityAfterAnim = false;
4235                  }
4236             }
4237
4238             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
4239                       + ": hidden=" + wtoken.hidden + " hiddenRequested="
4240                       + wtoken.hiddenRequested);
4241
4242             if (changed) {
4243                 mInputMonitor.setUpdateInputWindowsNeededLw();
4244                 if (performLayout) {
4245                     updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4246                             false /*updateInputWindows*/);
4247                     performLayoutAndPlaceSurfacesLocked();
4248                 }
4249                 mInputMonitor.updateInputWindowsLw(false /*force*/);
4250             }
4251         }
4252
4253         if (wtoken.mAppAnimator.animation != null) {
4254             delayed = true;
4255         }
4256
4257         for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
4258             if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) {
4259                 delayed = true;
4260             }
4261         }
4262
4263         return delayed;
4264     }
4265
4266     @Override
4267     public void setAppVisibility(IBinder token, boolean visible) {
4268         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4269                 "setAppVisibility()")) {
4270             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4271         }
4272
4273         AppWindowToken wtoken;
4274
4275         synchronized(mWindowMap) {
4276             wtoken = findAppWindowToken(token);
4277             if (wtoken == null) {
4278                 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
4279                 return;
4280             }
4281
4282             if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
4283                 RuntimeException e = null;
4284                 if (!HIDE_STACK_CRAWLS) {
4285                     e = new RuntimeException();
4286                     e.fillInStackTrace();
4287                 }
4288                 Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible
4289                         + "): " + mAppTransition
4290                         + " hidden=" + wtoken.hidden
4291                         + " hiddenRequested=" + wtoken.hiddenRequested, e);
4292             }
4293
4294             // If we are preparing an app transition, then delay changing
4295             // the visibility of this token until we execute that transition.
4296             if (okToDisplay() && mAppTransition.isTransitionSet()) {
4297                 // Already in requested state, don't do anything more.
4298                 if (wtoken.hiddenRequested != visible) {
4299                     return;
4300                 }
4301                 wtoken.hiddenRequested = !visible;
4302
4303                 if (!wtoken.startingDisplayed) {
4304                     if (DEBUG_APP_TRANSITIONS) Slog.v(
4305                             TAG, "Setting dummy animation on: " + wtoken);
4306                     wtoken.mAppAnimator.setDummyAnimation();
4307                 }
4308                 mOpeningApps.remove(wtoken);
4309                 mClosingApps.remove(wtoken);
4310                 wtoken.waitingToShow = wtoken.waitingToHide = false;
4311                 wtoken.inPendingTransaction = true;
4312                 if (visible) {
4313                     mOpeningApps.add(wtoken);
4314                     wtoken.startingMoved = false;
4315
4316                     // If the token is currently hidden (should be the
4317                     // common case), then we need to set up to wait for
4318                     // its windows to be ready.
4319                     if (wtoken.hidden) {
4320                         wtoken.allDrawn = false;
4321                         wtoken.deferClearAllDrawn = false;
4322                         wtoken.waitingToShow = true;
4323
4324                         if (wtoken.clientHidden) {
4325                             // In the case where we are making an app visible
4326                             // but holding off for a transition, we still need
4327                             // to tell the client to make its windows visible so
4328                             // they get drawn.  Otherwise, we will wait on
4329                             // performing the transition until all windows have
4330                             // been drawn, they never will be, and we are sad.
4331                             wtoken.clientHidden = false;
4332                             wtoken.sendAppVisibilityToClients();
4333                         }
4334                     }
4335                 } else {
4336                     mClosingApps.add(wtoken);
4337
4338                     // If the token is currently visible (should be the
4339                     // common case), then set up to wait for it to be hidden.
4340                     if (!wtoken.hidden) {
4341                         wtoken.waitingToHide = true;
4342                     }
4343                 }
4344                 return;
4345             }
4346
4347             final long origId = Binder.clearCallingIdentity();
4348             setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
4349                     true);
4350             wtoken.updateReportedVisibilityLocked();
4351             Binder.restoreCallingIdentity(origId);
4352         }
4353     }
4354
4355     void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
4356             boolean unfreezeSurfaceNow, boolean force) {
4357         if (wtoken.mAppAnimator.freezingScreen) {
4358             if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
4359                     + " force=" + force);
4360             final int N = wtoken.allAppWindows.size();
4361             boolean unfrozeWindows = false;
4362             for (int i=0; i<N; i++) {
4363                 WindowState w = wtoken.allAppWindows.get(i);
4364                 if (w.mAppFreezing) {
4365                     w.mAppFreezing = false;
4366                     if (w.mHasSurface && !w.mOrientationChanging) {
4367                         if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w);
4368                         w.mOrientationChanging = true;
4369                         mInnerFields.mOrientationChangeComplete = false;
4370                     }
4371                     w.mLastFreezeDuration = 0;
4372                     unfrozeWindows = true;
4373                     w.mDisplayContent.layoutNeeded = true;
4374                 }
4375             }
4376             if (force || unfrozeWindows) {
4377                 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
4378                 wtoken.mAppAnimator.freezingScreen = false;
4379                 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime()
4380                         - mDisplayFreezeTime);
4381                 mAppsFreezingScreen--;
4382                 mLastFinishedFreezeSource = wtoken;
4383             }
4384             if (unfreezeSurfaceNow) {
4385                 if (unfrozeWindows) {
4386                     performLayoutAndPlaceSurfacesLocked();
4387                 }
4388                 stopFreezingDisplayLocked();
4389             }
4390         }
4391     }
4392
4393     public void startAppFreezingScreenLocked(AppWindowToken wtoken,
4394             int configChanges) {
4395         if (DEBUG_ORIENTATION) {
4396             RuntimeException e = null;
4397             if (!HIDE_STACK_CRAWLS) {
4398                 e = new RuntimeException();
4399                 e.fillInStackTrace();
4400             }
4401             Slog.i(TAG, "Set freezing of " + wtoken.appToken
4402                     + ": hidden=" + wtoken.hidden + " freezing="
4403                     + wtoken.mAppAnimator.freezingScreen, e);
4404         }
4405         if (!wtoken.hiddenRequested) {
4406             if (!wtoken.mAppAnimator.freezingScreen) {
4407                 wtoken.mAppAnimator.freezingScreen = true;
4408                 wtoken.mAppAnimator.lastFreezeDuration = 0;
4409                 mAppsFreezingScreen++;
4410                 if (mAppsFreezingScreen == 1) {
4411                     startFreezingDisplayLocked(false, 0, 0);
4412                     mH.removeMessages(H.APP_FREEZE_TIMEOUT);
4413                     mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000);
4414                 }
4415             }
4416             final int N = wtoken.allAppWindows.size();
4417             for (int i=0; i<N; i++) {
4418                 WindowState w = wtoken.allAppWindows.get(i);
4419                 w.mAppFreezing = true;
4420             }
4421         }
4422     }
4423
4424     @Override
4425     public void startAppFreezingScreen(IBinder token, int configChanges) {
4426         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4427                 "setAppFreezingScreen()")) {
4428             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4429         }
4430
4431         synchronized(mWindowMap) {
4432             if (configChanges == 0 && okToDisplay()) {
4433                 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
4434                 return;
4435             }
4436
4437             AppWindowToken wtoken = findAppWindowToken(token);
4438             if (wtoken == null || wtoken.appToken == null) {
4439                 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
4440                 return;
4441             }
4442             final long origId = Binder.clearCallingIdentity();
4443             startAppFreezingScreenLocked(wtoken, configChanges);
4444             Binder.restoreCallingIdentity(origId);
4445         }
4446     }
4447
4448     @Override
4449     public void stopAppFreezingScreen(IBinder token, boolean force) {
4450         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4451                 "setAppFreezingScreen()")) {
4452             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4453         }
4454
4455         synchronized(mWindowMap) {
4456             AppWindowToken wtoken = findAppWindowToken(token);
4457             if (wtoken == null || wtoken.appToken == null) {
4458                 return;
4459             }
4460             final long origId = Binder.clearCallingIdentity();
4461             if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
4462                     + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
4463             unsetAppFreezingScreenLocked(wtoken, true, force);
4464             Binder.restoreCallingIdentity(origId);
4465         }
4466     }
4467
4468     @Override
4469     public void removeAppToken(IBinder token) {
4470         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4471                 "removeAppToken()")) {
4472             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4473         }
4474
4475         AppWindowToken wtoken = null;
4476         AppWindowToken startingToken = null;
4477         boolean delayed = false;
4478
4479         final long origId = Binder.clearCallingIdentity();
4480         synchronized(mWindowMap) {
4481             WindowToken basewtoken = mTokenMap.remove(token);
4482             if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
4483                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
4484                 delayed = setTokenVisibilityLocked(wtoken, null, false,
4485                         AppTransition.TRANSIT_UNSET, true);
4486                 wtoken.inPendingTransaction = false;
4487                 mOpeningApps.remove(wtoken);
4488                 wtoken.waitingToShow = false;
4489                 if (mClosingApps.contains(wtoken)) {
4490                     delayed = true;
4491                 } else if (mAppTransition.isTransitionSet()) {
4492                     mClosingApps.add(wtoken);
4493                     wtoken.waitingToHide = true;
4494                     delayed = true;
4495                 }
4496                 if (DEBUG_APP_TRANSITIONS) Slog.v(
4497                         TAG, "Removing app " + wtoken + " delayed=" + delayed
4498                         + " animation=" + wtoken.mAppAnimator.animation
4499                         + " animating=" + wtoken.mAppAnimator.animating);
4500                 final Task task = mTaskIdToTask.get(wtoken.groupId);
4501                 DisplayContent displayContent = task.getDisplayContent();
4502                 if (delayed) {
4503                     // set the token aside because it has an active animation to be finished
4504                     if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
4505                             "removeAppToken make exiting: " + wtoken);
4506                     displayContent.mExitingAppTokens.add(wtoken);
4507                 } else {
4508                     // Make sure there is no animation running on this token,
4509                     // so any windows associated with it will be removed as
4510                     // soon as their animations are complete
4511                     wtoken.mAppAnimator.clearAnimation();
4512                     wtoken.mAppAnimator.animating = false;
4513                 }
4514                 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
4515                         "removeAppToken: " + wtoken);
4516
4517                 if (task.removeAppToken(wtoken)) {
4518                     mTaskIdToTask.delete(wtoken.groupId);
4519                 }
4520                 wtoken.removed = true;
4521                 if (wtoken.startingData != null) {
4522                     startingToken = wtoken;
4523                 }
4524                 unsetAppFreezingScreenLocked(wtoken, true, true);
4525                 if (mFocusedApp == wtoken) {
4526                     if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken);
4527                     mFocusedApp = null;
4528                     updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
4529                     mInputMonitor.setFocusedAppLw(null);
4530                 }
4531             } else {
4532                 Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
4533             }
4534
4535             if (!delayed && wtoken != null) {
4536                 wtoken.updateReportedVisibilityLocked();
4537             }
4538         }
4539         Binder.restoreCallingIdentity(origId);
4540
4541         // Will only remove if startingToken non null.
4542         scheduleRemoveStartingWindow(startingToken);
4543     }
4544
4545     void removeStartingWindowTimeout(AppWindowToken wtoken) {
4546         if (wtoken != null) {
4547             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
4548                     ": Remove starting window timeout " + wtoken + (wtoken != null ?
4549                     " startingWindow=" + wtoken.startingWindow : ""));
4550             mH.removeMessages(H.REMOVE_STARTING_TIMEOUT, wtoken);
4551         }
4552     }
4553
4554     void scheduleRemoveStartingWindow(AppWindowToken wtoken) {
4555         if (wtoken != null && wtoken.startingWindow != null) {
4556             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
4557                     ": Schedule remove starting " + wtoken + (wtoken != null ?
4558                     " startingWindow=" + wtoken.startingWindow : ""));
4559             removeStartingWindowTimeout(wtoken);
4560             Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
4561             mH.sendMessage(m);
4562         }
4563     }
4564     private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
4565         final int NW = token.windows.size();
4566         if (NW > 0) {
4567             mWindowsChanged = true;
4568         }
4569         for (int i=0; i<NW; i++) {
4570             WindowState win = token.windows.get(i);
4571             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
4572             win.getWindowList().remove(win);
4573             int j = win.mChildWindows.size();
4574             while (j > 0) {
4575                 j--;
4576                 WindowState cwin = win.mChildWindows.get(j);
4577                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
4578                         "Tmp removing child window " + cwin);
4579                 cwin.getWindowList().remove(cwin);
4580             }
4581         }
4582         return NW > 0;
4583     }
4584
4585     void dumpAppTokensLocked() {
4586         final int numDisplays = mDisplayContents.size();
4587         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4588             final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
4589             Slog.v(TAG, "  Display " + displayContent.getDisplayId());
4590             final ArrayList<Task> tasks = displayContent.getTasks();
4591             int i = displayContent.numTokens();
4592             for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
4593                 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
4594                 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
4595                     final AppWindowToken wtoken = tokens.get(tokenNdx);
4596                     Slog.v(TAG, "  #" + --i + ": " + wtoken.token);
4597                 }
4598             }
4599         }
4600     }
4601
4602     void dumpWindowsLocked() {
4603         int i = 0;
4604         final int numDisplays = mDisplayContents.size();
4605         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4606             final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
4607             for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
4608                 Slog.v(TAG, "  #" + i++ + ": " + windows.get(winNdx));
4609             }
4610         }
4611     }
4612
4613     private int findAppWindowInsertionPointLocked(AppWindowToken target) {
4614         final int taskId = target.groupId;
4615         Task targetTask = mTaskIdToTask.get(taskId);
4616         if (targetTask == null) {
4617             Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId="
4618                     + taskId);
4619             return 0;
4620         }
4621         DisplayContent displayContent = targetTask.getDisplayContent();
4622         if (displayContent == null) {
4623             Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target);
4624             return 0;
4625         }
4626         final WindowList windows = displayContent.getWindowList();
4627         final int NW = windows.size();
4628
4629         boolean found = false;
4630         final ArrayList<Task> tasks = displayContent.getTasks();
4631         for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
4632             final Task task = tasks.get(taskNdx);
4633             if (!found && task.taskId != taskId) {
4634                 continue;
4635             }
4636             AppTokenList tokens = task.mAppTokens;
4637             for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
4638                 final AppWindowToken wtoken = tokens.get(tokenNdx);
4639                 if (!found && wtoken == target) {
4640                     found = true;
4641                 }
4642                 if (found) {
4643                     // Find the first app token below the new position that has
4644                     // a window displayed.
4645                     if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token);
4646                     if (wtoken.sendingToBottom) {
4647                         if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom");
4648                         continue;
4649                     }
4650                     for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
4651                         WindowState win = wtoken.windows.get(i);
4652                         for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
4653                             WindowState cwin = win.mChildWindows.get(j);
4654                             if (cwin.mSubLayer >= 0) {
4655                                 for (int pos = NW - 1; pos >= 0; pos--) {
4656                                     if (windows.get(pos) == cwin) {
4657                                         if (DEBUG_REORDER) Slog.v(TAG,
4658                                                 "Found child win @" + (pos + 1));
4659                                         return pos + 1;
4660                                     }
4661                                 }
4662                             }
4663                         }
4664                         for (int pos = NW - 1; pos >= 0; pos--) {
4665                             if (windows.get(pos) == win) {
4666                                 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1));
4667                                 return pos + 1;
4668                             }
4669                         }
4670                     }
4671                 }
4672             }
4673         }
4674         // Never put an app window underneath wallpaper.
4675         for (int pos = NW - 1; pos >= 0; pos--) {
4676             if (windows.get(pos).mIsWallpaper) {
4677                 if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos);
4678                 return pos + 1;
4679             }
4680         }
4681         return 0;
4682     }
4683
4684     private final int reAddWindowLocked(int index, WindowState win) {
4685         final WindowList windows = win.getWindowList();
4686         final int NCW = win.mChildWindows.size();
4687         boolean added = false;
4688         for (int j=0; j<NCW; j++) {
4689             WindowState cwin = win.mChildWindows.get(j);
4690             if (!added && cwin.mSubLayer >= 0) {
4691                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
4692                         + index + ": " + cwin);
4693                 win.mRebuilding = false;
4694                 windows.add(index, win);
4695                 index++;
4696                 added = true;
4697             }
4698             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4699                     + index + ": " + cwin);
4700             cwin.mRebuilding = false;
4701             windows.add(index, cwin);
4702             index++;
4703         }
4704         if (!added) {
4705             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4706                     + index + ": " + win);
4707             win.mRebuilding = false;
4708             windows.add(index, win);
4709             index++;
4710         }
4711         mWindowsChanged = true;
4712         return index;
4713     }
4714
4715     private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index,
4716                                             WindowToken token) {
4717         final int NW = token.windows.size();
4718         for (int i=0; i<NW; i++) {
4719             final WindowState win = token.windows.get(i);
4720             if (win.mDisplayContent == displayContent) {
4721                 index = reAddWindowLocked(index, win);
4722             }
4723         }
4724         return index;
4725     }
4726
4727     void moveStackWindowsLocked(TaskStack stack) {
4728         DisplayContent displayContent = stack.getDisplayContent();
4729
4730         // First remove all of the windows from the list.
4731         final ArrayList<Task> tasks = stack.getTasks();
4732         final int numTasks = tasks.size();
4733         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4734             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
4735             final int numTokens = tokens.size();
4736             for (int tokenNdx = numTokens - 1; tokenNdx >= 0; --tokenNdx) {
4737                 tmpRemoveAppWindowsLocked(tokens.get(tokenNdx));
4738             }
4739         }
4740
4741         // And now add them back at the correct place.
4742         // Where to start adding?
4743         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4744             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
4745             int pos = findAppWindowInsertionPointLocked(tokens.get(0));
4746             final int numTokens = tokens.size();
4747             for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4748                 final AppWindowToken wtoken = tokens.get(tokenNdx);
4749                 if (wtoken != null) {
4750                     final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
4751                     if (newPos != pos) {
4752                         displayContent.layoutNeeded = true;
4753                     }
4754                     pos = newPos;
4755                 }
4756             }
4757         }
4758
4759         if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4760                 false /*updateInputWindows*/)) {
4761             assignLayersLocked(displayContent.getWindowList());
4762         }
4763
4764         mInputMonitor.setUpdateInputWindowsNeededLw();
4765         performLayoutAndPlaceSurfacesLocked();
4766         mInputMonitor.updateInputWindowsLw(false /*force*/);
4767
4768         //dump();
4769     }
4770
4771     public void moveTaskToTop(int taskId) {
4772         final long origId = Binder.clearCallingIdentity();
4773         try {
4774             synchronized(mWindowMap) {
4775                 Task task = mTaskIdToTask.get(taskId);
4776                 if (task == null) {
4777                     // Normal behavior, addAppToken will be called next and task will be created.
4778                     return;
4779                 }
4780                 final TaskStack stack = task.mStack;
4781                 final DisplayContent displayContent = task.getDisplayContent();
4782                 final boolean isHomeStackTask = stack.isHomeStack();
4783                 if (isHomeStackTask != displayContent.homeOnTop()) {
4784                     // First move the stack itself.
4785                     displayContent.moveHomeStackBox(isHomeStackTask);
4786                 }
4787                 stack.moveTaskToTop(task);
4788                 displayContent.moveStack(stack, true);
4789             }
4790         } finally {
4791             Binder.restoreCallingIdentity(origId);
4792         }
4793     }
4794
4795     public void moveTaskToBottom(int taskId) {
4796         final long origId = Binder.clearCallingIdentity();
4797         try {
4798             synchronized(mWindowMap) {
4799                 Task task = mTaskIdToTask.get(taskId);
4800                 if (task == null) {
4801                     Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId
4802                             + " not found in mTaskIdToTask");
4803                     return;
4804                 }
4805                 final TaskStack stack = task.mStack;
4806                 stack.moveTaskToBottom(task);
4807                 moveStackWindowsLocked(stack);
4808             }
4809         } finally {
4810             Binder.restoreCallingIdentity(origId);
4811         }
4812     }
4813
4814     /**
4815      * Create a new TaskStack and place it next to an existing stack.
4816      * @param stackId The unique identifier of the new stack.
4817      * @param relativeStackBoxId The existing stack that this stack goes before or after.
4818      * @param position One of:
4819      *      {@link StackBox#TASK_STACK_GOES_BEFORE}
4820      *      {@link StackBox#TASK_STACK_GOES_AFTER}
4821      *      {@link StackBox#TASK_STACK_GOES_ABOVE}
4822      *      {@link StackBox#TASK_STACK_GOES_BELOW}
4823      *      {@link StackBox#TASK_STACK_GOES_UNDER}
4824      *      {@link StackBox#TASK_STACK_GOES_OVER}
4825      * @param weight Relative weight for determining how big to make the new TaskStack.
4826      */
4827     public void createStack(int stackId, int relativeStackBoxId, int position, float weight) {
4828         synchronized (mWindowMap) {
4829             if (position <= StackBox.TASK_STACK_GOES_BELOW &&
4830                     (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX)) {
4831                 throw new IllegalArgumentException(
4832                         "createStack: weight must be between " + STACK_WEIGHT_MIN + " and " +
4833                         STACK_WEIGHT_MAX + ", weight=" + weight);
4834             }
4835             final int numDisplays = mDisplayContents.size();
4836             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4837                 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
4838                 TaskStack stack = displayContent.createStack(stackId, relativeStackBoxId, position,
4839                         weight);
4840                 if (stack != null) {
4841                     mStackIdToStack.put(stackId, stack);
4842                     displayContent.moveStack(stack, true);
4843                     performLayoutAndPlaceSurfacesLocked();
4844                     return;
4845                 }
4846             }
4847             Slog.e(TAG, "createStack: Unable to find relativeStackBoxId=" + relativeStackBoxId);
4848         }
4849     }
4850
4851     public int removeStack(int stackId) {
4852         synchronized (mWindowMap) {
4853             final TaskStack stack = mStackIdToStack.get(stackId);
4854             if (stack != null) {
4855                 mStackIdToStack.delete(stackId);
4856                 int nextStackId = stack.remove();
4857                 stack.getDisplayContent().layoutNeeded = true;
4858                 requestTraversalLocked();
4859                 return nextStackId;
4860             }
4861             if (DEBUG_STACK) Slog.i(TAG, "removeStack: could not find stackId=" + stackId);
4862         }
4863         return HOME_STACK_ID;
4864     }
4865
4866     public void removeTask(int taskId) {
4867         synchronized (mWindowMap) {
4868             Task task = mTaskIdToTask.get(taskId);
4869             if (task == null) {
4870                 if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId);
4871                 return;
4872             }
4873             final TaskStack stack = task.mStack;
4874             stack.removeTask(task);
4875             stack.getDisplayContent().layoutNeeded = true;
4876         }
4877     }
4878
4879     public void addTask(int taskId, int stackId, boolean toTop) {
4880         synchronized (mWindowMap) {
4881             Task task = mTaskIdToTask.get(taskId);
4882             if (task == null) {
4883                 return;
4884             }
4885             TaskStack stack = mStackIdToStack.get(stackId);
4886             stack.addTask(task, toTop);
4887             final DisplayContent displayContent = stack.getDisplayContent();
4888             displayContent.layoutNeeded = true;
4889             performLayoutAndPlaceSurfacesLocked();
4890         }
4891     }
4892
4893     public void resizeStackBox(int stackBoxId, float weight) {
4894         if (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX) {
4895             throw new IllegalArgumentException(
4896                     "resizeStack: weight must be between " + STACK_WEIGHT_MIN + " and " +
4897                     STACK_WEIGHT_MAX + ", weight=" + weight);
4898         }
4899         synchronized (mWindowMap) {
4900             final int numDisplays = mDisplayContents.size();
4901             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4902                 if (mDisplayContents.valueAt(displayNdx).resizeStack(stackBoxId, weight)) {
4903                     performLayoutAndPlaceSurfacesLocked();
4904                     return;
4905                 }
4906             }
4907         }
4908         throw new IllegalArgumentException("resizeStack: stackBoxId " + stackBoxId
4909                 + " not found.");
4910     }
4911
4912     public ArrayList<StackBoxInfo> getStackBoxInfos() {
4913         synchronized(mWindowMap) {
4914             return getDefaultDisplayContentLocked().getStackBoxInfos();
4915         }
4916     }
4917
4918     public Rect getStackBounds(int stackId) {
4919         final int numDisplays = mDisplayContents.size();
4920         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4921             Rect bounds = mDisplayContents.valueAt(displayNdx).getStackBounds(stackId);
4922             if (bounds != null) {
4923                 return bounds;
4924             }
4925         }
4926         return null;
4927     }
4928
4929     // -------------------------------------------------------------
4930     // Misc IWindowSession methods
4931     // -------------------------------------------------------------
4932
4933     @Override
4934     public void startFreezingScreen(int exitAnim, int enterAnim) {
4935         if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
4936                 "startFreezingScreen()")) {
4937             throw new SecurityException("Requires FREEZE_SCREEN permission");
4938         }
4939
4940         synchronized(mWindowMap) {
4941             if (!mClientFreezingScreen) {
4942                 mClientFreezingScreen = true;
4943                 final long origId = Binder.clearCallingIdentity();
4944                 try {
4945                     startFreezingDisplayLocked(false, exitAnim, enterAnim);
4946                     mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
4947                     mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
4948                 } finally {
4949                     Binder.restoreCallingIdentity(origId);
4950                 }
4951             }
4952         }
4953     }
4954
4955     @Override
4956     public void stopFreezingScreen() {
4957         if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
4958                 "stopFreezingScreen()")) {
4959             throw new SecurityException("Requires FREEZE_SCREEN permission");
4960         }
4961
4962         synchronized(mWindowMap) {
4963             if (mClientFreezingScreen) {
4964                 mClientFreezingScreen = false;
4965                 mLastFinishedFreezeSource = "client";
4966                 final long origId = Binder.clearCallingIdentity();
4967                 try {
4968                     stopFreezingDisplayLocked();
4969                 } finally {
4970                     Binder.restoreCallingIdentity(origId);
4971                 }
4972             }
4973         }
4974     }
4975
4976     @Override
4977     public void disableKeyguard(IBinder token, String tag) {
4978         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
4979             != PackageManager.PERMISSION_GRANTED) {
4980             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4981         }
4982
4983         mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
4984                 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
4985     }
4986
4987     @Override
4988     public void reenableKeyguard(IBinder token) {
4989         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
4990             != PackageManager.PERMISSION_GRANTED) {
4991             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4992         }
4993
4994         mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
4995                 KeyguardDisableHandler.KEYGUARD_REENABLE, token));
4996     }
4997
4998     /**
4999      * @see android.app.KeyguardManager#exitKeyguardSecurely
5000      */
5001     @Override
5002     public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
5003         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5004             != PackageManager.PERMISSION_GRANTED) {
5005             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5006         }
5007         mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
5008             @Override
5009             public void onKeyguardExitResult(boolean success) {
5010                 try {
5011                     callback.onKeyguardExitResult(success);
5012                 } catch (RemoteException e) {
5013                     // Client has died, we don't care.
5014                 }
5015             }
5016         });
5017     }
5018
5019     @Override
5020     public boolean inKeyguardRestrictedInputMode() {
5021         return mPolicy.inKeyguardRestrictedKeyInputMode();
5022     }
5023
5024     @Override
5025     public boolean isKeyguardLocked() {
5026         return mPolicy.isKeyguardLocked();
5027     }
5028
5029     @Override
5030     public boolean isKeyguardSecure() {
5031         return mPolicy.isKeyguardSecure();
5032     }
5033
5034     @Override
5035     public void dismissKeyguard() {
5036         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5037                 != PackageManager.PERMISSION_GRANTED) {
5038             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5039         }
5040         synchronized(mWindowMap) {
5041             mPolicy.dismissKeyguardLw();
5042         }
5043     }
5044
5045     @Override
5046     public void closeSystemDialogs(String reason) {
5047         synchronized(mWindowMap) {
5048             final int numDisplays = mDisplayContents.size();
5049             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5050                 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5051                 final int numWindows = windows.size();
5052                 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5053                     final WindowState w = windows.get(winNdx);
5054                     if (w.mHasSurface) {
5055                         try {
5056                             w.mClient.closeSystemDialogs(reason);
5057                         } catch (RemoteException e) {
5058                         }
5059                     }
5060                 }
5061             }
5062         }
5063     }
5064
5065     static float fixScale(float scale) {
5066         if (scale < 0) scale = 0;
5067         else if (scale > 20) scale = 20;
5068         return Math.abs(scale);
5069     }
5070
5071     @Override
5072     public void setAnimationScale(int which, float scale) {
5073         if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5074                 "setAnimationScale()")) {
5075             throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5076         }
5077
5078         scale = fixScale(scale);
5079         switch (which) {
5080             case 0: mWindowAnimationScale = scale; break;
5081             case 1: mTransitionAnimationScale = scale; break;
5082             case 2: mAnimatorDurationScale = scale; break;
5083         }
5084
5085         // Persist setting
5086         mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5087     }
5088
5089     @Override
5090     public void setAnimationScales(float[] scales) {
5091         if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5092                 "setAnimationScale()")) {
5093             throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5094         }
5095
5096         if (scales != null) {
5097             if (scales.length >= 1) {
5098                 mWindowAnimationScale = fixScale(scales[0]);
5099             }
5100             if (scales.length >= 2) {
5101                 mTransitionAnimationScale = fixScale(scales[1]);
5102             }
5103             if (scales.length >= 3) {
5104                 setAnimatorDurationScale(fixScale(scales[2]));
5105             }
5106         }
5107
5108         // Persist setting
5109         mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5110     }
5111
5112     private void setAnimatorDurationScale(float scale) {
5113         mAnimatorDurationScale = scale;
5114         ValueAnimator.setDurationScale(scale);
5115     }
5116
5117     @Override
5118     public float getAnimationScale(int which) {
5119         switch (which) {
5120             case 0: return mWindowAnimationScale;
5121             case 1: return mTransitionAnimationScale;
5122             case 2: return mAnimatorDurationScale;
5123         }
5124         return 0;
5125     }
5126
5127     @Override
5128     public float[] getAnimationScales() {
5129         return new float[] { mWindowAnimationScale, mTransitionAnimationScale,
5130                 mAnimatorDurationScale };
5131     }
5132
5133     @Override
5134     public void registerPointerEventListener(PointerEventListener listener) {
5135         mPointerEventDispatcher.registerInputEventListener(listener);
5136     }
5137
5138     @Override
5139     public void unregisterPointerEventListener(PointerEventListener listener) {
5140         mPointerEventDispatcher.unregisterInputEventListener(listener);
5141     }
5142
5143     // Called by window manager policy. Not exposed externally.
5144     @Override
5145     public int getLidState() {
5146         int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5147                 InputManagerService.SW_LID);
5148         if (sw > 0) {
5149             // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5150             return LID_CLOSED;
5151         } else if (sw == 0) {
5152             // Switch state: AKEY_STATE_UP.
5153             return LID_OPEN;
5154         } else {
5155             // Switch state: AKEY_STATE_UNKNOWN.
5156             return LID_ABSENT;
5157         }
5158     }
5159
5160     // Called by window manager policy.  Not exposed externally.
5161     @Override
5162     public void switchKeyboardLayout(int deviceId, int direction) {
5163         mInputManager.switchKeyboardLayout(deviceId, direction);
5164     }
5165
5166     // Called by window manager policy.  Not exposed externally.
5167     @Override
5168     public void shutdown(boolean confirm) {
5169         ShutdownThread.shutdown(mContext, confirm);
5170     }
5171
5172     // Called by window manager policy.  Not exposed externally.
5173     @Override
5174     public void rebootSafeMode(boolean confirm) {
5175         ShutdownThread.rebootSafeMode(mContext, confirm);
5176     }
5177
5178     @Override
5179     public void setInputFilter(IInputFilter filter) {
5180         if (!checkCallingPermission(android.Manifest.permission.FILTER_EVENTS, "setInputFilter()")) {
5181             throw new SecurityException("Requires FILTER_EVENTS permission");
5182         }
5183         mInputManager.setInputFilter(filter);
5184     }
5185
5186     @Override
5187     public void setTouchExplorationEnabled(boolean enabled) {
5188         mPolicy.setTouchExplorationEnabled(enabled);
5189     }
5190
5191     public void setCurrentUser(final int newUserId) {
5192         synchronized (mWindowMap) {
5193             int oldUserId = mCurrentUserId;
5194             mCurrentUserId = newUserId;
5195             mAppTransition.setCurrentUser(newUserId);
5196             mPolicy.setCurrentUserLw(newUserId);
5197
5198             // Hide windows that should not be seen by the new user.
5199             final int numDisplays = mDisplayContents.size();
5200             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5201                 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
5202                 displayContent.switchUserStacks(oldUserId, newUserId);
5203                 rebuildAppWindowListLocked(displayContent);
5204             }
5205             performLayoutAndPlaceSurfacesLocked();
5206         }
5207     }
5208
5209     public void enableScreenAfterBoot() {
5210         synchronized(mWindowMap) {
5211             if (DEBUG_BOOT) {
5212                 RuntimeException here = new RuntimeException("here");
5213                 here.fillInStackTrace();
5214                 Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
5215                         + " mForceDisplayEnabled=" + mForceDisplayEnabled
5216                         + " mShowingBootMessages=" + mShowingBootMessages
5217                         + " mSystemBooted=" + mSystemBooted, here);
5218             }
5219             if (mSystemBooted) {
5220                 return;
5221             }
5222             mSystemBooted = true;
5223             hideBootMessagesLocked();
5224             // If the screen still doesn't come up after 30 seconds, give
5225             // up and turn it on.
5226             mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
5227         }
5228
5229         mPolicy.systemBooted();
5230
5231         performEnableScreen();
5232     }
5233
5234     void enableScreenIfNeededLocked() {
5235         if (DEBUG_BOOT) {
5236             RuntimeException here = new RuntimeException("here");
5237             here.fillInStackTrace();
5238             Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
5239                     + " mForceDisplayEnabled=" + mForceDisplayEnabled
5240                     + " mShowingBootMessages=" + mShowingBootMessages
5241                     + " mSystemBooted=" + mSystemBooted, here);
5242         }
5243         if (mDisplayEnabled) {
5244             return;
5245         }
5246         if (!mSystemBooted && !mShowingBootMessages) {
5247             return;
5248         }
5249         mH.sendEmptyMessage(H.ENABLE_SCREEN);
5250     }
5251
5252     public void performBootTimeout() {
5253         synchronized(mWindowMap) {
5254             if (mDisplayEnabled || mHeadless) {
5255                 return;
5256             }
5257             Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled");
5258             mForceDisplayEnabled = true;
5259         }
5260         performEnableScreen();
5261     }
5262
5263     public void performEnableScreen() {
5264         synchronized(mWindowMap) {
5265             if (DEBUG_BOOT) {
5266                 RuntimeException here = new RuntimeException("here");
5267                 here.fillInStackTrace();
5268                 Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
5269                         + " mForceDisplayEnabled=" + mForceDisplayEnabled
5270                         + " mShowingBootMessages=" + mShowingBootMessages
5271                         + " mSystemBooted=" + mSystemBooted
5272                         + " mOnlyCore=" + mOnlyCore, here);
5273             }
5274             if (mDisplayEnabled) {
5275                 return;
5276             }
5277             if (!mSystemBooted && !mShowingBootMessages) {
5278                 return;
5279             }
5280
5281             if (!mForceDisplayEnabled) {
5282                 // Don't enable the screen until all existing windows
5283                 // have been drawn.
5284                 boolean haveBootMsg = false;
5285                 boolean haveApp = false;
5286                 // if the wallpaper service is disabled on the device, we're never going to have
5287                 // wallpaper, don't bother waiting for it
5288                 boolean haveWallpaper = false;
5289                 boolean wallpaperEnabled = mContext.getResources().getBoolean(
5290                         com.android.internal.R.bool.config_enableWallpaperService)
5291                         && !mOnlyCore;
5292                 boolean haveKeyguard = true;
5293                 // TODO(multidisplay): Expand to all displays?
5294                 final WindowList windows = getDefaultWindowListLocked();
5295                 final int N = windows.size();
5296                 for (int i=0; i<N; i++) {
5297                     WindowState w = windows.get(i);
5298                     if (w.mAttrs.type == TYPE_KEYGUARD) {
5299                         // Only if there is a keyguard attached to the window manager
5300                         // will we consider ourselves as having a keyguard.  If it
5301                         // isn't attached, we don't know if it wants to be shown or
5302                         // hidden.  If it is attached, we will say we have a keyguard
5303                         // if the window doesn't want to be visible, because in that
5304                         // case it explicitly doesn't want to be shown so we should
5305                         // not delay turning the screen on for it.
5306                         boolean vis = w.mViewVisibility == View.VISIBLE
5307                                 && w.mPolicyVisibility;
5308                         haveKeyguard = !vis;
5309                     }
5310                     if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
5311                         return;
5312                     }
5313                     if (w.isDrawnLw()) {
5314                         if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
5315                             haveBootMsg = true;
5316                         } else if (w.mAttrs.type == TYPE_APPLICATION) {
5317                             haveApp = true;
5318                         } else if (w.mAttrs.type == TYPE_WALLPAPER) {
5319                             haveWallpaper = true;
5320                         } else if (w.mAttrs.type == TYPE_KEYGUARD) {
5321                             haveKeyguard = true;
5322                         }
5323                     }
5324                 }
5325
5326                 if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
5327                     Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
5328                             + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
5329                             + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
5330                             + " haveKeyguard=" + haveKeyguard);
5331                 }
5332
5333                 // If we are turning on the screen to show the boot message,
5334                 // don't do it until the boot message is actually displayed.
5335                 if (!mSystemBooted && !haveBootMsg) {
5336                     return;
5337                 }
5338
5339                 // If we are turning on the screen after the boot is completed
5340                 // normally, don't do so until we have the application and
5341                 // wallpaper.
5342                 if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
5343                         (wallpaperEnabled && !haveWallpaper))) {
5344                     return;
5345                 }
5346             }
5347
5348             mDisplayEnabled = true;
5349             if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
5350             if (false) {
5351                 StringWriter sw = new StringWriter();
5352                 PrintWriter pw = new FastPrintWriter(sw, false, 1024);
5353                 this.dump(null, pw, null);
5354                 pw.flush();
5355                 Slog.i(TAG, sw.toString());
5356             }
5357             try {
5358                 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5359                 if (surfaceFlinger != null) {
5360                     //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5361                     Parcel data = Parcel.obtain();
5362                     data.writeInterfaceToken("android.ui.ISurfaceComposer");
5363                     surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5364                                             data, null, 0);
5365                     data.recycle();
5366                 }
5367             } catch (RemoteException ex) {
5368                 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
5369             }
5370
5371             // Enable input dispatch.
5372             mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5373         }
5374
5375         mPolicy.enableScreenAfterBoot();
5376
5377         // Make sure the last requested orientation has been applied.
5378         updateRotationUnchecked(false, false);
5379     }
5380
5381     public void showBootMessage(final CharSequence msg, final boolean always) {
5382         boolean first = false;
5383         synchronized(mWindowMap) {
5384             if (DEBUG_BOOT) {
5385                 RuntimeException here = new RuntimeException("here");
5386                 here.fillInStackTrace();
5387                 Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always
5388                         + " mAllowBootMessages=" + mAllowBootMessages
5389                         + " mShowingBootMessages=" + mShowingBootMessages
5390                         + " mSystemBooted=" + mSystemBooted, here);
5391             }
5392             if (!mAllowBootMessages) {
5393                 return;
5394             }
5395             if (!mShowingBootMessages) {
5396                 if (!always) {
5397                     return;
5398                 }
5399                 first = true;
5400             }
5401             if (mSystemBooted) {
5402                 return;
5403             }
5404             mShowingBootMessages = true;
5405             mPolicy.showBootMessage(msg, always);
5406         }
5407         if (first) {
5408             performEnableScreen();
5409         }
5410     }
5411
5412     public void hideBootMessagesLocked() {
5413         if (DEBUG_BOOT) {
5414             RuntimeException here = new RuntimeException("here");
5415             here.fillInStackTrace();
5416             Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
5417                     + " mForceDisplayEnabled=" + mForceDisplayEnabled
5418                     + " mShowingBootMessages=" + mShowingBootMessages
5419                     + " mSystemBooted=" + mSystemBooted, here);
5420         }
5421         if (mShowingBootMessages) {
5422             mShowingBootMessages = false;
5423             mPolicy.hideBootMessages();
5424         }
5425     }
5426
5427     @Override
5428     public void setInTouchMode(boolean mode) {
5429         synchronized(mWindowMap) {
5430             mInTouchMode = mode;
5431         }
5432     }
5433
5434     // TODO: more accounting of which pid(s) turned it on, keep count,
5435     // only allow disables from pids which have count on, etc.
5436     @Override
5437     public void showStrictModeViolation(boolean on) {
5438         if (mHeadless) return;
5439         int pid = Binder.getCallingPid();
5440         mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
5441     }
5442
5443     private void showStrictModeViolation(int arg, int pid) {
5444         final boolean on = arg != 0;
5445         synchronized(mWindowMap) {
5446             // Ignoring requests to enable the red border from clients
5447             // which aren't on screen.  (e.g. Broadcast Receivers in
5448             // the background..)
5449             if (on) {
5450                 boolean isVisible = false;
5451                 final int numDisplays = mDisplayContents.size();
5452                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5453                     final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5454                     final int numWindows = windows.size();
5455                     for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5456                         final WindowState ws = windows.get(winNdx);
5457                         if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
5458                             isVisible = true;
5459                             break;
5460                         }
5461                     }
5462                 }
5463                 if (!isVisible) {
5464                     return;
5465                 }
5466             }
5467
5468             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5469                     ">>> OPEN TRANSACTION showStrictModeViolation");
5470             SurfaceControl.openTransaction();
5471             try {
5472                 // TODO(multi-display): support multiple displays
5473                 if (mStrictModeFlash == null) {
5474                     mStrictModeFlash = new StrictModeFlash(
5475                             getDefaultDisplayContentLocked().getDisplay(), mFxSession);
5476                 }
5477                 mStrictModeFlash.setVisibility(on);
5478             } finally {
5479                 SurfaceControl.closeTransaction();
5480                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5481                         "<<< CLOSE TRANSACTION showStrictModeViolation");
5482             }
5483         }
5484     }
5485
5486     @Override
5487     public void setStrictModeVisualIndicatorPreference(String value) {
5488         SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
5489     }
5490
5491     /**
5492      * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
5493      * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
5494      * of the target image.
5495      *
5496      * @param displayId the Display to take a screenshot of.
5497      * @param width the width of the target bitmap
5498      * @param height the height of the target bitmap
5499      * @param force565 if true the returned bitmap will be RGB_565, otherwise it
5500      *                 will be the same config as the surface
5501      */
5502     @Override
5503     public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
5504             int height, boolean force565) {
5505         if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5506                 "screenshotApplications()")) {
5507             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
5508         }
5509
5510         Bitmap rawss = null;
5511
5512         int maxLayer = 0;
5513         final Rect frame = new Rect();
5514
5515         float scale = 0;
5516         int dw, dh;
5517         int rot = Surface.ROTATION_0;
5518
5519         boolean screenshotReady;
5520         int minLayer;
5521         if (appToken == null) {
5522             screenshotReady = true;
5523             minLayer = 0;
5524         } else {
5525             screenshotReady = false;
5526             minLayer = Integer.MAX_VALUE;
5527         }
5528
5529         int retryCount = 0;
5530         WindowState appWin = null;
5531
5532         do {
5533             if (retryCount++ > 0) {
5534                 try {
5535                     Thread.sleep(100);
5536                 } catch (InterruptedException e) {
5537                 }
5538             }
5539             synchronized(mWindowMap) {
5540                 final DisplayContent displayContent = getDisplayContentLocked(displayId);
5541                 if (displayContent == null) {
5542                     return null;
5543                 }
5544                 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5545                 dw = displayInfo.logicalWidth;
5546                 dh = displayInfo.logicalHeight;
5547
5548                 int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION)
5549                         * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
5550                 aboveAppLayer += TYPE_LAYER_MULTIPLIER;
5551
5552                 boolean isImeTarget = mInputMethodTarget != null
5553                         && mInputMethodTarget.mAppToken != null
5554                         && mInputMethodTarget.mAppToken.appToken != null
5555                         && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
5556
5557                 // Figure out the part of the screen that is actually the app.
5558                 boolean including = false;
5559                 appWin = null;
5560                 final WindowList windows = displayContent.getWindowList();
5561                 final Rect stackBounds = new Rect();
5562                 for (int i = windows.size() - 1; i >= 0; i--) {
5563                     WindowState ws = windows.get(i);
5564                     if (!ws.mHasSurface) {
5565                         continue;
5566                     }
5567                     if (ws.mLayer >= aboveAppLayer) {
5568                         continue;
5569                     }
5570                     // When we will skip windows: when we are not including
5571                     // ones behind a window we didn't skip, and we are actually
5572                     // taking a screenshot of a specific app.
5573                     if (!including && appToken != null) {
5574                         // Also, we can possibly skip this window if it is not
5575                         // an IME target or the application for the screenshot
5576                         // is not the current IME target.
5577                         if (!ws.mIsImWindow || !isImeTarget) {
5578                             // And finally, this window is of no interest if it
5579                             // is not associated with the screenshot app.
5580                             if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
5581                                 continue;
5582                             }
5583                             appWin = ws;
5584                             stackBounds.set(ws.getStackBounds());
5585                         }
5586                     }
5587
5588                     // We keep on including windows until we go past a full-screen
5589                     // window.
5590                     boolean fullscreen = ws.isFullscreen(dw, dh);
5591                     including = !ws.mIsImWindow && !fullscreen;
5592
5593                     final WindowStateAnimator winAnim = ws.mWinAnimator;
5594                     if (maxLayer < winAnim.mSurfaceLayer) {
5595                         maxLayer = winAnim.mSurfaceLayer;
5596                     }
5597                     if (minLayer > winAnim.mSurfaceLayer) {
5598                         minLayer = winAnim.mSurfaceLayer;
5599                     }
5600
5601                     // Don't include wallpaper in bounds calculation
5602                     if (!ws.mIsWallpaper) {
5603                         final Rect wf = ws.mFrame;
5604                         final Rect cr = ws.mContentInsets;
5605                         int left = wf.left + cr.left;
5606                         int top = wf.top + cr.top;
5607                         int right = wf.right - cr.right;
5608                         int bottom = wf.bottom - cr.bottom;
5609                         frame.union(left, top, right, bottom);
5610                         frame.intersect(stackBounds);
5611                     }
5612
5613                     if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
5614                             ws.isDisplayedLw()) {
5615                         screenshotReady = true;
5616                     }
5617
5618                     if (fullscreen) {
5619                         // No point in continuing down through windows.
5620                         break;
5621                     }
5622                 }
5623
5624                 if (appToken != null && appWin == null) {
5625                     // Can't find a window to snapshot.
5626                     if (DEBUG_SCREENSHOT) Slog.i(TAG,
5627                             "Screenshot: Couldn't find a surface matching " + appToken);
5628                     return null;
5629                 }
5630                 if (!screenshotReady) {
5631                     // Delay and hope that window gets drawn.
5632                     if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken
5633                             + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState);
5634                     continue;
5635                 }
5636
5637                 // Constrain frame to the screen size.
5638                 frame.intersect(0, 0, dw, dh);
5639
5640                 if (frame.isEmpty() || maxLayer == 0) {
5641                     if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
5642                             + ": returning null frame=" + frame.toShortString() + " maxLayer="
5643                             + maxLayer);
5644                     return null;
5645                 }
5646
5647                 // The screenshot API does not apply the current screen rotation.
5648                 rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
5649                 int fw = frame.width();
5650                 int fh = frame.height();
5651
5652                 // Constrain thumbnail to smaller of screen width or height. Assumes aspect
5653                 // of thumbnail is the same as the screen (in landscape) or square.
5654                 scale = Math.max(width / (float) fw, height / (float) fh);
5655                 /*
5656                 float targetWidthScale = width / (float) fw;
5657                 float targetHeightScale = height / (float) fh;
5658                 if (fw <= fh) {
5659                     scale = targetWidthScale;
5660                     // If aspect of thumbnail is the same as the screen (in landscape),
5661                     // select the slightly larger value so we fill the entire bitmap
5662                     if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) {
5663                         scale = targetHeightScale;
5664                     }
5665                 } else {
5666                     scale = targetHeightScale;
5667                     // If aspect of thumbnail is the same as the screen (in landscape),
5668                     // select the slightly larger value so we fill the entire bitmap
5669                     if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) {
5670                         scale = targetWidthScale;
5671                     }
5672                 }
5673                 */
5674
5675                 // The screen shot will contain the entire screen.
5676                 dw = (int)(dw*scale);
5677                 dh = (int)(dh*scale);
5678                 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
5679                     int tmp = dw;
5680                     dw = dh;
5681                     dh = tmp;
5682                     rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
5683                 }
5684                 if (DEBUG_SCREENSHOT) {
5685                     Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
5686                             + maxLayer + " appToken=" + appToken);
5687                     for (int i = 0; i < windows.size(); i++) {
5688                         WindowState win = windows.get(i);
5689                         Slog.i(TAG, win + ": " + win.mLayer
5690                                 + " animLayer=" + win.mWinAnimator.mAnimLayer
5691                                 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
5692                     }
5693                 }
5694                 rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer);
5695             }
5696         } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES);
5697         if (retryCount > MAX_SCREENSHOT_RETRIES)  Slog.i(TAG, "Screenshot max retries " +
5698                 retryCount + " of " + appToken + " appWin=" + (appWin == null ?
5699                         "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState)));
5700
5701         if (rawss == null) {
5702             Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
5703                     + ") to layer " + maxLayer);
5704             return null;
5705         }
5706
5707         Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig());
5708         frame.scale(scale);
5709         Matrix matrix = new Matrix();
5710         ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
5711         // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left
5712         matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top));
5713         Canvas canvas = new Canvas(bm);
5714         canvas.drawColor(0xFF000000);
5715         canvas.drawBitmap(rawss, matrix, null);
5716         canvas.setBitmap(null);
5717
5718         if (true || DEBUG_SCREENSHOT) {
5719             // TEST IF IT's ALL BLACK
5720             int[] buffer = new int[bm.getWidth() * bm.getHeight()];
5721             bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
5722             boolean allBlack = true;
5723             final int firstColor = buffer[0];
5724             for (int i = 0; i < buffer.length; i++) {
5725                 if (buffer[i] != firstColor) {
5726                     allBlack = false;
5727                     break;
5728                 }
5729             }
5730             if (allBlack) {
5731                 Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" +
5732                         Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
5733                         (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") +
5734                         " minLayer=" + minLayer + " maxLayer=" + maxLayer);
5735             }
5736         }
5737
5738         rawss.recycle();
5739         return bm;
5740     }
5741
5742     /**
5743      * Freeze rotation changes.  (Enable "rotation lock".)
5744      * Persists across reboots.
5745      * @param rotation The desired rotation to freeze to, or -1 to use the
5746      * current rotation.
5747      */
5748     @Override
5749     public void freezeRotation(int rotation) {
5750         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5751                 "freezeRotation()")) {
5752             throw new SecurityException("Requires SET_ORIENTATION permission");
5753         }
5754         if (rotation < -1 || rotation > Surface.ROTATION_270) {
5755             throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
5756                     + "rotation constant.");
5757         }
5758
5759         if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
5760
5761         long origId = Binder.clearCallingIdentity();
5762         try {
5763             mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
5764                     rotation == -1 ? mRotation : rotation);
5765         } finally {
5766             Binder.restoreCallingIdentity(origId);
5767         }
5768
5769         updateRotationUnchecked(false, false);
5770     }
5771
5772     /**
5773      * Thaw rotation changes.  (Disable "rotation lock".)
5774      * Persists across reboots.
5775      */
5776     @Override
5777     public void thawRotation() {
5778         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5779                 "thawRotation()")) {
5780             throw new SecurityException("Requires SET_ORIENTATION permission");
5781         }
5782
5783         if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
5784
5785         long origId = Binder.clearCallingIdentity();
5786         try {
5787             mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
5788                     777); // rot not used
5789         } finally {
5790             Binder.restoreCallingIdentity(origId);
5791         }
5792
5793         updateRotationUnchecked(false, false);
5794     }
5795
5796     /**
5797      * Recalculate the current rotation.
5798      *
5799      * Called by the window manager policy whenever the state of the system changes
5800      * such that the current rotation might need to be updated, such as when the
5801      * device is docked or rotated into a new posture.
5802      */
5803     @Override
5804     public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
5805         updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
5806     }
5807
5808     /**
5809      * Temporarily pauses rotation changes until resumed.
5810      *
5811      * This can be used to prevent rotation changes from occurring while the user is
5812      * performing certain operations, such as drag and drop.
5813      *
5814      * This call nests and must be matched by an equal number of calls to
5815      * {@link #resumeRotationLocked}.
5816      */
5817     void pauseRotationLocked() {
5818         mDeferredRotationPauseCount += 1;
5819     }
5820
5821     /**
5822      * Resumes normal rotation changes after being paused.
5823      */
5824     void resumeRotationLocked() {
5825         if (mDeferredRotationPauseCount > 0) {
5826             mDeferredRotationPauseCount -= 1;
5827             if (mDeferredRotationPauseCount == 0) {
5828                 boolean changed = updateRotationUncheckedLocked(false);
5829                 if (changed) {
5830                     mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
5831                 }
5832             }
5833         }
5834     }
5835
5836     public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
5837         if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
5838                    + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
5839
5840         long origId = Binder.clearCallingIdentity();
5841         boolean changed;
5842         synchronized(mWindowMap) {
5843             changed = updateRotationUncheckedLocked(false);
5844             if (!changed || forceRelayout) {
5845                 getDefaultDisplayContentLocked().layoutNeeded = true;
5846                 performLayoutAndPlaceSurfacesLocked();
5847             }
5848         }
5849
5850         if (changed || alwaysSendConfiguration) {
5851             sendNewConfiguration();
5852         }
5853
5854         Binder.restoreCallingIdentity(origId);
5855     }
5856
5857     // TODO(multidisplay): Rotate any display?
5858     /**
5859      * Updates the current rotation.
5860      *
5861      * Returns true if the rotation has been changed.  In this case YOU
5862      * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
5863      */
5864     public boolean updateRotationUncheckedLocked(boolean inTransaction) {
5865         if (mDeferredRotationPauseCount > 0) {
5866             // Rotation updates have been paused temporarily.  Defer the update until
5867             // updates have been resumed.
5868             if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");
5869             return false;
5870         }
5871
5872         ScreenRotationAnimation screenRotationAnimation =
5873                 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
5874         if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
5875             // Rotation updates cannot be performed while the previous rotation change
5876             // animation is still in progress.  Skip this update.  We will try updating
5877             // again after the animation is finished and the display is unfrozen.
5878             if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");
5879             return false;
5880         }
5881
5882         if (!mDisplayEnabled) {
5883             // No point choosing a rotation if the display is not enabled.
5884             if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");
5885             return false;
5886         }
5887
5888         // TODO: Implement forced rotation changes.
5889         //       Set mAltOrientation to indicate that the application is receiving
5890         //       an orientation that has different metrics than it expected.
5891         //       eg. Portrait instead of Landscape.
5892
5893         int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
5894         boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
5895                 mForcedAppOrientation, rotation);
5896
5897         if (DEBUG_ORIENTATION) {
5898             Slog.v(TAG, "Application requested orientation "
5899                     + mForcedAppOrientation + ", got rotation " + rotation
5900                     + " which has " + (altOrientation ? "incompatible" : "compatible")
5901                     + " metrics");
5902         }
5903
5904         if (mRotation == rotation && mAltOrientation == altOrientation) {
5905             // No change.
5906             return false;
5907         }
5908
5909         if (DEBUG_ORIENTATION) {
5910             Slog.v(TAG,
5911                 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
5912                 + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
5913                 + ", forceApp=" + mForcedAppOrientation);
5914         }
5915
5916         mRotation = rotation;
5917         mAltOrientation = altOrientation;
5918         mPolicy.setRotationLw(mRotation);
5919
5920         mWindowsFreezingScreen = true;
5921         mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
5922         mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
5923         mWaitingForConfig = true;
5924         final DisplayContent displayContent = getDefaultDisplayContentLocked();
5925         displayContent.layoutNeeded = true;
5926         final int[] anim = new int[2];
5927         if (displayContent.isDimming()) {
5928             anim[0] = anim[1] = 0;
5929         } else {
5930             mPolicy.selectRotationAnimationLw(anim);
5931         }
5932         startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
5933         // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
5934         screenRotationAnimation =
5935                 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
5936
5937         // We need to update our screen size information to match the new
5938         // rotation.  Note that this is redundant with the later call to
5939         // sendNewConfiguration() that must be called after this function
5940         // returns...  however we need to do the screen size part of that
5941         // before then so we have the correct size to use when initializing
5942         // the rotation animation for the new rotation.
5943         computeScreenConfigurationLocked(null);
5944
5945         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5946         if (!inTransaction) {
5947             if (SHOW_TRANSACTIONS) {
5948                 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
5949             }
5950             SurfaceControl.openTransaction();
5951         }
5952         try {
5953             // NOTE: We disable the rotation in the emulator because
5954             //       it doesn't support hardware OpenGL emulation yet.
5955             if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
5956                     && screenRotationAnimation.hasScreenshot()) {
5957                 if (screenRotationAnimation.setRotationInTransaction(
5958                         rotation, mFxSession,
5959                         MAX_ANIMATION_DURATION, mTransitionAnimationScale,
5960                         displayInfo.logicalWidth, displayInfo.logicalHeight)) {
5961                     scheduleAnimationLocked();
5962                 }
5963             }
5964
5965             mDisplayManagerService.performTraversalInTransactionFromWindowManager();
5966         } finally {
5967             if (!inTransaction) {
5968                 SurfaceControl.closeTransaction();
5969                 if (SHOW_LIGHT_TRANSACTIONS) {
5970                     Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
5971                 }
5972             }
5973         }
5974
5975         final WindowList windows = displayContent.getWindowList();
5976         for (int i = windows.size() - 1; i >= 0; i--) {
5977             WindowState w = windows.get(i);
5978             if (w.mHasSurface) {
5979                 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
5980                 w.mOrientationChanging = true;
5981                 mInnerFields.mOrientationChangeComplete = false;
5982             }
5983             w.mLastFreezeDuration = 0;
5984         }
5985
5986         for (int i=mRotationWatchers.size()-1; i>=0; i--) {
5987             try {
5988                 mRotationWatchers.get(i).onRotationChanged(rotation);
5989             } catch (RemoteException e) {
5990             }
5991         }
5992
5993         //TODO (multidisplay): Magnification is supported only for the default display.
5994         if (mDisplayMagnifier != null
5995                 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
5996             mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation);
5997         }
5998
5999         return true;
6000     }
6001
6002     @Override
6003     public int getRotation() {
6004         return mRotation;
6005     }
6006
6007     @Override
6008     public boolean isRotationFrozen() {
6009         return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6010     }
6011
6012     @Override
6013     public int watchRotation(IRotationWatcher watcher) {
6014         final IBinder watcherBinder = watcher.asBinder();
6015         IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6016             @Override
6017             public void binderDied() {
6018                 synchronized (mWindowMap) {
6019                     for (int i=0; i<mRotationWatchers.size(); i++) {
6020                         if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
6021                             IRotationWatcher removed = mRotationWatchers.remove(i);
6022                             if (removed != null) {
6023                                 removed.asBinder().unlinkToDeath(this, 0);
6024                             }
6025                             i--;
6026                         }
6027                     }
6028                 }
6029             }
6030         };
6031
6032         synchronized (mWindowMap) {
6033             try {
6034                 watcher.asBinder().linkToDeath(dr, 0);
6035                 mRotationWatchers.add(watcher);
6036             } catch (RemoteException e) {
6037                 // Client died, no cleanup needed.
6038             }
6039
6040             return mRotation;
6041         }
6042     }
6043
6044     @Override
6045     public void removeRotationWatcher(IRotationWatcher watcher) {
6046         final IBinder watcherBinder = watcher.asBinder();
6047         synchronized (mWindowMap) {
6048             for (int i=0; i<mRotationWatchers.size(); i++) {
6049                 if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
6050                     mRotationWatchers.remove(i);
6051                     i--;
6052                 }
6053             }
6054         }
6055     }
6056
6057     /**
6058      * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6059      * theme attribute) on devices that feature a physical options menu key attempt to position
6060      * their menu panel window along the edge of the screen nearest the physical menu key.
6061      * This lowers the travel distance between invoking the menu panel and selecting
6062      * a menu option.
6063      *
6064      * This method helps control where that menu is placed. Its current implementation makes
6065      * assumptions about the menu key and its relationship to the screen based on whether
6066      * the device's natural orientation is portrait (width < height) or landscape.
6067      *
6068      * The menu key is assumed to be located along the bottom edge of natural-portrait
6069      * devices and along the right edge of natural-landscape devices. If these assumptions
6070      * do not hold for the target device, this method should be changed to reflect that.
6071      *
6072      * @return A {@link Gravity} value for placing the options menu window
6073      */
6074     @Override
6075     public int getPreferredOptionsPanelGravity() {
6076         synchronized (mWindowMap) {
6077             final int rotation = getRotation();
6078
6079             // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6080             final DisplayContent displayContent = getDefaultDisplayContentLocked();
6081             if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6082                 // On devices with a natural orientation of portrait
6083                 switch (rotation) {
6084                     default:
6085                     case Surface.ROTATION_0:
6086                         return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6087                     case Surface.ROTATION_90:
6088                         return Gravity.RIGHT | Gravity.BOTTOM;
6089                     case Surface.ROTATION_180:
6090                         return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6091                     case Surface.ROTATION_270:
6092                         return Gravity.START | Gravity.BOTTOM;
6093                 }
6094             }
6095
6096             // On devices with a natural orientation of landscape
6097             switch (rotation) {
6098                 default:
6099                 case Surface.ROTATION_0:
6100                     return Gravity.RIGHT | Gravity.BOTTOM;
6101                 case Surface.ROTATION_90:
6102                     return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6103                 case Surface.ROTATION_180:
6104                     return Gravity.START | Gravity.BOTTOM;
6105                 case Surface.ROTATION_270:
6106                     return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6107             }
6108         }
6109     }
6110
6111     /**
6112      * Starts the view server on the specified port.
6113      *
6114      * @param port The port to listener to.
6115      *
6116      * @return True if the server was successfully started, false otherwise.
6117      *
6118      * @see com.android.server.wm.ViewServer
6119      * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
6120      */
6121     @Override
6122     public boolean startViewServer(int port) {
6123         if (isSystemSecure()) {
6124             return false;
6125         }
6126
6127         if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
6128             return false;
6129         }
6130
6131         if (port < 1024) {
6132             return false;
6133         }
6134
6135         if (mViewServer != null) {
6136             if (!mViewServer.isRunning()) {
6137                 try {
6138                     return mViewServer.start();
6139                 } catch (IOException e) {
6140                     Slog.w(TAG, "View server did not start");
6141                 }
6142             }
6143             return false;
6144         }
6145
6146         try {
6147             mViewServer = new ViewServer(this, port);
6148             return mViewServer.start();
6149         } catch (IOException e) {
6150             Slog.w(TAG, "View server did not start");
6151         }
6152         return false;
6153     }
6154
6155     private boolean isSystemSecure() {
6156         return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
6157                 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6158     }
6159
6160     /**
6161      * Stops the view server if it exists.
6162      *
6163      * @return True if the server stopped, false if it wasn't started or
6164      *         couldn't be stopped.
6165      *
6166      * @see com.android.server.wm.ViewServer
6167      */
6168     @Override
6169     public boolean stopViewServer() {
6170         if (isSystemSecure()) {
6171             return false;
6172         }
6173
6174         if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
6175             return false;
6176         }
6177
6178         if (mViewServer != null) {
6179             return mViewServer.stop();
6180         }
6181         return false;
6182     }
6183
6184     /**
6185      * Indicates whether the view server is running.
6186      *
6187      * @return True if the server is running, false otherwise.
6188      *
6189      * @see com.android.server.wm.ViewServer
6190      */
6191     @Override
6192     public boolean isViewServerRunning() {
6193         if (isSystemSecure()) {
6194             return false;
6195         }
6196
6197         if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
6198             return false;
6199         }
6200
6201         return mViewServer != null && mViewServer.isRunning();
6202     }
6203
6204     /**
6205      * Lists all availble windows in the system. The listing is written in the
6206      * specified Socket's output stream with the following syntax:
6207      * windowHashCodeInHexadecimal windowName
6208      * Each line of the ouput represents a different window.
6209      *
6210      * @param client The remote client to send the listing to.
6211      * @return False if an error occured, true otherwise.
6212      */
6213     boolean viewServerListWindows(Socket client) {
6214         if (isSystemSecure()) {
6215             return false;
6216         }
6217
6218         boolean result = true;
6219
6220         WindowList windows = new WindowList();
6221         synchronized (mWindowMap) {
6222             //noinspection unchecked
6223             final int numDisplays = mDisplayContents.size();
6224             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6225                 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
6226                 windows.addAll(displayContent.getWindowList());
6227             }
6228         }
6229
6230         BufferedWriter out = null;
6231
6232         // Any uncaught exception will crash the system process
6233         try {
6234             OutputStream clientStream = client.getOutputStream();
6235             out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6236
6237             final int count = windows.size();
6238             for (int i = 0; i < count; i++) {
6239                 final WindowState w = windows.get(i);
6240                 out.write(Integer.toHexString(System.identityHashCode(w)));
6241                 out.write(' ');
6242                 out.append(w.mAttrs.getTitle());
6243                 out.write('\n');
6244             }
6245
6246             out.write("DONE.\n");
6247             out.flush();
6248         } catch (Exception e) {
6249             result = false;
6250         } finally {
6251             if (out != null) {
6252                 try {
6253                     out.close();
6254                 } catch (IOException e) {
6255                     result = false;
6256                 }
6257             }
6258         }
6259
6260         return result;
6261     }
6262
6263     // TODO(multidisplay): Extend to multiple displays.
6264     /**
6265      * Returns the focused window in the following format:
6266      * windowHashCodeInHexadecimal windowName
6267      *
6268      * @param client The remote client to send the listing to.
6269      * @return False if an error occurred, true otherwise.
6270      */
6271     boolean viewServerGetFocusedWindow(Socket client) {
6272         if (isSystemSecure()) {
6273             return false;
6274         }
6275
6276         boolean result = true;
6277
6278         WindowState focusedWindow = getFocusedWindow();
6279
6280         BufferedWriter out = null;
6281
6282         // Any uncaught exception will crash the system process
6283         try {
6284             OutputStream clientStream = client.getOutputStream();
6285             out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6286
6287             if(focusedWindow != null) {
6288                 out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
6289                 out.write(' ');
6290                 out.append(focusedWindow.mAttrs.getTitle());
6291             }
6292             out.write('\n');
6293             out.flush();
6294         } catch (Exception e) {
6295             result = false;
6296         } finally {
6297             if (out != null) {
6298                 try {
6299                     out.close();
6300                 } catch (IOException e) {
6301                     result = false;
6302                 }
6303             }
6304         }
6305
6306         return result;
6307     }
6308
6309     /**
6310      * Sends a command to a target window. The result of the command, if any, will be
6311      * written in the output stream of the specified socket.
6312      *
6313      * The parameters must follow this syntax:
6314      * windowHashcode extra
6315      *
6316      * Where XX is the length in characeters of the windowTitle.
6317      *
6318      * The first parameter is the target window. The window with the specified hashcode
6319      * will be the target. If no target can be found, nothing happens. The extra parameters
6320      * will be delivered to the target window and as parameters to the command itself.
6321      *
6322      * @param client The remote client to sent the result, if any, to.
6323      * @param command The command to execute.
6324      * @param parameters The command parameters.
6325      *
6326      * @return True if the command was successfully delivered, false otherwise. This does
6327      *         not indicate whether the command itself was successful.
6328      */
6329     boolean viewServerWindowCommand(Socket client, String command, String parameters) {
6330         if (isSystemSecure()) {
6331             return false;
6332         }
6333
6334         boolean success = true;
6335         Parcel data = null;
6336         Parcel reply = null;
6337
6338         BufferedWriter out = null;
6339
6340         // Any uncaught exception will crash the system process
6341         try {
6342             // Find the hashcode of the window
6343             int index = parameters.indexOf(' ');
6344             if (index == -1) {
6345                 index = parameters.length();
6346             }
6347             final String code = parameters.substring(0, index);
6348             int hashCode = (int) Long.parseLong(code, 16);
6349
6350             // Extract the command's parameter after the window description
6351             if (index < parameters.length()) {
6352                 parameters = parameters.substring(index + 1);
6353             } else {
6354                 parameters = "";
6355             }
6356
6357             final WindowState window = findWindow(hashCode);
6358             if (window == null) {
6359                 return false;
6360             }
6361
6362             data = Parcel.obtain();
6363             data.writeInterfaceToken("android.view.IWindow");
6364             data.writeString(command);
6365             data.writeString(parameters);
6366             data.writeInt(1);
6367             ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
6368
6369             reply = Parcel.obtain();
6370
6371             final IBinder binder = window.mClient.asBinder();
6372             // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
6373             binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
6374
6375             reply.readException();
6376
6377             if (!client.isOutputShutdown()) {
6378                 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
6379                 out.write("DONE\n");
6380                 out.flush();
6381             }
6382
6383         } catch (Exception e) {
6384             Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
6385             success = false;
6386         } finally {
6387             if (data != null) {
6388                 data.recycle();
6389             }
6390             if (reply != null) {
6391                 reply.recycle();
6392             }
6393             if (out != null) {
6394                 try {
6395                     out.close();
6396                 } catch (IOException e) {
6397
6398                 }
6399             }
6400         }
6401
6402         return success;
6403     }
6404
6405     public void addWindowChangeListener(WindowChangeListener listener) {
6406         synchronized(mWindowMap) {
6407             mWindowChangeListeners.add(listener);
6408         }
6409     }
6410
6411     public void removeWindowChangeListener(WindowChangeListener listener) {
6412         synchronized(mWindowMap) {
6413             mWindowChangeListeners.remove(listener);
6414         }
6415     }
6416
6417     private void notifyWindowsChanged() {
6418         WindowChangeListener[] windowChangeListeners;
6419         synchronized(mWindowMap) {
6420             if(mWindowChangeListeners.isEmpty()) {
6421                 return;
6422             }
6423             windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6424             windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6425         }
6426         int N = windowChangeListeners.length;
6427         for(int i = 0; i < N; i++) {
6428             windowChangeListeners[i].windowsChanged();
6429         }
6430     }
6431
6432     private void notifyFocusChanged() {
6433         WindowChangeListener[] windowChangeListeners;
6434         synchronized(mWindowMap) {
6435             if(mWindowChangeListeners.isEmpty()) {
6436                 return;
6437             }
6438             windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6439             windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6440         }
6441         int N = windowChangeListeners.length;
6442         for(int i = 0; i < N; i++) {
6443             windowChangeListeners[i].focusChanged();
6444         }
6445     }
6446
6447     private WindowState findWindow(int hashCode) {
6448         if (hashCode == -1) {
6449             // TODO(multidisplay): Extend to multiple displays.
6450             return getFocusedWindow();
6451         }
6452
6453         synchronized (mWindowMap) {
6454             final int numDisplays = mDisplayContents.size();
6455             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6456                 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
6457                 final int numWindows = windows.size();
6458                 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
6459                     final WindowState w = windows.get(winNdx);
6460                     if (System.identityHashCode(w) == hashCode) {
6461                         return w;
6462                     }
6463                 }
6464             }
6465         }
6466
6467         return null;
6468     }
6469
6470     /*
6471      * Instruct the Activity Manager to fetch the current configuration and broadcast
6472      * that to config-changed listeners if appropriate.
6473      */
6474     void sendNewConfiguration() {
6475         try {
6476             mActivityManager.updateConfiguration(null);
6477         } catch (RemoteException e) {
6478         }
6479     }
6480
6481     public Configuration computeNewConfiguration() {
6482         synchronized (mWindowMap) {
6483             Configuration config = computeNewConfigurationLocked();
6484             if (config == null && mWaitingForConfig) {
6485                 // Nothing changed but we are waiting for something... stop that!
6486                 mWaitingForConfig = false;
6487                 mLastFinishedFreezeSource = "new-config";
6488                 performLayoutAndPlaceSurfacesLocked();
6489             }
6490             return config;
6491         }
6492     }
6493
6494     Configuration computeNewConfigurationLocked() {
6495         Configuration config = new Configuration();
6496         config.fontScale = 0;
6497         if (!computeScreenConfigurationLocked(config)) {
6498             return null;
6499         }
6500         return config;
6501     }
6502
6503     private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
6504         // TODO: Multidisplay: for now only use with default display.
6505         final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
6506         if (width < displayInfo.smallestNominalAppWidth) {
6507             displayInfo.smallestNominalAppWidth = width;
6508         }
6509         if (width > displayInfo.largestNominalAppWidth) {
6510             displayInfo.largestNominalAppWidth = width;
6511         }
6512         final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
6513         if (height < displayInfo.smallestNominalAppHeight) {
6514             displayInfo.smallestNominalAppHeight = height;
6515         }
6516         if (height > displayInfo.largestNominalAppHeight) {
6517             displayInfo.largestNominalAppHeight = height;
6518         }
6519     }
6520
6521     private int reduceConfigLayout(int curLayout, int rotation, float density,
6522             int dw, int dh) {
6523         // TODO: Multidisplay: for now only use with default display.
6524         // Get the app screen size at this rotation.
6525         int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6526         int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6527
6528         // Compute the screen layout size class for this rotation.
6529         int longSize = w;
6530         int shortSize = h;
6531         if (longSize < shortSize) {
6532             int tmp = longSize;
6533             longSize = shortSize;
6534             shortSize = tmp;
6535         }
6536         longSize = (int)(longSize/density);
6537         shortSize = (int)(shortSize/density);
6538         return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
6539     }
6540
6541     private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
6542                   int dw, int dh, float density, Configuration outConfig) {
6543         // TODO: Multidisplay: for now only use with default display.
6544
6545         // We need to determine the smallest width that will occur under normal
6546         // operation.  To this, start with the base screen size and compute the
6547         // width under the different possible rotations.  We need to un-rotate
6548         // the current screen dimensions before doing this.
6549         int unrotDw, unrotDh;
6550         if (rotated) {
6551             unrotDw = dh;
6552             unrotDh = dw;
6553         } else {
6554             unrotDw = dw;
6555             unrotDh = dh;
6556         }
6557         displayInfo.smallestNominalAppWidth = 1<<30;
6558         displayInfo.smallestNominalAppHeight = 1<<30;
6559         displayInfo.largestNominalAppWidth = 0;
6560         displayInfo.largestNominalAppHeight = 0;
6561         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
6562         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
6563         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
6564         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
6565         int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
6566         sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
6567         sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
6568         sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
6569         sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
6570         outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
6571         outConfig.screenLayout = sl;
6572     }
6573
6574     private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
6575             int dw, int dh) {
6576         // TODO: Multidisplay: for now only use with default display.
6577         dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6578         dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6579         float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
6580         int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
6581         if (curSize == 0 || size < curSize) {
6582             curSize = size;
6583         }
6584         return curSize;
6585     }
6586
6587     private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) {
6588         // TODO: Multidisplay: for now only use with default display.
6589         mTmpDisplayMetrics.setTo(dm);
6590         final DisplayMetrics tmpDm = mTmpDisplayMetrics;
6591         final int unrotDw, unrotDh;
6592         if (rotated) {
6593             unrotDw = dh;
6594             unrotDh = dw;
6595         } else {
6596             unrotDw = dw;
6597             unrotDh = dh;
6598         }
6599         int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
6600         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
6601         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
6602         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
6603         return sw;
6604     }
6605
6606     boolean computeScreenConfigurationLocked(Configuration config) {
6607         if (!mDisplayReady) {
6608             return false;
6609         }
6610
6611         // TODO(multidisplay): For now, apply Configuration to main screen only.
6612         final DisplayContent displayContent = getDefaultDisplayContentLocked();
6613
6614         // Use the effective "visual" dimensions based on current rotation
6615         final boolean rotated = (mRotation == Surface.ROTATION_90
6616                 || mRotation == Surface.ROTATION_270);
6617         final int realdw = rotated ?
6618                 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
6619         final int realdh = rotated ?
6620                 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
6621         int dw = realdw;
6622         int dh = realdh;
6623
6624         if (mAltOrientation) {
6625             if (realdw > realdh) {
6626                 // Turn landscape into portrait.
6627                 int maxw = (int)(realdh/1.3f);
6628                 if (maxw < realdw) {
6629                     dw = maxw;
6630                 }
6631             } else {
6632                 // Turn portrait into landscape.
6633                 int maxh = (int)(realdw/1.3f);
6634                 if (maxh < realdh) {
6635                     dh = maxh;
6636                 }
6637             }
6638         }
6639
6640         if (config != null) {
6641             config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
6642                     Configuration.ORIENTATION_LANDSCAPE;
6643         }
6644
6645         // Update application display metrics.
6646         final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
6647         final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
6648         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6649         synchronized(displayContent.mDisplaySizeLock) {
6650             displayInfo.rotation = mRotation;
6651             displayInfo.logicalWidth = dw;
6652             displayInfo.logicalHeight = dh;
6653             displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
6654             displayInfo.appWidth = appWidth;
6655             displayInfo.appHeight = appHeight;
6656             displayInfo.getLogicalMetrics(mRealDisplayMetrics,
6657                     CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
6658             displayInfo.getAppMetrics(mDisplayMetrics);
6659             mDisplayManagerService.setDisplayInfoOverrideFromWindowManager(
6660                     displayContent.getDisplayId(), displayInfo);
6661         }
6662         if (false) {
6663             Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
6664         }
6665
6666         final DisplayMetrics dm = mDisplayMetrics;
6667         mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
6668                 mCompatDisplayMetrics);
6669
6670         if (config != null) {
6671             config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
6672                     / dm.density);
6673             config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
6674                     / dm.density);
6675             computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
6676
6677             config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
6678             config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
6679             config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
6680             config.densityDpi = displayContent.mBaseDisplayDensity;
6681
6682             // Update the configuration based on available input devices, lid switch,
6683             // and platform configuration.
6684             config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6685             config.keyboard = Configuration.KEYBOARD_NOKEYS;
6686             config.navigation = Configuration.NAVIGATION_NONAV;
6687
6688             int keyboardPresence = 0;
6689             int navigationPresence = 0;
6690             final InputDevice[] devices = mInputManager.getInputDevices();
6691             final int len = devices.length;
6692             for (int i = 0; i < len; i++) {
6693                 InputDevice device = devices[i];
6694                 if (!device.isVirtual()) {
6695                     final int sources = device.getSources();
6696                     final int presenceFlag = device.isExternal() ?
6697                             WindowManagerPolicy.PRESENCE_EXTERNAL :
6698                                     WindowManagerPolicy.PRESENCE_INTERNAL;
6699
6700                     if (mIsTouchDevice) {
6701                         if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
6702                                 InputDevice.SOURCE_TOUCHSCREEN) {
6703                             config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
6704                         }
6705                     } else {
6706                         config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6707                     }
6708
6709                     if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
6710                         config.navigation = Configuration.NAVIGATION_TRACKBALL;
6711                         navigationPresence |= presenceFlag;
6712                     } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
6713                             && config.navigation == Configuration.NAVIGATION_NONAV) {
6714                         config.navigation = Configuration.NAVIGATION_DPAD;
6715                         navigationPresence |= presenceFlag;
6716                     }
6717
6718                     if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
6719                         config.keyboard = Configuration.KEYBOARD_QWERTY;
6720                         keyboardPresence |= presenceFlag;
6721                     }
6722                 }
6723             }
6724
6725             // Determine whether a hard keyboard is available and enabled.
6726             boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
6727             if (hardKeyboardAvailable != mHardKeyboardAvailable) {
6728                 mHardKeyboardAvailable = hardKeyboardAvailable;
6729                 mHardKeyboardEnabled = hardKeyboardAvailable;
6730                 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6731                 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6732             }
6733             if (!mHardKeyboardEnabled) {
6734                 config.keyboard = Configuration.KEYBOARD_NOKEYS;
6735             }
6736
6737             // Let the policy update hidden states.
6738             config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
6739             config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
6740             config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
6741             mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
6742         }
6743
6744         return true;
6745     }
6746
6747     public boolean isHardKeyboardAvailable() {
6748         synchronized (mWindowMap) {
6749             return mHardKeyboardAvailable;
6750         }
6751     }
6752
6753     public boolean isHardKeyboardEnabled() {
6754         synchronized (mWindowMap) {
6755             return mHardKeyboardEnabled;
6756         }
6757     }
6758
6759     public void setHardKeyboardEnabled(boolean enabled) {
6760         synchronized (mWindowMap) {
6761             if (mHardKeyboardEnabled != enabled) {
6762                 mHardKeyboardEnabled = enabled;
6763                 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6764             }
6765         }
6766     }
6767
6768     public void setOnHardKeyboardStatusChangeListener(
6769             OnHardKeyboardStatusChangeListener listener) {
6770         synchronized (mWindowMap) {
6771             mHardKeyboardStatusChangeListener = listener;
6772         }
6773     }
6774
6775     void notifyHardKeyboardStatusChange() {
6776         final boolean available, enabled;
6777         final OnHardKeyboardStatusChangeListener listener;
6778         synchronized (mWindowMap) {
6779             listener = mHardKeyboardStatusChangeListener;
6780             available = mHardKeyboardAvailable;
6781             enabled = mHardKeyboardEnabled;
6782         }
6783         if (listener != null) {
6784             listener.onHardKeyboardStatusChange(available, enabled);
6785         }
6786     }
6787
6788     // -------------------------------------------------------------
6789     // Drag and drop
6790     // -------------------------------------------------------------
6791
6792     IBinder prepareDragSurface(IWindow window, SurfaceSession session,
6793             int flags, int width, int height, Surface outSurface) {
6794         if (DEBUG_DRAG) {
6795             Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height
6796                     + " flags=" + Integer.toHexString(flags) + " win=" + window
6797                     + " asbinder=" + window.asBinder());
6798         }
6799
6800         final int callerPid = Binder.getCallingPid();
6801         final long origId = Binder.clearCallingIdentity();
6802         IBinder token = null;
6803
6804         try {
6805             synchronized (mWindowMap) {
6806                 try {
6807                     if (mDragState == null) {
6808                         // TODO(multi-display): support other displays
6809                         final DisplayContent displayContent = getDefaultDisplayContentLocked();
6810                         final Display display = displayContent.getDisplay();
6811                         SurfaceControl surface = new SurfaceControl(session, "drag surface",
6812                                 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
6813                         surface.setLayerStack(display.getLayerStack());
6814                         if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
6815                                 + surface + ": CREATE");
6816                         outSurface.copyFrom(surface);
6817                         final IBinder winBinder = window.asBinder();
6818                         token = new Binder();
6819                         mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
6820                         token = mDragState.mToken = new Binder();
6821
6822                         // 5 second timeout for this window to actually begin the drag
6823                         mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
6824                         Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
6825                         mH.sendMessageDelayed(msg, 5000);
6826                     } else {
6827                         Slog.w(TAG, "Drag already in progress");
6828                     }
6829                 } catch (OutOfResourcesException e) {
6830                     Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
6831                     if (mDragState != null) {
6832                         mDragState.reset();
6833                         mDragState = null;
6834                     }
6835                 }
6836             }
6837         } finally {
6838             Binder.restoreCallingIdentity(origId);
6839         }
6840
6841         return token;
6842     }
6843
6844     // -------------------------------------------------------------
6845     // Input Events and Focus Management
6846     // -------------------------------------------------------------
6847
6848     final InputMonitor mInputMonitor = new InputMonitor(this);
6849     private boolean mEventDispatchingEnabled;
6850
6851     @Override
6852     public void pauseKeyDispatching(IBinder _token) {
6853         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6854                 "pauseKeyDispatching()")) {
6855             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6856         }
6857
6858         synchronized (mWindowMap) {
6859             WindowToken token = mTokenMap.get(_token);
6860             if (token != null) {
6861                 mInputMonitor.pauseDispatchingLw(token);
6862             }
6863         }
6864     }
6865
6866     @Override
6867     public void resumeKeyDispatching(IBinder _token) {
6868         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6869                 "resumeKeyDispatching()")) {
6870             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6871         }
6872
6873         synchronized (mWindowMap) {
6874             WindowToken token = mTokenMap.get(_token);
6875             if (token != null) {
6876                 mInputMonitor.resumeDispatchingLw(token);
6877             }
6878         }
6879     }
6880
6881     @Override
6882     public void setEventDispatching(boolean enabled) {
6883         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6884                 "setEventDispatching()")) {
6885             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6886         }
6887
6888         synchronized (mWindowMap) {
6889             mEventDispatchingEnabled = enabled;
6890             if (mDisplayEnabled) {
6891                 mInputMonitor.setEventDispatchingLw(enabled);
6892             }
6893             sendScreenStatusToClientsLocked();
6894         }
6895     }
6896
6897     @Override
6898     public IBinder getFocusedWindowToken() {
6899         if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
6900                 "getFocusedWindowToken()")) {
6901             throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
6902         }
6903         synchronized (mWindowMap) {
6904             WindowState windowState = getFocusedWindowLocked();
6905             if (windowState != null) {
6906                 return windowState.mClient.asBinder();
6907             }
6908             return null;
6909         }
6910     }
6911
6912     private WindowState getFocusedWindow() {
6913         synchronized (mWindowMap) {
6914             return getFocusedWindowLocked();
6915         }
6916     }
6917
6918     private WindowState getFocusedWindowLocked() {
6919         return mCurrentFocus;
6920     }
6921
6922     public boolean detectSafeMode() {
6923         if (!mInputMonitor.waitForInputDevicesReady(
6924                 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
6925             Slog.w(TAG, "Devices still not ready after waiting "
6926                    + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
6927                    + " milliseconds before attempting to detect safe mode.");
6928         }
6929
6930         int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
6931                 KeyEvent.KEYCODE_MENU);
6932         int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
6933         int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
6934                 KeyEvent.KEYCODE_DPAD_CENTER);
6935         int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
6936                 InputManagerService.BTN_MOUSE);
6937         int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
6938                 KeyEvent.KEYCODE_VOLUME_DOWN);
6939         mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
6940                 || volumeDownState > 0;
6941         try {
6942             if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
6943                 mSafeMode = true;
6944                 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
6945             }
6946         } catch (IllegalArgumentException e) {
6947         }
6948         if (mSafeMode) {
6949             Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
6950                     + " dpad=" + dpadState + " trackball=" + trackballState + ")");
6951         } else {
6952             Log.i(TAG, "SAFE MODE not enabled");
6953         }
6954         mPolicy.setSafeMode(mSafeMode);
6955         return mSafeMode;
6956     }
6957
6958     public void displayReady() {
6959         displayReady(Display.DEFAULT_DISPLAY);
6960
6961         synchronized(mWindowMap) {
6962             final DisplayContent displayContent = getDefaultDisplayContentLocked();
6963             readForcedDisplaySizeAndDensityLocked(displayContent);
6964             mDisplayReady = true;
6965         }
6966
6967         try {
6968             mActivityManager.updateConfiguration(null);
6969         } catch (RemoteException e) {
6970         }
6971
6972         synchronized(mWindowMap) {
6973             mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
6974                     PackageManager.FEATURE_TOUCHSCREEN);
6975             configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
6976         }
6977
6978         try {
6979             mActivityManager.updateConfiguration(null);
6980         } catch (RemoteException e) {
6981         }
6982     }
6983
6984     private void displayReady(int displayId) {
6985         synchronized(mWindowMap) {
6986             final DisplayContent displayContent = getDisplayContentLocked(displayId);
6987             if (displayContent != null) {
6988                 mAnimator.addDisplayLocked(displayId);
6989                 synchronized(displayContent.mDisplaySizeLock) {
6990                     // Bootstrap the default logical display from the display manager.
6991                     final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6992                     DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId);
6993                     if (newDisplayInfo != null) {
6994                         displayInfo.copyFrom(newDisplayInfo);
6995                     }
6996                     displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
6997                     displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
6998                     displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
6999                     displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
7000                     displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
7001                     displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
7002                     displayContent.mBaseDisplayRect.set(0, 0,
7003                             displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight);
7004                 }
7005             }
7006         }
7007     }
7008
7009     public void systemReady() {
7010         mPolicy.systemReady();
7011     }
7012
7013     // TODO(multidisplay): Call isScreenOn for each display.
7014     private void sendScreenStatusToClientsLocked() {
7015         final boolean on = mPowerManager.isScreenOn();
7016         final int numDisplays = mDisplayContents.size();
7017         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
7018             final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
7019             final int numWindows = windows.size();
7020             for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
7021                 try {
7022                     windows.get(winNdx).mClient.dispatchScreenState(on);
7023                 } catch (RemoteException e) {
7024                     // Ignored
7025                 }
7026             }
7027         }
7028     }
7029
7030     // -------------------------------------------------------------
7031     // Async Handler
7032     // -------------------------------------------------------------
7033
7034     final class H extends Handler {
7035         public static final int REPORT_FOCUS_CHANGE = 2;
7036         public static final int REPORT_LOSING_FOCUS = 3;
7037         public static final int DO_TRAVERSAL = 4;
7038         public static final int ADD_STARTING = 5;
7039         public static final int REMOVE_STARTING = 6;
7040         public static final int FINISHED_STARTING = 7;
7041         public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
7042         public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
7043         public static final int WINDOW_FREEZE_TIMEOUT = 11;
7044
7045         public static final int APP_TRANSITION_TIMEOUT = 13;
7046         public static final int PERSIST_ANIMATION_SCALE = 14;
7047         public static final int FORCE_GC = 15;
7048         public static final int ENABLE_SCREEN = 16;
7049         public static final int APP_FREEZE_TIMEOUT = 17;
7050         public static final int SEND_NEW_CONFIGURATION = 18;
7051         public static final int REPORT_WINDOWS_CHANGE = 19;
7052         public static final int DRAG_START_TIMEOUT = 20;
7053         public static final int DRAG_END_TIMEOUT = 21;
7054         public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
7055         public static final int BOOT_TIMEOUT = 23;
7056         public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
7057         public static final int SHOW_STRICT_MODE_VIOLATION = 25;
7058         public static final int DO_ANIMATION_CALLBACK = 26;
7059
7060         public static final int DO_DISPLAY_ADDED = 27;
7061         public static final int DO_DISPLAY_REMOVED = 28;
7062         public static final int DO_DISPLAY_CHANGED = 29;
7063
7064         public static final int CLIENT_FREEZE_TIMEOUT = 30;
7065         public static final int TAP_OUTSIDE_STACK = 31;
7066         public static final int NOTIFY_ACTIVITY_DRAWN = 32;
7067
7068         public static final int REMOVE_STARTING_TIMEOUT = 33;
7069
7070         @Override
7071         public void handleMessage(Message msg) {
7072             if (DEBUG_WINDOW_TRACE) {
7073                 Slog.v(TAG, "handleMessage: entry what=" + msg.what);
7074             }
7075             switch (msg.what) {
7076                 case REPORT_FOCUS_CHANGE: {
7077                     WindowState lastFocus;
7078                     WindowState newFocus;
7079
7080                     synchronized(mWindowMap) {
7081                         lastFocus = mLastFocus;
7082                         newFocus = mCurrentFocus;
7083                         if (lastFocus == newFocus) {
7084                             // Focus is not changing, so nothing to do.
7085                             return;
7086                         }
7087                         mLastFocus = newFocus;
7088                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus +
7089                                 " to " + newFocus);
7090                         if (newFocus != null && lastFocus != null
7091                                 && !newFocus.isDisplayedLw()) {
7092                             //Slog.i(TAG, "Delaying loss of focus...");
7093                             mLosingFocus.add(lastFocus);
7094                             lastFocus = null;
7095                         }
7096                     }
7097
7098                     //System.out.println("Changing focus from " + lastFocus
7099                     //                   + " to " + newFocus);
7100                     if (newFocus != null) {
7101                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus);
7102                         newFocus.reportFocusChangedSerialized(true, mInTouchMode);
7103                         notifyFocusChanged();
7104                     }
7105
7106                     if (lastFocus != null) {
7107                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus);
7108                         lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
7109                     }
7110                 } break;
7111
7112                 case REPORT_LOSING_FOCUS: {
7113                     ArrayList<WindowState> losers;
7114
7115                     synchronized(mWindowMap) {
7116                         losers = mLosingFocus;
7117                         mLosingFocus = new ArrayList<WindowState>();
7118                     }
7119
7120                     final int N = losers.size();
7121                     for (int i=0; i<N; i++) {
7122                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " +
7123                                 losers.get(i));
7124                         losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
7125                     }
7126                 } break;
7127
7128                 case DO_TRAVERSAL: {
7129                     synchronized(mWindowMap) {
7130                         mTraversalScheduled = false;
7131                         performLayoutAndPlaceSurfacesLocked();
7132                     }
7133                 } break;
7134
7135                 case ADD_STARTING: {
7136                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7137                     final StartingData sd = wtoken.startingData;
7138
7139                     if (sd == null) {
7140                         // Animation has been canceled... do nothing.
7141                         return;
7142                     }
7143
7144                     if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
7145                             + wtoken + ": pkg=" + sd.pkg);
7146
7147                     View view = null;
7148                     try {
7149                         view = mPolicy.addStartingWindow(
7150                             wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
7151                             sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags);
7152                     } catch (Exception e) {
7153                         Slog.w(TAG, "Exception when adding starting window", e);
7154                     }
7155
7156                     if (view != null) {
7157                         boolean abort = false;
7158
7159                         synchronized(mWindowMap) {
7160                             if (wtoken.removed || wtoken.startingData == null) {
7161                                 // If the window was successfully added, then
7162                                 // we need to remove it.
7163                                 if (wtoken.startingWindow != null) {
7164                                     if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7165                                             "Aborted starting " + wtoken
7166                                             + ": removed=" + wtoken.removed
7167                                             + " startingData=" + wtoken.startingData);
7168                                     removeStartingWindowTimeout(wtoken);
7169                                     wtoken.startingWindow = null;
7170                                     wtoken.startingData = null;
7171                                     abort = true;
7172                                 }
7173                             } else {
7174                                 wtoken.startingView = view;
7175                             }
7176                             if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
7177                                     "Added starting " + wtoken
7178                                     + ": startingWindow="
7179                                     + wtoken.startingWindow + " startingView="
7180                                     + wtoken.startingView);
7181                         }
7182
7183                         if (abort) {
7184                             try {
7185                                 mPolicy.removeStartingWindow(wtoken.token, view);
7186                             } catch (Exception e) {
7187                                 Slog.w(TAG, "Exception when removing starting window", e);
7188                             }
7189                         }
7190                     }
7191                 } break;
7192
7193                 case REMOVE_STARTING_TIMEOUT: {
7194                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7195                     Slog.e(TAG, "Starting window " + wtoken + " timed out");
7196                     // Fall through.
7197                 }
7198                 case REMOVE_STARTING: {
7199                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7200                     IBinder token = null;
7201                     View view = null;
7202                     synchronized (mWindowMap) {
7203                         if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
7204                                 + wtoken + ": startingWindow="
7205                                 + wtoken.startingWindow + " startingView="
7206                                 + wtoken.startingView);
7207                         if (wtoken.startingWindow != null) {
7208                             view = wtoken.startingView;
7209                             token = wtoken.token;
7210                             wtoken.startingData = null;
7211                             wtoken.startingView = null;
7212                             wtoken.startingWindow = null;
7213                             wtoken.startingDisplayed = false;
7214                         }
7215                     }
7216                     if (view != null) {
7217                         try {
7218                             mPolicy.removeStartingWindow(token, view);
7219                         } catch (Exception e) {
7220                             Slog.w(TAG, "Exception when removing starting window", e);
7221                         }
7222                     }
7223                 } break;
7224
7225                 case FINISHED_STARTING: {
7226                     IBinder token = null;
7227                     View view = null;
7228                     while (true) {
7229                         synchronized (mWindowMap) {
7230                             final int N = mFinishedStarting.size();
7231                             if (N <= 0) {
7232                                 break;
7233                             }
7234                             AppWindowToken wtoken = mFinishedStarting.remove(N-1);
7235
7236                             if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7237                                     "Finished starting " + wtoken
7238                                     + ": startingWindow=" + wtoken.startingWindow
7239                                     + " startingView=" + wtoken.startingView);
7240
7241                             if (wtoken.startingWindow == null) {
7242                                 continue;
7243                             }
7244
7245                             view = wtoken.startingView;
7246                             token = wtoken.token;
7247                             wtoken.startingData = null;
7248                             wtoken.startingView = null;
7249                             wtoken.startingWindow = null;
7250                             wtoken.startingDisplayed = false;
7251                         }
7252
7253                         try {
7254                             mPolicy.removeStartingWindow(token, view);
7255                         } catch (Exception e) {
7256                             Slog.w(TAG, "Exception when removing starting window", e);
7257                         }
7258                     }
7259                 } break;
7260
7261                 case REPORT_APPLICATION_TOKEN_DRAWN: {
7262                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7263
7264                     try {
7265                         if (DEBUG_VISIBILITY) Slog.v(
7266                                 TAG, "Reporting drawn in " + wtoken);
7267                         wtoken.appToken.windowsDrawn();
7268                     } catch (RemoteException ex) {
7269                     }
7270                 } break;
7271
7272                 case REPORT_APPLICATION_TOKEN_WINDOWS: {
7273                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7274
7275                     boolean nowVisible = msg.arg1 != 0;
7276                     boolean nowGone = msg.arg2 != 0;
7277
7278                     try {
7279                         if (DEBUG_VISIBILITY) Slog.v(
7280                                 TAG, "Reporting visible in " + wtoken
7281                                 + " visible=" + nowVisible
7282                                 + " gone=" + nowGone);
7283                         if (nowVisible) {
7284                             wtoken.appToken.windowsVisible();
7285                         } else {
7286                             wtoken.appToken.windowsGone();
7287                         }
7288                     } catch (RemoteException ex) {
7289                     }
7290                 } break;
7291
7292                 case WINDOW_FREEZE_TIMEOUT: {
7293                     // TODO(multidisplay): Can non-default displays rotate?
7294                     synchronized (mWindowMap) {
7295                         Slog.w(TAG, "Window freeze timeout expired.");
7296                         final WindowList windows = getDefaultWindowListLocked();
7297                         int i = windows.size();
7298                         while (i > 0) {
7299                             i--;
7300                             WindowState w = windows.get(i);
7301                             if (w.mOrientationChanging) {
7302                                 w.mOrientationChanging = false;
7303                                 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
7304                                         - mDisplayFreezeTime);
7305                                 Slog.w(TAG, "Force clearing orientation change: " + w);
7306                             }
7307                         }
7308                         performLayoutAndPlaceSurfacesLocked();
7309                     }
7310                     break;
7311                 }
7312
7313                 case APP_TRANSITION_TIMEOUT: {
7314                     synchronized (mWindowMap) {
7315                         if (mAppTransition.isTransitionSet()) {
7316                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
7317                             mAppTransition.setTimeout();
7318                             performLayoutAndPlaceSurfacesLocked();
7319                         }
7320                     }
7321                     break;
7322                 }
7323
7324                 case PERSIST_ANIMATION_SCALE: {
7325                     Settings.Global.putFloat(mContext.getContentResolver(),
7326                             Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
7327                     Settings.Global.putFloat(mContext.getContentResolver(),
7328                             Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
7329                     Settings.Global.putFloat(mContext.getContentResolver(),
7330                             Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale);
7331                     break;
7332                 }
7333
7334                 case FORCE_GC: {
7335                     synchronized (mWindowMap) {
7336                         // Since we're holding both mWindowMap and mAnimator we don't need to
7337                         // hold mAnimator.mLayoutToAnim.
7338                         if (mAnimator.mAnimating || mAnimationScheduled) {
7339                             // If we are animating, don't do the gc now but
7340                             // delay a bit so we don't interrupt the animation.
7341                             sendEmptyMessageDelayed(H.FORCE_GC, 2000);
7342                             return;
7343                         }
7344                         // If we are currently rotating the display, it will
7345                         // schedule a new message when done.
7346                         if (mDisplayFrozen) {
7347                             return;
7348                         }
7349                     }
7350                     Runtime.getRuntime().gc();
7351                     break;
7352                 }
7353
7354                 case ENABLE_SCREEN: {
7355                     performEnableScreen();
7356                     break;
7357                 }
7358
7359                 case APP_FREEZE_TIMEOUT: {
7360                     synchronized (mWindowMap) {
7361                         Slog.w(TAG, "App freeze timeout expired.");
7362                         DisplayContent displayContent = getDefaultDisplayContentLocked();
7363                         final ArrayList<Task> tasks = displayContent.getTasks();
7364                         for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
7365                             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
7366                             for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
7367                                 AppWindowToken tok = tokens.get(tokenNdx);
7368                                 if (tok.mAppAnimator.freezingScreen) {
7369                                     Slog.w(TAG, "Force clearing freeze: " + tok);
7370                                     unsetAppFreezingScreenLocked(tok, true, true);
7371                                 }
7372                             }
7373                         }
7374                     }
7375                     break;
7376                 }
7377
7378                 case CLIENT_FREEZE_TIMEOUT: {
7379                     synchronized (mWindowMap) {
7380                         if (mClientFreezingScreen) {
7381                             mClientFreezingScreen = false;
7382                             mLastFinishedFreezeSource = "client-timeout";
7383                             stopFreezingDisplayLocked();
7384                         }
7385                     }
7386                     break;
7387                 }
7388
7389                 case SEND_NEW_CONFIGURATION: {
7390                     removeMessages(SEND_NEW_CONFIGURATION);
7391                     sendNewConfiguration();
7392                     break;
7393                 }
7394
7395                 case REPORT_WINDOWS_CHANGE: {
7396                     if (mWindowsChanged) {
7397                         synchronized (mWindowMap) {
7398                             mWindowsChanged = false;
7399                         }
7400                         notifyWindowsChanged();
7401                     }
7402                     break;
7403                 }
7404
7405                 case DRAG_START_TIMEOUT: {
7406                     IBinder win = (IBinder)msg.obj;
7407                     if (DEBUG_DRAG) {
7408                         Slog.w(TAG, "Timeout starting drag by win " + win);
7409                     }
7410                     synchronized (mWindowMap) {
7411                         // !!! TODO: ANR the app that has failed to start the drag in time
7412                         if (mDragState != null) {
7413                             mDragState.unregister();
7414                             mInputMonitor.updateInputWindowsLw(true /*force*/);
7415                             mDragState.reset();
7416                             mDragState = null;
7417                         }
7418                     }
7419                     break;
7420                 }
7421
7422                 case DRAG_END_TIMEOUT: {
7423                     IBinder win = (IBinder)msg.obj;
7424                     if (DEBUG_DRAG) {
7425                         Slog.w(TAG, "Timeout ending drag to win " + win);
7426                     }
7427                     synchronized (mWindowMap) {
7428                         // !!! TODO: ANR the drag-receiving app
7429                         if (mDragState != null) {
7430                             mDragState.mDragResult = false;
7431                             mDragState.endDragLw();
7432                         }
7433                     }
7434                     break;
7435                 }
7436
7437                 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
7438                     notifyHardKeyboardStatusChange();
7439                     break;
7440                 }
7441
7442                 case BOOT_TIMEOUT: {
7443                     performBootTimeout();
7444                     break;
7445                 }
7446
7447                 case WAITING_FOR_DRAWN_TIMEOUT: {
7448                     Pair<WindowState, IRemoteCallback> pair;
7449                     synchronized (mWindowMap) {
7450                         pair = (Pair<WindowState, IRemoteCallback>)msg.obj;
7451                         Slog.w(TAG, "Timeout waiting for drawn: " + pair.first);
7452                         if (!mWaitingForDrawn.remove(pair)) {
7453                             return;
7454                         }
7455                     }
7456                     try {
7457                         pair.second.sendResult(null);
7458                     } catch (RemoteException e) {
7459                     }
7460                     break;
7461                 }
7462
7463                 case SHOW_STRICT_MODE_VIOLATION: {
7464                     showStrictModeViolation(msg.arg1, msg.arg2);
7465                     break;
7466                 }
7467
7468                 case DO_ANIMATION_CALLBACK: {
7469                     try {
7470                         ((IRemoteCallback)msg.obj).sendResult(null);
7471                     } catch (RemoteException e) {
7472                     }
7473                     break;
7474                 }
7475
7476                 case DO_DISPLAY_ADDED:
7477                     synchronized (mWindowMap) {
7478                         handleDisplayAddedLocked(msg.arg1);
7479                     }
7480                     break;
7481
7482                 case DO_DISPLAY_REMOVED:
7483                     synchronized (mWindowMap) {
7484                         handleDisplayRemovedLocked(msg.arg1);
7485                     }
7486                     break;
7487
7488                 case DO_DISPLAY_CHANGED:
7489                     synchronized (mWindowMap) {
7490                         handleDisplayChangedLocked(msg.arg1);
7491                     }
7492                     break;
7493
7494                 case TAP_OUTSIDE_STACK: {
7495                     int stackId;
7496                     synchronized (mWindowMap) {
7497                         stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
7498                     }
7499                     if (stackId >= 0) {
7500                         try {
7501                             mActivityManager.setFocusedStack(stackId);
7502                         } catch (RemoteException e) {
7503                         }
7504                     }
7505                 }
7506                 break;
7507                 case NOTIFY_ACTIVITY_DRAWN:
7508                     try {
7509                         mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
7510                     } catch (RemoteException e) {
7511                     }
7512                     break;
7513             }
7514             if (DEBUG_WINDOW_TRACE) {
7515                 Slog.v(TAG, "handleMessage: exit");
7516             }
7517         }
7518     }
7519
7520     // -------------------------------------------------------------
7521     // IWindowManager API
7522     // -------------------------------------------------------------
7523
7524     @Override
7525     public IWindowSession openSession(IInputMethodClient client,
7526             IInputContext inputContext) {
7527         if (client == null) throw new IllegalArgumentException("null client");
7528         if (inputContext == null) throw new IllegalArgumentException("null inputContext");
7529         Session session = new Session(this, client, inputContext);
7530         return session;
7531     }
7532
7533     @Override
7534     public boolean inputMethodClientHasFocus(IInputMethodClient client) {
7535         synchronized (mWindowMap) {
7536             // The focus for the client is the window immediately below
7537             // where we would place the input method window.
7538             int idx = findDesiredInputMethodWindowIndexLocked(false);
7539             if (idx > 0) {
7540                 // TODO(multidisplay): IMEs are only supported on the default display.
7541                 WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
7542                 if (DEBUG_INPUT_METHOD) {
7543                     Slog.i(TAG, "Desired input method target: " + imFocus);
7544                     Slog.i(TAG, "Current focus: " + mCurrentFocus);
7545                     Slog.i(TAG, "Last focus: " + mLastFocus);
7546                 }
7547                 if (imFocus != null) {
7548                     // This may be a starting window, in which case we still want
7549                     // to count it as okay.
7550                     if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
7551                             && imFocus.mAppToken != null) {
7552                         // The client has definitely started, so it really should
7553                         // have a window in this app token.  Let's look for it.
7554                         for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
7555                             WindowState w = imFocus.mAppToken.windows.get(i);
7556                             if (w != imFocus) {
7557                                 Log.i(TAG, "Switching to real app window: " + w);
7558                                 imFocus = w;
7559                                 break;
7560                             }
7561                         }
7562                     }
7563                     if (DEBUG_INPUT_METHOD) {
7564                         Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient);
7565                         if (imFocus.mSession.mClient != null) {
7566                             Slog.i(TAG, "IM target client binder: "
7567                                     + imFocus.mSession.mClient.asBinder());
7568                             Slog.i(TAG, "Requesting client binder: " + client.asBinder());
7569                         }
7570                     }
7571                     if (imFocus.mSession.mClient != null &&
7572                             imFocus.mSession.mClient.asBinder() == client.asBinder()) {
7573                         return true;
7574                     }
7575                 }
7576             }
7577
7578             // Okay, how about this...  what is the current focus?
7579             // It seems in some cases we may not have moved the IM
7580             // target window, such as when it was in a pop-up window,
7581             // so let's also look at the current focus.  (An example:
7582             // go to Gmail, start searching so the keyboard goes up,
7583             // press home.  Sometimes the IME won't go down.)
7584             // Would be nice to fix this more correctly, but it's
7585             // way at the end of a release, and this should be good enough.
7586             if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
7587                     && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
7588                 return true;
7589             }
7590         }
7591         return false;
7592     }
7593
7594     @Override
7595     public void getInitialDisplaySize(int displayId, Point size) {
7596         synchronized (mWindowMap) {
7597             final DisplayContent displayContent = getDisplayContentLocked(displayId);
7598             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7599                 synchronized(displayContent.mDisplaySizeLock) {
7600                     size.x = displayContent.mInitialDisplayWidth;
7601                     size.y = displayContent.mInitialDisplayHeight;
7602                 }
7603             }
7604         }
7605     }
7606
7607     @Override
7608     public void getBaseDisplaySize(int displayId, Point size) {
7609         synchronized (mWindowMap) {
7610             final DisplayContent displayContent = getDisplayContentLocked(displayId);
7611             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7612                 synchronized(displayContent.mDisplaySizeLock) {
7613                     size.x = displayContent.mBaseDisplayWidth;
7614                     size.y = displayContent.mBaseDisplayHeight;
7615                 }
7616             }
7617         }
7618     }
7619
7620     @Override
7621     public void setForcedDisplaySize(int displayId, int width, int height) {
7622         if (mContext.checkCallingOrSelfPermission(
7623                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7624                 PackageManager.PERMISSION_GRANTED) {
7625             throw new SecurityException("Must hold permission " +
7626                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
7627         }
7628         if (displayId != Display.DEFAULT_DISPLAY) {
7629             throw new IllegalArgumentException("Can only set the default display");
7630         }
7631         synchronized(mWindowMap) {
7632             // Set some sort of reasonable bounds on the size of the display that we
7633             // will try to emulate.
7634             final int MIN_WIDTH = 200;
7635             final int MIN_HEIGHT = 200;
7636             final int MAX_SCALE = 2;
7637             final DisplayContent displayContent = getDisplayContentLocked(displayId);
7638             if (displayContent != null) {
7639                 width = Math.min(Math.max(width, MIN_WIDTH),
7640                         displayContent.mInitialDisplayWidth * MAX_SCALE);
7641                 height = Math.min(Math.max(height, MIN_HEIGHT),
7642                         displayContent.mInitialDisplayHeight * MAX_SCALE);
7643                 setForcedDisplaySizeLocked(displayContent, width, height);
7644                 Settings.Global.putString(mContext.getContentResolver(),
7645                         Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
7646             }
7647         }
7648     }
7649
7650     private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
7651         String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
7652                 Settings.Global.DISPLAY_SIZE_FORCED);
7653         if (sizeStr == null || sizeStr.length() == 0) {
7654             sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
7655         }
7656         if (sizeStr != null && sizeStr.length() > 0) {
7657             final int pos = sizeStr.indexOf(',');
7658             if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
7659                 int width, height;
7660                 try {
7661                     width = Integer.parseInt(sizeStr.substring(0, pos));
7662                     height = Integer.parseInt(sizeStr.substring(pos+1));
7663                     synchronized(displayContent.mDisplaySizeLock) {
7664                         if (displayContent.mBaseDisplayWidth != width
7665                                 || displayContent.mBaseDisplayHeight != height) {
7666                             Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
7667                             displayContent.mBaseDisplayWidth = width;
7668                             displayContent.mBaseDisplayHeight = height;
7669                         }
7670                     }
7671                 } catch (NumberFormatException ex) {
7672                 }
7673             }
7674         }
7675         String densityStr = Settings.Global.getString(mContext.getContentResolver(),
7676                 Settings.Global.DISPLAY_DENSITY_FORCED);
7677         if (densityStr == null || densityStr.length() == 0) {
7678             densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
7679         }
7680         if (densityStr != null && densityStr.length() > 0) {
7681             int density;
7682             try {
7683                 density = Integer.parseInt(densityStr);
7684                 synchronized(displayContent.mDisplaySizeLock) {
7685                     if (displayContent.mBaseDisplayDensity != density) {
7686                         Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
7687                         displayContent.mBaseDisplayDensity = density;
7688                     }
7689                 }
7690             } catch (NumberFormatException ex) {
7691             }
7692         }
7693     }
7694
7695     // displayContent must not be null
7696     private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
7697         Slog.i(TAG, "Using new display size: " + width + "x" + height);
7698
7699         synchronized(displayContent.mDisplaySizeLock) {
7700             displayContent.mBaseDisplayWidth = width;
7701             displayContent.mBaseDisplayHeight = height;
7702         }
7703         reconfigureDisplayLocked(displayContent);
7704     }
7705
7706     @Override
7707     public void clearForcedDisplaySize(int displayId) {
7708         if (mContext.checkCallingOrSelfPermission(
7709                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7710                 PackageManager.PERMISSION_GRANTED) {
7711             throw new SecurityException("Must hold permission " +
7712                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
7713         }
7714         if (displayId != Display.DEFAULT_DISPLAY) {
7715             throw new IllegalArgumentException("Can only set the default display");
7716         }
7717         synchronized(mWindowMap) {
7718             final DisplayContent displayContent = getDisplayContentLocked(displayId);
7719             if (displayContent != null) {
7720                 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
7721                         displayContent.mInitialDisplayHeight);
7722                 Settings.Global.putString(mContext.getContentResolver(),
7723                         Settings.Global.DISPLAY_SIZE_FORCED, "");
7724             }
7725         }
7726     }
7727
7728     @Override
7729     public int getInitialDisplayDensity(int displayId) {
7730         synchronized (mWindowMap) {
7731             final DisplayContent displayContent = getDisplayContentLocked(displayId);
7732             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7733                 synchronized(displayContent.mDisplaySizeLock) {
7734                     return displayContent.mInitialDisplayDensity;
7735                 }
7736             }
7737         }
7738         return -1;
7739     }
7740
7741     @Override
7742     public int getBaseDisplayDensity(int displayId) {
7743         synchronized (mWindowMap) {
7744             final DisplayContent displayContent = getDisplayContentLocked(displayId);
7745             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7746                 synchronized(displayContent.mDisplaySizeLock) {
7747                     return displayContent.mBaseDisplayDensity;
7748                 }
7749             }
7750         }
7751         return -1;
7752     }
7753
7754     @Override
7755     public void setForcedDisplayDensity(int displayId, int density) {
7756         if (mContext.checkCallingOrSelfPermission(
7757                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7758                 PackageManager.PERMISSION_GRANTED) {
7759             throw new SecurityException("Must hold permission " +
7760                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
7761         }
7762         if (displayId != Display.DEFAULT_DISPLAY) {
7763             throw new IllegalArgumentException("Can only set the default display");
7764         }
7765         synchronized(mWindowMap) {
7766             final DisplayContent displayContent = getDisplayContentLocked(displayId);
7767             if (displayContent != null) {
7768                 setForcedDisplayDensityLocked(displayContent, density);
7769                 Settings.Global.putString(mContext.getContentResolver(),
7770                         Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
7771             }
7772         }
7773     }
7774
7775     // displayContent must not be null
7776     private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
7777         Slog.i(TAG, "Using new display density: " + density);
7778
7779         synchronized(displayContent.mDisplaySizeLock) {
7780             displayContent.mBaseDisplayDensity = density;
7781         }
7782         reconfigureDisplayLocked(displayContent);
7783     }
7784
7785     @Override
7786     public void clearForcedDisplayDensity(int displayId) {
7787         if (mContext.checkCallingOrSelfPermission(
7788                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7789                 PackageManager.PERMISSION_GRANTED) {
7790             throw new SecurityException("Must hold permission " +
7791                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
7792         }
7793         if (displayId != Display.DEFAULT_DISPLAY) {
7794             throw new IllegalArgumentException("Can only set the default display");
7795         }
7796         synchronized(mWindowMap) {
7797             final DisplayContent displayContent = getDisplayContentLocked(displayId);
7798             if (displayContent != null) {
7799                 setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
7800                 Settings.Global.putString(mContext.getContentResolver(),
7801                         Settings.Global.DISPLAY_DENSITY_FORCED, "");
7802             }
7803         }
7804     }
7805
7806     // displayContent must not be null
7807     private void reconfigureDisplayLocked(DisplayContent displayContent) {
7808         // TODO: Multidisplay: for now only use with default display.
7809         configureDisplayPolicyLocked(displayContent);
7810         displayContent.layoutNeeded = true;
7811
7812         boolean configChanged = updateOrientationFromAppTokensLocked(false);
7813         mTempConfiguration.setToDefaults();
7814         mTempConfiguration.fontScale = mCurConfiguration.fontScale;
7815         if (computeScreenConfigurationLocked(mTempConfiguration)) {
7816             if (mCurConfiguration.diff(mTempConfiguration) != 0) {
7817                 configChanged = true;
7818             }
7819         }
7820
7821         if (configChanged) {
7822             mWaitingForConfig = true;
7823             startFreezingDisplayLocked(false, 0, 0);
7824             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
7825         }
7826
7827         performLayoutAndPlaceSurfacesLocked();
7828     }
7829
7830     private void configureDisplayPolicyLocked(DisplayContent displayContent) {
7831         mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
7832                 displayContent.mBaseDisplayWidth,
7833                 displayContent.mBaseDisplayHeight,
7834                 displayContent.mBaseDisplayDensity);
7835
7836         DisplayInfo displayInfo = displayContent.getDisplayInfo();
7837         mPolicy.setDisplayOverscan(displayContent.getDisplay(),
7838                 displayInfo.overscanLeft, displayInfo.overscanTop,
7839                 displayInfo.overscanRight, displayInfo.overscanBottom);
7840     }
7841
7842     @Override
7843     public void setOverscan(int displayId, int left, int top, int right, int bottom) {
7844         if (mContext.checkCallingOrSelfPermission(
7845                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7846                 PackageManager.PERMISSION_GRANTED) {
7847             throw new SecurityException("Must hold permission " +
7848                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
7849         }
7850         synchronized(mWindowMap) {
7851             DisplayContent displayContent = getDisplayContentLocked(displayId);
7852             if (displayContent != null) {
7853                 setOverscanLocked(displayContent, left, top, right, bottom);
7854             }
7855         }
7856     }
7857
7858     private void setOverscanLocked(DisplayContent displayContent,
7859             int left, int top, int right, int bottom) {
7860         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7861         synchronized (displayContent.mDisplaySizeLock) {
7862             displayInfo.overscanLeft = left;
7863             displayInfo.overscanTop = top;
7864             displayInfo.overscanRight = right;
7865             displayInfo.overscanBottom = bottom;
7866         }
7867
7868         mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom);
7869         mDisplaySettings.writeSettingsLocked();
7870
7871         reconfigureDisplayLocked(displayContent);
7872     }
7873
7874     // -------------------------------------------------------------
7875     // Internals
7876     // -------------------------------------------------------------
7877
7878     final WindowState windowForClientLocked(Session session, IWindow client,
7879             boolean throwOnError) {
7880         return windowForClientLocked(session, client.asBinder(), throwOnError);
7881     }
7882
7883     final WindowState windowForClientLocked(Session session, IBinder client,
7884             boolean throwOnError) {
7885         WindowState win = mWindowMap.get(client);
7886         if (localLOGV) Slog.v(
7887             TAG, "Looking up client " + client + ": " + win);
7888         if (win == null) {
7889             RuntimeException ex = new IllegalArgumentException(
7890                     "Requested window " + client + " does not exist");
7891             if (throwOnError) {
7892                 throw ex;
7893             }
7894             Slog.w(TAG, "Failed looking up window", ex);
7895             return null;
7896         }
7897         if (session != null && win.mSession != session) {
7898             RuntimeException ex = new IllegalArgumentException(
7899                     "Requested window " + client + " is in session " +
7900                     win.mSession + ", not " + session);
7901             if (throwOnError) {
7902                 throw ex;
7903             }
7904             Slog.w(TAG, "Failed looking up window", ex);
7905             return null;
7906         }
7907
7908         return win;
7909     }
7910
7911     final void rebuildAppWindowListLocked() {
7912         // TODO: Multidisplay, when ActivityStacks and tasks exist on more than one display.
7913         rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
7914     }
7915
7916     private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
7917         final WindowList windows = displayContent.getWindowList();
7918         int NW = windows.size();
7919         int i;
7920         int lastBelow = -1;
7921         int numRemoved = 0;
7922
7923         if (mRebuildTmp.length < NW) {
7924             mRebuildTmp = new WindowState[NW+10];
7925         }
7926
7927         // First remove all existing app windows.
7928         i=0;
7929         while (i < NW) {
7930             WindowState w = windows.get(i);
7931             if (w.mAppToken != null) {
7932                 WindowState win = windows.remove(i);
7933                 win.mRebuilding = true;
7934                 mRebuildTmp[numRemoved] = win;
7935                 mWindowsChanged = true;
7936                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win);
7937                 NW--;
7938                 numRemoved++;
7939                 continue;
7940             } else if (lastBelow == i-1) {
7941                 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
7942                     lastBelow = i;
7943                 }
7944             }
7945             i++;
7946         }
7947
7948         // Keep whatever windows were below the app windows still below,
7949         // by skipping them.
7950         lastBelow++;
7951         i = lastBelow;
7952
7953         // First add all of the exiting app tokens...  these are no longer
7954         // in the main app list, but still have windows shown.  We put them
7955         // in the back because now that the animation is over we no longer
7956         // will care about them.
7957         AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
7958         int NT = exitingAppTokens.size();
7959         for (int j=0; j<NT; j++) {
7960             i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
7961         }
7962
7963         // And add in the still active app tokens in Z order.
7964         final ArrayList<Task> tasks = displayContent.getTasks();
7965         final int numTasks = tasks.size();
7966         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
7967             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
7968             final int numTokens = tokens.size();
7969             for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
7970                 final AppWindowToken wtoken = tokens.get(tokenNdx);
7971                 i = reAddAppWindowsLocked(displayContent, i, wtoken);
7972             }
7973         }
7974
7975         i -= lastBelow;
7976         if (i != numRemoved) {
7977             Slog.w(TAG, "Rebuild removed " + numRemoved + " windows but added " + i,
7978                     new RuntimeException("here").fillInStackTrace());
7979             for (i=0; i<numRemoved; i++) {
7980                 WindowState ws = mRebuildTmp[i];
7981                 if (ws.mRebuilding) {
7982                     StringWriter sw = new StringWriter();
7983                     PrintWriter pw = new FastPrintWriter(sw, false, 1024);
7984                     ws.dump(pw, "", true);
7985                     pw.flush();
7986                     Slog.w(TAG, "This window was lost: " + ws);
7987                     Slog.w(TAG, sw.toString());
7988                     ws.mWinAnimator.destroySurfaceLocked();
7989                 }
7990             }
7991             Slog.w(TAG, "Current app token list:");
7992             dumpAppTokensLocked();
7993             Slog.w(TAG, "Final window list:");
7994             dumpWindowsLocked();
7995         }
7996     }
7997
7998     private final void assignLayersLocked(WindowList windows) {
7999         int N = windows.size();
8000         int curBaseLayer = 0;
8001         int curLayer = 0;
8002         int i;
8003
8004         if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows,
8005                 new RuntimeException("here").fillInStackTrace());
8006
8007         boolean anyLayerChanged = false;
8008
8009         for (i=0; i<N; i++) {
8010             final WindowState w = windows.get(i);
8011             final WindowStateAnimator winAnimator = w.mWinAnimator;
8012             boolean layerChanged = false;
8013             int oldLayer = w.mLayer;
8014             if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
8015                     || (i > 0 && w.mIsWallpaper)) {
8016                 curLayer += WINDOW_LAYER_MULTIPLIER;
8017                 w.mLayer = curLayer;
8018             } else {
8019                 curBaseLayer = curLayer = w.mBaseLayer;
8020                 w.mLayer = curLayer;
8021             }
8022             if (w.mLayer != oldLayer) {
8023                 layerChanged = true;
8024                 anyLayerChanged = true;
8025             }
8026             final AppWindowToken wtoken = w.mAppToken;
8027             oldLayer = winAnimator.mAnimLayer;
8028             if (w.mTargetAppToken != null) {
8029                 winAnimator.mAnimLayer =
8030                         w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
8031             } else if (wtoken != null) {
8032                 winAnimator.mAnimLayer =
8033                         w.mLayer + wtoken.mAppAnimator.animLayerAdjustment;
8034             } else {
8035                 winAnimator.mAnimLayer = w.mLayer;
8036             }
8037             if (w.mIsImWindow) {
8038                 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
8039             } else if (w.mIsWallpaper) {
8040                 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
8041             }
8042             if (winAnimator.mAnimLayer != oldLayer) {
8043                 layerChanged = true;
8044                 anyLayerChanged = true;
8045             }
8046             if (layerChanged && w.getStack().isDimming(winAnimator)) {
8047                 // Force an animation pass just to update the mDimLayer layer.
8048                 scheduleAnimationLocked();
8049             }
8050             if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
8051                     + "mBase=" + w.mBaseLayer
8052                     + " mLayer=" + w.mLayer
8053                     + (wtoken == null ?
8054                             "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment)
8055                     + " =mAnimLayer=" + winAnimator.mAnimLayer);
8056             //System.out.println(
8057             //    "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
8058         }
8059
8060         //TODO (multidisplay): Magnification is supported only for the default display.
8061         if (mDisplayMagnifier != null && anyLayerChanged
8062                 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
8063             mDisplayMagnifier.onWindowLayersChangedLocked();
8064         }
8065     }
8066
8067     private final void performLayoutAndPlaceSurfacesLocked() {
8068         int loopCount = 6;
8069         do {
8070             mTraversalScheduled = false;
8071             performLayoutAndPlaceSurfacesLockedLoop();
8072             mH.removeMessages(H.DO_TRAVERSAL);
8073             loopCount--;
8074         } while (mTraversalScheduled && loopCount > 0);
8075         mInnerFields.mWallpaperActionPending = false;
8076     }
8077
8078     private boolean mInLayout = false;
8079     private final void performLayoutAndPlaceSurfacesLockedLoop() {
8080         if (mInLayout) {
8081             if (DEBUG) {
8082                 throw new RuntimeException("Recursive call!");
8083             }
8084             Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
8085                     + Debug.getCallers(3));
8086             return;
8087         }
8088
8089         if (mWaitingForConfig) {
8090             // Our configuration has changed (most likely rotation), but we
8091             // don't yet have the complete configuration to report to
8092             // applications.  Don't do any window layout until we have it.
8093             return;
8094         }
8095
8096         if (!mDisplayReady) {
8097             // Not yet initialized, nothing to do.
8098             return;
8099         }
8100
8101         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
8102         mInLayout = true;
8103         boolean recoveringMemory = false;
8104
8105         try {
8106             if (mForceRemoves != null) {
8107                 recoveringMemory = true;
8108                 // Wait a little bit for things to settle down, and off we go.
8109                 for (int i=0; i<mForceRemoves.size(); i++) {
8110                     WindowState ws = mForceRemoves.get(i);
8111                     Slog.i(TAG, "Force removing: " + ws);
8112                     removeWindowInnerLocked(ws.mSession, ws);
8113                 }
8114                 mForceRemoves = null;
8115                 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
8116                 Object tmp = new Object();
8117                 synchronized (tmp) {
8118                     try {
8119                         tmp.wait(250);
8120                     } catch (InterruptedException e) {
8121                     }
8122                 }
8123             }
8124         } catch (RuntimeException e) {
8125             Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
8126         }
8127
8128         try {
8129             performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
8130
8131             mInLayout = false;
8132
8133             if (needsLayout()) {
8134                 if (++mLayoutRepeatCount < 6) {
8135                     requestTraversalLocked();
8136                 } else {
8137                     Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
8138                     mLayoutRepeatCount = 0;
8139                 }
8140             } else {
8141                 mLayoutRepeatCount = 0;
8142             }
8143
8144             if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
8145                 mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
8146                 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE);
8147             }
8148         } catch (RuntimeException e) {
8149             mInLayout = false;
8150             Log.wtf(TAG, "Unhandled exception while laying out windows", e);
8151         }
8152
8153         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
8154     }
8155
8156     private final void performLayoutLockedInner(final DisplayContent displayContent,
8157                                     boolean initial, boolean updateInputWindows) {
8158         if (!displayContent.layoutNeeded) {
8159             return;
8160         }
8161         displayContent.layoutNeeded = false;
8162         WindowList windows = displayContent.getWindowList();
8163         boolean isDefaultDisplay = displayContent.isDefaultDisplay;
8164
8165         DisplayInfo displayInfo = displayContent.getDisplayInfo();
8166         final int dw = displayInfo.logicalWidth;
8167         final int dh = displayInfo.logicalHeight;
8168
8169         final int NFW = mFakeWindows.size();
8170         for (int i=0; i<NFW; i++) {
8171             mFakeWindows.get(i).layout(dw, dh);
8172         }
8173
8174         final int N = windows.size();
8175         int i;
8176
8177         if (DEBUG_LAYOUT) {
8178             Slog.v(TAG, "-------------------------------------");
8179             Slog.v(TAG, "performLayout: needed="
8180                     + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
8181         }
8182
8183         WindowStateAnimator universeBackground = null;
8184
8185         mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
8186         if (isDefaultDisplay) {
8187             // Not needed on non-default displays.
8188             mSystemDecorLayer = mPolicy.getSystemDecorLayerLw();
8189             mScreenRect.set(0, 0, dw, dh);
8190         }
8191
8192         mPolicy.getContentRectLw(mTmpContentRect);
8193         displayContent.setStackBoxSize(mTmpContentRect);
8194
8195         int seq = mLayoutSeq+1;
8196         if (seq < 0) seq = 0;
8197         mLayoutSeq = seq;
8198
8199         boolean behindDream = false;
8200
8201         // First perform layout of any root windows (not attached
8202         // to another window).
8203         int topAttached = -1;
8204         for (i = N-1; i >= 0; i--) {
8205             final WindowState win = windows.get(i);
8206
8207             // Don't do layout of a window if it is not visible, or
8208             // soon won't be visible, to avoid wasting time and funky
8209             // changes while a window is animating away.
8210             final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
8211                     || win.isGoneForLayoutLw();
8212
8213             if (DEBUG_LAYOUT && !win.mLayoutAttached) {
8214                 Slog.v(TAG, "1ST PASS " + win
8215                         + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
8216                         + " mLayoutAttached=" + win.mLayoutAttached
8217                         + " screen changed=" + win.isConfigChanged());
8218                 final AppWindowToken atoken = win.mAppToken;
8219                 if (gone) Slog.v(TAG, "  GONE: mViewVisibility="
8220                         + win.mViewVisibility + " mRelayoutCalled="
8221                         + win.mRelayoutCalled + " hidden="
8222                         + win.mRootToken.hidden + " hiddenRequested="
8223                         + (atoken != null && atoken.hiddenRequested)
8224                         + " mAttachedHidden=" + win.mAttachedHidden);
8225                 else Slog.v(TAG, "  VIS: mViewVisibility="
8226                         + win.mViewVisibility + " mRelayoutCalled="
8227                         + win.mRelayoutCalled + " hidden="
8228                         + win.mRootToken.hidden + " hiddenRequested="
8229                         + (atoken != null && atoken.hiddenRequested)
8230                         + " mAttachedHidden=" + win.mAttachedHidden);
8231             }
8232
8233             // If this view is GONE, then skip it -- keep the current
8234             // frame, and let the caller know so they can ignore it
8235             // if they want.  (We do the normal layout for INVISIBLE
8236             // windows, since that means "perform layout as normal,
8237             // just don't display").
8238             if (!gone || !win.mHaveFrame || win.mLayoutNeeded
8239                     || (win.mAttrs.type == TYPE_KEYGUARD && win.isConfigChanged())
8240                     || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8241                 if (!win.mLayoutAttached) {
8242                     if (initial) {
8243                         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8244                         win.mContentChanged = false;
8245                     }
8246                     if (win.mAttrs.type == TYPE_DREAM) {
8247                         // Don't layout windows behind a dream, so that if it
8248                         // does stuff like hide the status bar we won't get a
8249                         // bad transition when it goes away.
8250                         behindDream = true;
8251                     }
8252                     win.mLayoutNeeded = false;
8253                     win.prelayout();
8254                     mPolicy.layoutWindowLw(win, win.mAttrs, null);
8255                     win.mLayoutSeq = seq;
8256                     if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8257                             + win.mFrame + " mContainingFrame="
8258                             + win.mContainingFrame + " mDisplayFrame="
8259                             + win.mDisplayFrame);
8260                 } else {
8261                     if (topAttached < 0) topAttached = i;
8262                 }
8263             }
8264             if (win.mViewVisibility == View.VISIBLE
8265                     && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
8266                     && universeBackground == null) {
8267                 universeBackground = win.mWinAnimator;
8268             }
8269         }
8270
8271         if (mAnimator.mUniverseBackground  != universeBackground) {
8272             mFocusMayChange = true;
8273             mAnimator.mUniverseBackground = universeBackground;
8274         }
8275
8276         boolean attachedBehindDream = false;
8277
8278         // Now perform layout of attached windows, which usually
8279         // depend on the position of the window they are attached to.
8280         // XXX does not deal with windows that are attached to windows
8281         // that are themselves attached.
8282         for (i = topAttached; i >= 0; i--) {
8283             final WindowState win = windows.get(i);
8284
8285             if (win.mLayoutAttached) {
8286                 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
8287                         + " mHaveFrame=" + win.mHaveFrame
8288                         + " mViewVisibility=" + win.mViewVisibility
8289                         + " mRelayoutCalled=" + win.mRelayoutCalled);
8290                 // If this view is GONE, then skip it -- keep the current
8291                 // frame, and let the caller know so they can ignore it
8292                 // if they want.  (We do the normal layout for INVISIBLE
8293                 // windows, since that means "perform layout as normal,
8294                 // just don't display").
8295                 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
8296                     continue;
8297                 }
8298                 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
8299                         || !win.mHaveFrame || win.mLayoutNeeded) {
8300                     if (initial) {
8301                         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8302                         win.mContentChanged = false;
8303                     }
8304                     win.mLayoutNeeded = false;
8305                     win.prelayout();
8306                     mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
8307                     win.mLayoutSeq = seq;
8308                     if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8309                             + win.mFrame + " mContainingFrame="
8310                             + win.mContainingFrame + " mDisplayFrame="
8311                             + win.mDisplayFrame);
8312                 }
8313             } else if (win.mAttrs.type == TYPE_DREAM) {
8314                 // Don't layout windows behind a dream, so that if it
8315                 // does stuff like hide the status bar we won't get a
8316                 // bad transition when it goes away.
8317                 attachedBehindDream = behindDream;
8318             }
8319         }
8320
8321         // Window frames may have changed.  Tell the input dispatcher about it.
8322         mInputMonitor.setUpdateInputWindowsNeededLw();
8323         if (updateInputWindows) {
8324             mInputMonitor.updateInputWindowsLw(false /*force*/);
8325         }
8326
8327         mPolicy.finishLayoutLw();
8328     }
8329
8330     void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
8331         // If the screen is currently frozen or off, then keep
8332         // it frozen/off until this window draws at its new
8333         // orientation.
8334         if (!okToDisplay()) {
8335             if (DEBUG_ORIENTATION) Slog.v(TAG,
8336                     "Changing surface while display frozen: " + w);
8337             w.mOrientationChanging = true;
8338             w.mLastFreezeDuration = 0;
8339             mInnerFields.mOrientationChangeComplete = false;
8340             if (!mWindowsFreezingScreen) {
8341                 mWindowsFreezingScreen = true;
8342                 // XXX should probably keep timeout from
8343                 // when we first froze the display.
8344                 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8345                 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
8346                         WINDOW_FREEZE_TIMEOUT_DURATION);
8347             }
8348         }
8349     }
8350
8351     /**
8352      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8353      * @param windows List of windows on default display.
8354      * @return bitmap indicating if another pass through layout must be made.
8355      */
8356     public int handleAppTransitionReadyLocked(WindowList windows) {
8357         int changes = 0;
8358         int i;
8359         int NN = mOpeningApps.size();
8360         boolean goodToGo = true;
8361         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8362                 "Checking " + NN + " opening apps (frozen="
8363                 + mDisplayFrozen + " timeout="
8364                 + mAppTransition.isTimeout() + ")...");
8365         if (!mDisplayFrozen && !mAppTransition.isTimeout()) {
8366             // If the display isn't frozen, wait to do anything until
8367             // all of the apps are ready.  Otherwise just go because
8368             // we'll unfreeze the display when everyone is ready.
8369             for (i=0; i<NN && goodToGo; i++) {
8370                 AppWindowToken wtoken = mOpeningApps.get(i);
8371                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8372                         "Check opening app=" + wtoken + ": allDrawn="
8373                         + wtoken.allDrawn + " startingDisplayed="
8374                         + wtoken.startingDisplayed + " startingMoved="
8375                         + wtoken.startingMoved);
8376                 if (!wtoken.allDrawn && !wtoken.startingDisplayed
8377                         && !wtoken.startingMoved) {
8378                     goodToGo = false;
8379                 }
8380             }
8381         }
8382         if (goodToGo) {
8383             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
8384             int transit = mAppTransition.getAppTransition();
8385             if (mSkipAppTransitionAnimation) {
8386                 transit = AppTransition.TRANSIT_UNSET;
8387             }
8388             mAppTransition.goodToGo();
8389             mStartingIconInTransition = false;
8390             mSkipAppTransitionAnimation = false;
8391
8392             mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
8393
8394             rebuildAppWindowListLocked();
8395
8396             // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
8397             WindowState oldWallpaper =
8398                     mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
8399                         && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
8400                     ? null : mWallpaperTarget;
8401
8402             mInnerFields.mWallpaperMayChange = false;
8403
8404             // The top-most window will supply the layout params,
8405             // and we will determine it below.
8406             LayoutParams animLp = null;
8407             int bestAnimLayer = -1;
8408             boolean fullscreenAnim = false;
8409
8410             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8411                     "New wallpaper target=" + mWallpaperTarget
8412                     + ", oldWallpaper=" + oldWallpaper
8413                     + ", lower target=" + mLowerWallpaperTarget
8414                     + ", upper target=" + mUpperWallpaperTarget);
8415
8416             boolean openingAppHasWallpaper = false;
8417             boolean closingAppHasWallpaper = false;
8418             final AppWindowToken lowerWallpaperAppToken;
8419             final AppWindowToken upperWallpaperAppToken;
8420             if (mLowerWallpaperTarget == null) {
8421                 lowerWallpaperAppToken = upperWallpaperAppToken = null;
8422             } else {
8423                 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
8424                 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
8425             }
8426
8427             // Do a first pass through the tokens for two
8428             // things:
8429             // (1) Determine if both the closing and opening
8430             // app token sets are wallpaper targets, in which
8431             // case special animations are needed
8432             // (since the wallpaper needs to stay static
8433             // behind them).
8434             // (2) Find the layout params of the top-most
8435             // application window in the tokens, which is
8436             // what will control the animation theme.
8437             final int NC = mClosingApps.size();
8438             NN = NC + mOpeningApps.size();
8439             for (i=0; i<NN; i++) {
8440                 final AppWindowToken wtoken;
8441                 if (i < NC) {
8442                     wtoken = mClosingApps.get(i);
8443                     if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8444                         closingAppHasWallpaper = true;
8445                     }
8446                 } else {
8447                     wtoken = mOpeningApps.get(i - NC);
8448                     if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8449                         openingAppHasWallpaper = true;
8450                     }
8451                 }
8452
8453                 if (wtoken.appFullscreen) {
8454                     WindowState ws = wtoken.findMainWindow();
8455                     if (ws != null) {
8456                         animLp = ws.mAttrs;
8457                         bestAnimLayer = ws.mLayer;
8458                         fullscreenAnim = true;
8459                     }
8460                 } else if (!fullscreenAnim) {
8461                     WindowState ws = wtoken.findMainWindow();
8462                     if (ws != null) {
8463                         if (ws.mLayer > bestAnimLayer) {
8464                             animLp = ws.mAttrs;
8465                             bestAnimLayer = ws.mLayer;
8466                         }
8467                     }
8468                 }
8469             }
8470
8471             if (closingAppHasWallpaper && openingAppHasWallpaper) {
8472                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
8473                 switch (transit) {
8474                     case AppTransition.TRANSIT_ACTIVITY_OPEN:
8475                     case AppTransition.TRANSIT_TASK_OPEN:
8476                     case AppTransition.TRANSIT_TASK_TO_FRONT:
8477                         transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
8478                         break;
8479                     case AppTransition.TRANSIT_ACTIVITY_CLOSE:
8480                     case AppTransition.TRANSIT_TASK_CLOSE:
8481                     case AppTransition.TRANSIT_TASK_TO_BACK:
8482                         transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
8483                         break;
8484                 }
8485                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
8486             } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
8487                 // We are transitioning from an activity with
8488                 // a wallpaper to one without.
8489                 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
8490                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8491                         "New transit away from wallpaper: " + transit);
8492             } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
8493                 // We are transitioning from an activity without
8494                 // a wallpaper to now showing the wallpaper
8495                 transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
8496                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8497                         "New transit into wallpaper: " + transit);
8498             }
8499
8500             // If all closing windows are obscured, then there is
8501             // no need to do an animation.  This is the case, for
8502             // example, when this transition is being done behind
8503             // the lock screen.
8504             if (!mPolicy.allowAppAnimationsLw()) {
8505                 animLp = null;
8506             }
8507
8508             AppWindowToken topOpeningApp = null;
8509             int topOpeningLayer = 0;
8510
8511             NN = mOpeningApps.size();
8512             for (i=0; i<NN; i++) {
8513                 AppWindowToken wtoken = mOpeningApps.get(i);
8514                 final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
8515                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
8516                 appAnimator.clearThumbnail();
8517                 wtoken.inPendingTransaction = false;
8518                 appAnimator.animation = null;
8519                 setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
8520                 wtoken.updateReportedVisibilityLocked();
8521                 wtoken.waitingToShow = false;
8522
8523                 appAnimator.mAllAppWinAnimators.clear();
8524                 final int N = wtoken.allAppWindows.size();
8525                 for (int j = 0; j < N; j++) {
8526                     appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
8527                 }
8528                 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
8529
8530                 if (animLp != null) {
8531                     int layer = -1;
8532                     for (int j=0; j<wtoken.windows.size(); j++) {
8533                         WindowState win = wtoken.windows.get(j);
8534                         if (win.mWinAnimator.mAnimLayer > layer) {
8535                             layer = win.mWinAnimator.mAnimLayer;
8536                         }
8537                     }
8538                     if (topOpeningApp == null || layer > topOpeningLayer) {
8539                         topOpeningApp = wtoken;
8540                         topOpeningLayer = layer;
8541                     }
8542                 }
8543             }
8544             NN = mClosingApps.size();
8545             for (i=0; i<NN; i++) {
8546                 AppWindowToken wtoken = mClosingApps.get(i);
8547                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8548                         "Now closing app " + wtoken);
8549                 wtoken.mAppAnimator.clearThumbnail();
8550                 wtoken.inPendingTransaction = false;
8551                 wtoken.mAppAnimator.animation = null;
8552                 setTokenVisibilityLocked(wtoken, animLp, false,
8553                         transit, false);
8554                 wtoken.updateReportedVisibilityLocked();
8555                 wtoken.waitingToHide = false;
8556                 // Force the allDrawn flag, because we want to start
8557                 // this guy's animations regardless of whether it's
8558                 // gotten drawn.
8559                 wtoken.allDrawn = true;
8560                 wtoken.deferClearAllDrawn = false;
8561             }
8562
8563             AppWindowAnimator appAnimator =
8564                     topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
8565             Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
8566             if (nextAppTransitionThumbnail != null && appAnimator != null
8567                     && appAnimator.animation != null) {
8568                 // This thumbnail animation is very special, we need to have
8569                 // an extra surface with the thumbnail included with the animation.
8570                 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
8571                         nextAppTransitionThumbnail.getHeight());
8572                 try {
8573                     // TODO(multi-display): support other displays
8574                     final DisplayContent displayContent = getDefaultDisplayContentLocked();
8575                     final Display display = displayContent.getDisplay();
8576                     SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
8577                             "thumbnail anim",
8578                             dirty.width(), dirty.height(),
8579                             PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
8580                     surfaceControl.setLayerStack(display.getLayerStack());
8581                     appAnimator.thumbnail = surfaceControl;
8582                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
8583                     Surface drawSurface = new Surface();
8584                     drawSurface.copyFrom(surfaceControl);
8585                     Canvas c = drawSurface.lockCanvas(dirty);
8586                     c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
8587                     drawSurface.unlockCanvasAndPost(c);
8588                     drawSurface.release();
8589                     appAnimator.thumbnailLayer = topOpeningLayer;
8590                     DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
8591                     Animation anim = mAppTransition.createThumbnailAnimationLocked(
8592                             transit, true, true, displayInfo.appWidth, displayInfo.appHeight);
8593                     appAnimator.thumbnailAnimation = anim;
8594                     anim.restrictDuration(MAX_ANIMATION_DURATION);
8595                     anim.scaleCurrentDuration(mTransitionAnimationScale);
8596                     Point p = new Point();
8597                     mAppTransition.getStartingPoint(p);
8598                     appAnimator.thumbnailX = p.x;
8599                     appAnimator.thumbnailY = p.y;
8600                 } catch (OutOfResourcesException e) {
8601                     Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
8602                             + " h=" + dirty.height(), e);
8603                     appAnimator.clearThumbnail();
8604                 }
8605             }
8606
8607             mAppTransition.postAnimationCallback();
8608             mAppTransition.clear();
8609
8610             mOpeningApps.clear();
8611             mClosingApps.clear();
8612
8613             // This has changed the visibility of windows, so perform
8614             // a new layout to get them all up-to-date.
8615             changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
8616                     | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
8617             getDefaultDisplayContentLocked().layoutNeeded = true;
8618
8619             // TODO(multidisplay): IMEs are only supported on the default display.
8620             if (windows == getDefaultWindowListLocked()
8621                     && !moveInputMethodWindowsIfNeededLocked(true)) {
8622                 assignLayersLocked(windows);
8623             }
8624             updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/);
8625             mFocusMayChange = false;
8626         }
8627
8628         return changes;
8629     }
8630
8631     /**
8632      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8633      * @return bitmap indicating if another pass through layout must be made.
8634      */
8635     private int handleAnimatingStoppedAndTransitionLocked() {
8636         int changes = 0;
8637
8638         mAppTransition.setIdle();
8639         // Restore window app tokens to the ActivityManager views
8640         final DisplayContent displayContent = getDefaultDisplayContentLocked();
8641         final ArrayList<Task> tasks = displayContent.getTasks();
8642         final int numTasks = tasks.size();
8643         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
8644             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8645             final int numTokens = tokens.size();
8646             for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
8647                 final AppWindowToken wtoken = tokens.get(tokenNdx);
8648                 wtoken.sendingToBottom = false;
8649             }
8650         }
8651         rebuildAppWindowListLocked();
8652
8653         changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
8654         if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
8655                 "Wallpaper layer changed: assigning layers + relayout");
8656         moveInputMethodWindowsIfNeededLocked(true);
8657         mInnerFields.mWallpaperMayChange = true;
8658         // Since the window list has been rebuilt, focus might
8659         // have to be recomputed since the actual order of windows
8660         // might have changed again.
8661         mFocusMayChange = true;
8662
8663         return changes;
8664     }
8665
8666     private void updateResizingWindows(final WindowState w) {
8667         final WindowStateAnimator winAnimator = w.mWinAnimator;
8668         if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
8669             w.mOverscanInsetsChanged |=
8670                     !w.mLastOverscanInsets.equals(w.mOverscanInsets);
8671             w.mContentInsetsChanged |=
8672                     !w.mLastContentInsets.equals(w.mContentInsets);
8673             w.mVisibleInsetsChanged |=
8674                     !w.mLastVisibleInsets.equals(w.mVisibleInsets);
8675             boolean configChanged = w.isConfigChanged();
8676             if (DEBUG_CONFIGURATION && configChanged) {
8677                 Slog.v(TAG, "Win " + w + " config changed: "
8678                         + mCurConfiguration);
8679             }
8680             if (localLOGV) Slog.v(TAG, "Resizing " + w
8681                     + ": configChanged=" + configChanged
8682                     + " last=" + w.mLastFrame + " frame=" + w.mFrame);
8683             w.mLastFrame.set(w.mFrame);
8684             if (w.mContentInsetsChanged
8685                     || w.mVisibleInsetsChanged
8686                     || winAnimator.mSurfaceResized
8687                     || configChanged) {
8688                 if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
8689                     Slog.v(TAG, "Resize reasons for w=" + w + ": "
8690                             + " contentInsetsChanged=" + w.mContentInsetsChanged
8691                             + " " + w.mContentInsets.toShortString()
8692                             + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
8693                             + " " + w.mVisibleInsets.toShortString()
8694                             + " surfaceResized=" + winAnimator.mSurfaceResized
8695                             + " configChanged=" + configChanged);
8696                 }
8697
8698                 w.mLastOverscanInsets.set(w.mOverscanInsets);
8699                 w.mLastContentInsets.set(w.mContentInsets);
8700                 w.mLastVisibleInsets.set(w.mVisibleInsets);
8701                 makeWindowFreezingScreenIfNeededLocked(w);
8702                 // If the orientation is changing, then we need to
8703                 // hold off on unfreezing the display until this
8704                 // window has been redrawn; to do that, we need
8705                 // to go through the process of getting informed
8706                 // by the application when it has finished drawing.
8707                 if (w.mOrientationChanging) {
8708                     if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
8709                             "Orientation start waiting for draw mDrawState=DRAW_PENDING in "
8710                             + w + ", surface " + winAnimator.mSurfaceControl);
8711                     winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
8712                     if (w.mAppToken != null) {
8713                         w.mAppToken.allDrawn = false;
8714                         w.mAppToken.deferClearAllDrawn = false;
8715                     }
8716                 }
8717                 if (!mResizingWindows.contains(w)) {
8718                     if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
8719                             "Resizing window " + w + " to " + winAnimator.mSurfaceW
8720                             + "x" + winAnimator.mSurfaceH);
8721                     mResizingWindows.add(w);
8722                 }
8723             } else if (w.mOrientationChanging) {
8724                 if (w.isDrawnLw()) {
8725                     if (DEBUG_ORIENTATION) Slog.v(TAG,
8726                             "Orientation not waiting for draw in "
8727                             + w + ", surface " + winAnimator.mSurfaceControl);
8728                     w.mOrientationChanging = false;
8729                     w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
8730                             - mDisplayFreezeTime);
8731                 }
8732             }
8733         }
8734     }
8735
8736     /**
8737      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8738      *
8739      * @param w WindowState this method is applied to.
8740      * @param currentTime The time which animations use for calculating transitions.
8741      * @param innerDw Width of app window.
8742      * @param innerDh Height of app window.
8743      */
8744     private void handleNotObscuredLocked(final WindowState w, final long currentTime,
8745                                          final int innerDw, final int innerDh) {
8746         final WindowManager.LayoutParams attrs = w.mAttrs;
8747         final int attrFlags = attrs.flags;
8748         final boolean canBeSeen = w.isDisplayedLw();
8749
8750         if (w.mHasSurface) {
8751             if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
8752                 mInnerFields.mHoldScreen = w.mSession;
8753             }
8754             if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0
8755                     && mInnerFields.mScreenBrightness < 0) {
8756                 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness;
8757             }
8758             if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0
8759                     && mInnerFields.mButtonBrightness < 0) {
8760                 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
8761             }
8762             if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
8763                     && mInnerFields.mUserActivityTimeout < 0) {
8764                 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
8765             }
8766
8767             final int type = attrs.type;
8768             if (canBeSeen
8769                     && (type == TYPE_SYSTEM_DIALOG
8770                      || type == TYPE_RECENTS_OVERLAY
8771                      || type == TYPE_KEYGUARD
8772                      || type == TYPE_SYSTEM_ERROR)) {
8773                 mInnerFields.mSyswin = true;
8774             }
8775
8776             if (canBeSeen) {
8777                 if (type == TYPE_DREAM || type == TYPE_KEYGUARD) {
8778                     mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_MIRROR;
8779                 } else if (mInnerFields.mDisplayHasContent
8780                         == LayoutFields.DISPLAY_CONTENT_UNKNOWN) {
8781                     mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNIQUE;
8782                 }
8783             }
8784         }
8785
8786         boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
8787         if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
8788             // This window completely covers everything behind it,
8789             // so we want to leave all of them as undimmed (for
8790             // performance reasons).
8791             mInnerFields.mObscured = true;
8792         }
8793     }
8794
8795     private void handleFlagDimBehind(WindowState w, int innerDw, int innerDh) {
8796         final WindowManager.LayoutParams attrs = w.mAttrs;
8797         if ((attrs.flags & FLAG_DIM_BEHIND) != 0
8798                 && w.isDisplayedLw()
8799                 && !w.mExiting) {
8800             final WindowStateAnimator winAnimator = w.mWinAnimator;
8801             final TaskStack stack = w.getStack();
8802             stack.setDimmingTag();
8803             if (!stack.isDimming(winAnimator)) {
8804                 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
8805                 stack.startDimmingIfNeeded(winAnimator);
8806             }
8807         }
8808     }
8809
8810     private void updateAllDrawnLocked(DisplayContent displayContent) {
8811         // See if any windows have been drawn, so they (and others
8812         // associated with them) can now be shown.
8813         final ArrayList<Task> tasks = displayContent.getTasks();
8814         final int numTasks = tasks.size();
8815         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
8816             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8817             final int numTokens = tokens.size();
8818             for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
8819                 final AppWindowToken wtoken = tokens.get(tokenNdx);
8820                 if (!wtoken.allDrawn) {
8821                     int numInteresting = wtoken.numInterestingWindows;
8822                     if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
8823                         if (DEBUG_VISIBILITY) Slog.v(TAG,
8824                                 "allDrawn: " + wtoken
8825                                 + " interesting=" + numInteresting
8826                                 + " drawn=" + wtoken.numDrawnWindows);
8827                         wtoken.allDrawn = true;
8828                         mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
8829                     }
8830                 }
8831             }
8832         }
8833     }
8834
8835     // "Something has changed!  Let's make it correct now."
8836     private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
8837         if (DEBUG_WINDOW_TRACE) {
8838             Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
8839                     + Debug.getCallers(3));
8840         }
8841
8842         final long currentTime = SystemClock.uptimeMillis();
8843
8844         int i;
8845
8846         if (mFocusMayChange) {
8847             mFocusMayChange = false;
8848             updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
8849                     false /*updateInputWindows*/);
8850         }
8851
8852         // Initialize state of exiting tokens.
8853         final int numDisplays = mDisplayContents.size();
8854         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
8855             final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
8856             for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
8857                 displayContent.mExitingTokens.get(i).hasVisible = false;
8858             }
8859
8860             // Initialize state of exiting applications.
8861             for (i=displayContent.mExitingAppTokens.size()-1; i>=0; i--) {
8862                 displayContent.mExitingAppTokens.get(i).hasVisible = false;
8863             }
8864         }
8865
8866         mInnerFields.mHoldScreen = null;
8867         mInnerFields.mScreenBrightness = -1;
8868         mInnerFields.mButtonBrightness = -1;
8869         mInnerFields.mUserActivityTimeout = -1;
8870         mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN;
8871
8872         mTransactionSequence++;
8873
8874         final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
8875         final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
8876         final int defaultDw = defaultInfo.logicalWidth;
8877         final int defaultDh = defaultInfo.logicalHeight;
8878
8879         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
8880                 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
8881         SurfaceControl.openTransaction();
8882         try {
8883
8884             if (mWatermark != null) {
8885                 mWatermark.positionSurface(defaultDw, defaultDh);
8886             }
8887             if (mStrictModeFlash != null) {
8888                 mStrictModeFlash.positionSurface(defaultDw, defaultDh);
8889             }
8890
8891             boolean focusDisplayed = false;
8892
8893             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
8894                 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
8895                 boolean updateAllDrawn = false;
8896                 WindowList windows = displayContent.getWindowList();
8897                 DisplayInfo displayInfo = displayContent.getDisplayInfo();
8898                 final int displayId = displayContent.getDisplayId();
8899                 final int dw = displayInfo.logicalWidth;
8900                 final int dh = displayInfo.logicalHeight;
8901                 final int innerDw = displayInfo.appWidth;
8902                 final int innerDh = displayInfo.appHeight;
8903                 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
8904
8905                 // Reset for each display unless we are forcing mirroring.
8906                 if (mInnerFields.mDisplayHasContent != LayoutFields.DISPLAY_CONTENT_MIRROR) {
8907                     mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN;
8908                 }
8909
8910                 int repeats = 0;
8911                 do {
8912                     repeats++;
8913                     if (repeats > 6) {
8914                         Slog.w(TAG, "Animation repeat aborted after too many iterations");
8915                         displayContent.layoutNeeded = false;
8916                         break;
8917                     }
8918
8919                     if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
8920                         displayContent.pendingLayoutChanges);
8921
8922                     if ((displayContent.pendingLayoutChanges &
8923                             WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
8924                             (adjustWallpaperWindowsLocked() &
8925                                     ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
8926                         assignLayersLocked(windows);
8927                         displayContent.layoutNeeded = true;
8928                     }
8929
8930                     if (isDefaultDisplay && (displayContent.pendingLayoutChanges
8931                             & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
8932                         if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
8933                         if (updateOrientationFromAppTokensLocked(true)) {
8934                             displayContent.layoutNeeded = true;
8935                             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
8936                         }
8937                     }
8938
8939                     if ((displayContent.pendingLayoutChanges
8940                             & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
8941                         displayContent.layoutNeeded = true;
8942                     }
8943
8944                     // FIRST LOOP: Perform a layout, if needed.
8945                     if (repeats < 4) {
8946                         performLayoutLockedInner(displayContent, repeats == 1,
8947                                 false /*updateInputWindows*/);
8948                     } else {
8949                         Slog.w(TAG, "Layout repeat skipped after too many iterations");
8950                     }
8951
8952                     // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
8953                     // it is animating.
8954                     displayContent.pendingLayoutChanges = 0;
8955
8956                     if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
8957                             + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
8958
8959                     if (isDefaultDisplay) {
8960                         mPolicy.beginPostLayoutPolicyLw(dw, dh);
8961                         for (i = windows.size() - 1; i >= 0; i--) {
8962                             WindowState w = windows.get(i);
8963                             if (w.mHasSurface) {
8964                                 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs);
8965                             }
8966                         }
8967                         displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
8968                         if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
8969                             "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
8970                     }
8971                 } while (displayContent.pendingLayoutChanges != 0);
8972
8973                 mInnerFields.mObscured = false;
8974                 mInnerFields.mSyswin = false;
8975                 displayContent.resetDimming();
8976
8977                 // Only used if default window
8978                 final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
8979
8980                 final int N = windows.size();
8981                 for (i=N-1; i>=0; i--) {
8982                     WindowState w = windows.get(i);
8983
8984                     final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
8985
8986                     // Update effect.
8987                     w.mObscured = mInnerFields.mObscured;
8988                     if (!mInnerFields.mObscured) {
8989                         handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
8990                     }
8991
8992                     if (!w.getStack().testDimmingTag()) {
8993                         handleFlagDimBehind(w, innerDw, innerDh);
8994                     }
8995
8996                     if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
8997                             && w.isVisibleLw()) {
8998                         // This is the wallpaper target and its obscured state
8999                         // changed... make sure the current wallaper's visibility
9000                         // has been updated accordingly.
9001                         updateWallpaperVisibilityLocked();
9002                     }
9003
9004                     final WindowStateAnimator winAnimator = w.mWinAnimator;
9005
9006                     // If the window has moved due to its containing
9007                     // content frame changing, then we'd like to animate
9008                     // it.
9009                     if (w.mHasSurface && w.shouldAnimateMove()) {
9010                         // Frame has moved, containing content frame
9011                         // has also moved, and we're not currently animating...
9012                         // let's do something.
9013                         Animation a = AnimationUtils.loadAnimation(mContext,
9014                                 com.android.internal.R.anim.window_move_from_decor);
9015                         winAnimator.setAnimation(a);
9016                         winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
9017                         winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
9018                         try {
9019                             w.mClient.moved(w.mFrame.left, w.mFrame.top);
9020                         } catch (RemoteException e) {
9021                         }
9022                     }
9023
9024                     //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
9025                     w.mContentChanged = false;
9026
9027                     // Moved from updateWindowsAndWallpaperLocked().
9028                     if (w.mHasSurface) {
9029                         // Take care of the window being ready to display.
9030                         final boolean committed =
9031                                 winAnimator.commitFinishDrawingLocked(currentTime);
9032                         if (isDefaultDisplay && committed) {
9033                             if (w.mAttrs.type == TYPE_DREAM) {
9034                                 // HACK: When a dream is shown, it may at that
9035                                 // point hide the lock screen.  So we need to
9036                                 // redo the layout to let the phone window manager
9037                                 // make this happen.
9038                                 displayContent.pendingLayoutChanges |=
9039                                         WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9040                                 if (DEBUG_LAYOUT_REPEATS) {
9041                                     debugLayoutRepeats(
9042                                         "dream and commitFinishDrawingLocked true",
9043                                         displayContent.pendingLayoutChanges);
9044                                 }
9045                             }
9046                             if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
9047                                 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
9048                                         "First draw done in potential wallpaper target " + w);
9049                                 mInnerFields.mWallpaperMayChange = true;
9050                                 displayContent.pendingLayoutChanges |=
9051                                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9052                                 if (DEBUG_LAYOUT_REPEATS) {
9053                                     debugLayoutRepeats(
9054                                         "wallpaper and commitFinishDrawingLocked true",
9055                                         displayContent.pendingLayoutChanges);
9056                                 }
9057                             }
9058                         }
9059
9060                         winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
9061
9062                         final AppWindowToken atoken = w.mAppToken;
9063                         if (DEBUG_STARTING_WINDOW && atoken != null
9064                                 && w == atoken.startingWindow) {
9065                             Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
9066                                 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
9067                                 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
9068                         }
9069                         if (atoken != null
9070                                 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
9071                             if (atoken.lastTransactionSequence != mTransactionSequence) {
9072                                 atoken.lastTransactionSequence = mTransactionSequence;
9073                                 atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9074                                 atoken.startingDisplayed = false;
9075                             }
9076                             if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
9077                                     && !w.mExiting && !w.mDestroying) {
9078                                 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
9079                                     Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
9080                                             + ", isAnimating=" + winAnimator.isAnimating());
9081                                     if (!w.isDrawnLw()) {
9082                                         Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
9083                                                 + " pv=" + w.mPolicyVisibility
9084                                                 + " mDrawState=" + winAnimator.mDrawState
9085                                                 + " ah=" + w.mAttachedHidden
9086                                                 + " th=" + atoken.hiddenRequested
9087                                                 + " a=" + winAnimator.mAnimating);
9088                                     }
9089                                 }
9090                                 if (w != atoken.startingWindow) {
9091                                     if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
9092                                         atoken.numInterestingWindows++;
9093                                         if (w.isDrawnLw()) {
9094                                             atoken.numDrawnWindows++;
9095                                             if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
9096                                                     "tokenMayBeDrawn: " + atoken
9097                                                     + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
9098                                                     + " mAppFreezing=" + w.mAppFreezing);
9099                                             updateAllDrawn = true;
9100                                         }
9101                                     }
9102                                 } else if (w.isDrawnLw()) {
9103                                     atoken.startingDisplayed = true;
9104                                 }
9105                             }
9106                         }
9107                     }
9108
9109                     if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
9110                             && w.isDisplayedLw()) {
9111                         focusDisplayed = true;
9112                     }
9113
9114                     updateResizingWindows(w);
9115                 }
9116
9117                 final boolean hasUniqueContent;
9118                 switch (mInnerFields.mDisplayHasContent) {
9119                     case LayoutFields.DISPLAY_CONTENT_MIRROR:
9120                         hasUniqueContent = isDefaultDisplay;
9121                         break;
9122                     case LayoutFields.DISPLAY_CONTENT_UNIQUE:
9123                         hasUniqueContent = true;
9124                         break;
9125                     case LayoutFields.DISPLAY_CONTENT_UNKNOWN:
9126                     default:
9127                         hasUniqueContent = false;
9128                         break;
9129                 }
9130                 mDisplayManagerService.setDisplayHasContent(displayId, hasUniqueContent,
9131                         true /* inTraversal, must call performTraversalInTrans... below */);
9132
9133                 getDisplayContentLocked(displayId).stopDimmingIfNeeded();
9134
9135                 if (updateAllDrawn) {
9136                     updateAllDrawnLocked(displayContent);
9137                 }
9138             }
9139
9140             if (focusDisplayed) {
9141                 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
9142             }
9143
9144             // Give the display manager a chance to adjust properties
9145             // like display rotation if it needs to.
9146             mDisplayManagerService.performTraversalInTransactionFromWindowManager();
9147
9148         } catch (RuntimeException e) {
9149             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
9150         } finally {
9151             SurfaceControl.closeTransaction();
9152             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9153                     "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
9154         }
9155
9156         final WindowList defaultWindows = defaultDisplay.getWindowList();
9157
9158         // If we are ready to perform an app transition, check through
9159         // all of the app tokens to be shown and see if they are ready
9160         // to go.
9161         if (mAppTransition.isReady()) {
9162             defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
9163             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
9164                     defaultDisplay.pendingLayoutChanges);
9165         }
9166
9167         if (!mAnimator.mAnimating && mAppTransition.isRunning()) {
9168             // We have finished the animation of an app transition.  To do
9169             // this, we have delayed a lot of operations like showing and
9170             // hiding apps, moving apps in Z-order, etc.  The app token list
9171             // reflects the correct Z-order, but the window list may now
9172             // be out of sync with it.  So here we will just rebuild the
9173             // entire app window list.  Fun!
9174             defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
9175             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
9176                 defaultDisplay.pendingLayoutChanges);
9177         }
9178
9179         if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
9180                 && !mAppTransition.isReady()) {
9181             // At this point, there was a window with a wallpaper that
9182             // was force hiding other windows behind it, but now it
9183             // is going away.  This may be simple -- just animate
9184             // away the wallpaper and its window -- or it may be
9185             // hard -- the wallpaper now needs to be shown behind
9186             // something that was hidden.
9187             defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9188             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
9189                 defaultDisplay.pendingLayoutChanges);
9190         }
9191         mInnerFields.mWallpaperForceHidingChanged = false;
9192
9193         if (mInnerFields.mWallpaperMayChange) {
9194             if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
9195             defaultDisplay.pendingLayoutChanges |=
9196                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9197             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
9198                     defaultDisplay.pendingLayoutChanges);
9199         }
9200
9201         if (mFocusMayChange) {
9202             mFocusMayChange = false;
9203             if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
9204                     false /*updateInputWindows*/)) {
9205                 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
9206             }
9207         }
9208
9209         if (needsLayout()) {
9210             defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9211             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
9212                     defaultDisplay.pendingLayoutChanges);
9213         }
9214
9215         for (i = mResizingWindows.size() - 1; i >= 0; i--) {
9216             WindowState win = mResizingWindows.get(i);
9217             if (win.mAppFreezing) {
9218                 // Don't remove this window until rotation has completed.
9219                 continue;
9220             }
9221             final WindowStateAnimator winAnimator = win.mWinAnimator;
9222             try {
9223                 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
9224                         "Reporting new frame to " + win + ": " + win.mCompatFrame);
9225                 int diff = 0;
9226                 boolean configChanged = win.isConfigChanged();
9227                 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
9228                         && configChanged) {
9229                     Slog.i(TAG, "Sending new config to window " + win + ": "
9230                             + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH
9231                             + " / " + mCurConfiguration + " / 0x"
9232                             + Integer.toHexString(diff));
9233                 }
9234                 win.setConfiguration(mCurConfiguration);
9235                 if (DEBUG_ORIENTATION &&
9236                         winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(
9237                         TAG, "Resizing " + win + " WITH DRAW PENDING");
9238                 final IWindow client = win.mClient;
9239                 final Rect frame = win.mFrame;
9240                 final Rect overscanInsets = win.mLastOverscanInsets;
9241                 final Rect contentInsets = win.mLastContentInsets;
9242                 final Rect visibleInsets = win.mLastVisibleInsets;
9243                 final boolean reportDraw
9244                         = winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING;
9245                 final Configuration newConfig = configChanged ? win.mConfiguration : null;
9246                 if (win.mClient instanceof IWindow.Stub) {
9247                     // To prevent deadlock simulate one-way call if win.mClient is a local object.
9248                     mH.post(new Runnable() {
9249                         @Override
9250                         public void run() {
9251                             try {
9252                                 client.resized(frame, overscanInsets, contentInsets,
9253                                         visibleInsets, reportDraw, newConfig);
9254                             } catch (RemoteException e) {
9255                                 // Not a remote call, RemoteException won't be raised.
9256                             }
9257                         }
9258                     });
9259                 } else {
9260                    client.resized(frame, overscanInsets, contentInsets, visibleInsets, reportDraw,
9261                            newConfig);
9262                 }
9263                 win.mOverscanInsetsChanged = false;
9264                 win.mContentInsetsChanged = false;
9265                 win.mVisibleInsetsChanged = false;
9266                 winAnimator.mSurfaceResized = false;
9267             } catch (RemoteException e) {
9268                 win.mOrientationChanging = false;
9269                 win.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
9270                         - mDisplayFreezeTime);
9271             }
9272             mResizingWindows.remove(i);
9273         }
9274
9275         if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
9276                 "With display frozen, orientationChangeComplete="
9277                 + mInnerFields.mOrientationChangeComplete);
9278         if (mInnerFields.mOrientationChangeComplete) {
9279             if (mWindowsFreezingScreen) {
9280                 mWindowsFreezingScreen = false;
9281                 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource;
9282                 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9283             }
9284             stopFreezingDisplayLocked();
9285         }
9286
9287         // Destroy the surface of any windows that are no longer visible.
9288         boolean wallpaperDestroyed = false;
9289         i = mDestroySurface.size();
9290         if (i > 0) {
9291             do {
9292                 i--;
9293                 WindowState win = mDestroySurface.get(i);
9294                 win.mDestroying = false;
9295                 if (mInputMethodWindow == win) {
9296                     mInputMethodWindow = null;
9297                 }
9298                 if (win == mWallpaperTarget) {
9299                     wallpaperDestroyed = true;
9300                 }
9301                 win.mWinAnimator.destroySurfaceLocked();
9302             } while (i > 0);
9303             mDestroySurface.clear();
9304         }
9305
9306         // Time to remove any exiting tokens?
9307         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9308             final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9309             ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
9310             for (i = exitingTokens.size() - 1; i >= 0; i--) {
9311                 WindowToken token = exitingTokens.get(i);
9312                 if (!token.hasVisible) {
9313                     exitingTokens.remove(i);
9314                     if (token.windowType == TYPE_WALLPAPER) {
9315                         mWallpaperTokens.remove(token);
9316                     }
9317                 }
9318             }
9319
9320             // Time to remove any exiting applications?
9321             AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
9322             for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
9323                 AppWindowToken token = exitingAppTokens.get(i);
9324                 if (!token.hasVisible && !mClosingApps.contains(token)) {
9325                     // Make sure there is no animation running on this token,
9326                     // so any windows associated with it will be removed as
9327                     // soon as their animations are complete
9328                     token.mAppAnimator.clearAnimation();
9329                     token.mAppAnimator.animating = false;
9330                     if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
9331                             "performLayout: App token exiting now removed" + token);
9332                     final Task task = mTaskIdToTask.get(token.groupId);
9333                     if (task != null && task.removeAppToken(token)) {
9334                         mTaskIdToTask.delete(token.groupId);
9335                     }
9336                     exitingAppTokens.remove(i);
9337                 }
9338             }
9339         }
9340
9341         if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
9342             for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
9343                 try {
9344                     mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
9345                 } catch (RemoteException e) {
9346                 }
9347             }
9348             mRelayoutWhileAnimating.clear();
9349         }
9350
9351         if (wallpaperDestroyed) {
9352             defaultDisplay.pendingLayoutChanges |=
9353                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9354             defaultDisplay.layoutNeeded = true;
9355         }
9356
9357         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9358             final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9359             if (displayContent.pendingLayoutChanges != 0) {
9360                 displayContent.layoutNeeded = true;
9361             }
9362         }
9363
9364         // Finally update all input windows now that the window changes have stabilized.
9365         mInputMonitor.updateInputWindowsLw(true /*force*/);
9366
9367         setHoldScreenLocked(mInnerFields.mHoldScreen);
9368         if (!mDisplayFrozen) {
9369             if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
9370                 mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1);
9371             } else {
9372                 mPowerManager.setScreenBrightnessOverrideFromWindowManager(
9373                         toBrightnessOverride(mInnerFields.mScreenBrightness));
9374             }
9375             if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
9376                 mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1);
9377             } else {
9378                 mPowerManager.setButtonBrightnessOverrideFromWindowManager(
9379                         toBrightnessOverride(mInnerFields.mButtonBrightness));
9380             }
9381             mPowerManager.setUserActivityTimeoutOverrideFromWindowManager(
9382                     mInnerFields.mUserActivityTimeout);
9383         }
9384
9385         if (mTurnOnScreen) {
9386             if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
9387             mPowerManager.wakeUp(SystemClock.uptimeMillis());
9388             mTurnOnScreen = false;
9389         }
9390
9391         if (mInnerFields.mUpdateRotation) {
9392             if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
9393             if (updateRotationUncheckedLocked(false)) {
9394                 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9395             } else {
9396                 mInnerFields.mUpdateRotation = false;
9397             }
9398         }
9399
9400         if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded
9401                 && !mInnerFields.mUpdateRotation) {
9402             checkDrawnWindowsLocked();
9403         }
9404
9405         final int N = mPendingRemove.size();
9406         if (N > 0) {
9407             if (mPendingRemoveTmp.length < N) {
9408                 mPendingRemoveTmp = new WindowState[N+10];
9409             }
9410             mPendingRemove.toArray(mPendingRemoveTmp);
9411             mPendingRemove.clear();
9412             DisplayContentList displayList = new DisplayContentList();
9413             for (i = 0; i < N; i++) {
9414                 WindowState w = mPendingRemoveTmp[i];
9415                 removeWindowInnerLocked(w.mSession, w);
9416                 if (!displayList.contains(w.mDisplayContent)) {
9417                     displayList.add(w.mDisplayContent);
9418                 }
9419             }
9420
9421             for (DisplayContent displayContent : displayList) {
9422                 assignLayersLocked(displayContent.getWindowList());
9423                 displayContent.layoutNeeded = true;
9424             }
9425         }
9426
9427         setFocusedStackFrame();
9428
9429         // Check to see if we are now in a state where the screen should
9430         // be enabled, because the window obscured flags have changed.
9431         enableScreenIfNeededLocked();
9432
9433         scheduleAnimationLocked();
9434
9435         if (DEBUG_WINDOW_TRACE) {
9436             Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
9437                     + mAnimator.mAnimating);
9438         }
9439     }
9440
9441     private int toBrightnessOverride(float value) {
9442         return (int)(value * PowerManager.BRIGHTNESS_ON);
9443     }
9444
9445     void checkDrawnWindowsLocked() {
9446         if (mWaitingForDrawn.size() > 0) {
9447             for (int j=mWaitingForDrawn.size()-1; j>=0; j--) {
9448                 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j);
9449                 WindowState win = pair.first;
9450                 //Slog.i(TAG, "Waiting for drawn " + win + ": removed="
9451                 //        + win.mRemoved + " visible=" + win.isVisibleLw()
9452                 //        + " shown=" + win.mSurfaceShown);
9453                 if (win.mRemoved) {
9454                     // Window has been removed; no draw will now happen, so stop waiting.
9455                     Slog.w(TAG, "Aborted waiting for drawn: " + pair.first);
9456                     try {
9457                         pair.second.sendResult(null);
9458                     } catch (RemoteException e) {
9459                     }
9460                     mWaitingForDrawn.remove(pair);
9461                     mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9462                 } else if (win.mWinAnimator.mSurfaceShown) {
9463                     // Window is now drawn (and shown).
9464                     try {
9465                         pair.second.sendResult(null);
9466                     } catch (RemoteException e) {
9467                     }
9468                     mWaitingForDrawn.remove(pair);
9469                     mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9470                 }
9471             }
9472         }
9473     }
9474
9475     @Override
9476     public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
9477         if (token != null && callback != null) {
9478             synchronized (mWindowMap) {
9479                 WindowState win = windowForClientLocked(null, token, true);
9480                 if (win != null) {
9481                     Pair<WindowState, IRemoteCallback> pair =
9482                             new Pair<WindowState, IRemoteCallback>(win, callback);
9483                     Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9484                     mH.sendMessageDelayed(m, 2000);
9485                     mWaitingForDrawn.add(pair);
9486                     checkDrawnWindowsLocked();
9487                     return true;
9488                 }
9489                 Slog.i(TAG, "waitForWindowDrawn: win null");
9490             }
9491         }
9492         return false;
9493     }
9494
9495     void setHoldScreenLocked(final Session newHoldScreen) {
9496         final boolean hold = newHoldScreen != null;
9497
9498         if (hold && mHoldingScreenOn != newHoldScreen) {
9499             mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
9500         }
9501         mHoldingScreenOn = newHoldScreen;
9502
9503         final boolean state = mHoldingScreenWakeLock.isHeld();
9504         if (hold != state) {
9505             if (hold) {
9506                 mHoldingScreenWakeLock.acquire();
9507                 mPolicy.keepScreenOnStartedLw();
9508             } else {
9509                 mPolicy.keepScreenOnStoppedLw();
9510                 mHoldingScreenWakeLock.release();
9511             }
9512         }
9513     }
9514
9515     @Override
9516     public void requestTraversal() {
9517         synchronized (mWindowMap) {
9518             requestTraversalLocked();
9519         }
9520     }
9521
9522     void requestTraversalLocked() {
9523         if (!mTraversalScheduled) {
9524             mTraversalScheduled = true;
9525             mH.sendEmptyMessage(H.DO_TRAVERSAL);
9526         }
9527     }
9528
9529     /** Note that Locked in this case is on mLayoutToAnim */
9530     void scheduleAnimationLocked() {
9531         if (!mAnimationScheduled) {
9532             mAnimationScheduled = true;
9533             mChoreographer.postCallback(
9534                     Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
9535         }
9536     }
9537
9538     private boolean needsLayout() {
9539         final int numDisplays = mDisplayContents.size();
9540         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9541             final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9542             if (displayContent.layoutNeeded) {
9543                 return true;
9544             }
9545         }
9546         return false;
9547     }
9548
9549     boolean copyAnimToLayoutParamsLocked() {
9550         boolean doRequest = false;
9551
9552         final int bulkUpdateParams = mAnimator.mBulkUpdateParams;
9553         if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
9554             mInnerFields.mUpdateRotation = true;
9555             doRequest = true;
9556         }
9557         if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
9558             mInnerFields.mWallpaperMayChange = true;
9559             doRequest = true;
9560         }
9561         if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
9562             mInnerFields.mWallpaperForceHidingChanged = true;
9563             doRequest = true;
9564         }
9565         if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
9566             mInnerFields.mOrientationChangeComplete = false;
9567         } else {
9568             mInnerFields.mOrientationChangeComplete = true;
9569             mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource;
9570             if (mWindowsFreezingScreen) {
9571                 doRequest = true;
9572             }
9573         }
9574         if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
9575             mTurnOnScreen = true;
9576         }
9577         if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) {
9578             mInnerFields.mWallpaperActionPending = true;
9579         }
9580
9581         return doRequest;
9582     }
9583
9584     /** If a window that has an animation specifying a colored background and the current wallpaper
9585      * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
9586      * suddenly disappear. */
9587     int adjustAnimationBackground(WindowStateAnimator winAnimator) {
9588         WindowList windows = winAnimator.mWin.getWindowList();
9589         for (int i = windows.size() - 1; i >= 0; --i) {
9590             WindowState testWin = windows.get(i);
9591             if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
9592                 return testWin.mWinAnimator.mAnimLayer;
9593             }
9594         }
9595         return winAnimator.mAnimLayer;
9596     }
9597
9598     boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
9599                                            boolean secure) {
9600         final SurfaceControl surface = winAnimator.mSurfaceControl;
9601         boolean leakedSurface = false;
9602         boolean killedApps = false;
9603
9604         EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
9605                 winAnimator.mSession.mPid, operation);
9606
9607         if (mForceRemoves == null) {
9608             mForceRemoves = new ArrayList<WindowState>();
9609         }
9610
9611         long callingIdentity = Binder.clearCallingIdentity();
9612         try {
9613             // There was some problem...   first, do a sanity check of the
9614             // window list to make sure we haven't left any dangling surfaces
9615             // around.
9616
9617             Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
9618             final int numDisplays = mDisplayContents.size();
9619             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9620                 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9621                 final int numWindows = windows.size();
9622                 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9623                     final WindowState ws = windows.get(winNdx);
9624                     WindowStateAnimator wsa = ws.mWinAnimator;
9625                     if (wsa.mSurfaceControl != null) {
9626                         if (!mSessions.contains(wsa.mSession)) {
9627                             Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
9628                                     + ws + " surface=" + wsa.mSurfaceControl
9629                                     + " token=" + ws.mToken
9630                                     + " pid=" + ws.mSession.mPid
9631                                     + " uid=" + ws.mSession.mUid);
9632                             if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9633                             wsa.mSurfaceControl.destroy();
9634                             wsa.mSurfaceShown = false;
9635                             wsa.mSurfaceControl = null;
9636                             ws.mHasSurface = false;
9637                             mForceRemoves.add(ws);
9638                             leakedSurface = true;
9639                         } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
9640                             Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
9641                                     + ws + " surface=" + wsa.mSurfaceControl
9642                                     + " token=" + ws.mAppToken);
9643                             if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9644                             wsa.mSurfaceControl.destroy();
9645                             wsa.mSurfaceShown = false;
9646                             wsa.mSurfaceControl = null;
9647                             ws.mHasSurface = false;
9648                             leakedSurface = true;
9649                         }
9650                     }
9651                 }
9652             }
9653
9654             if (!leakedSurface) {
9655                 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
9656                 SparseIntArray pidCandidates = new SparseIntArray();
9657                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9658                     final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9659                     final int numWindows = windows.size();
9660                     for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9661                         final WindowState ws = windows.get(winNdx);
9662                         if (mForceRemoves.contains(ws)) {
9663                             continue;
9664                         }
9665                         WindowStateAnimator wsa = ws.mWinAnimator;
9666                         if (wsa.mSurfaceControl != null) {
9667                             pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
9668                         }
9669                     }
9670                     if (pidCandidates.size() > 0) {
9671                         int[] pids = new int[pidCandidates.size()];
9672                         for (int i=0; i<pids.length; i++) {
9673                             pids[i] = pidCandidates.keyAt(i);
9674                         }
9675                         try {
9676                             if (mActivityManager.killPids(pids, "Free memory", secure)) {
9677                                 killedApps = true;
9678                             }
9679                         } catch (RemoteException e) {
9680                         }
9681                     }
9682                 }
9683             }
9684
9685             if (leakedSurface || killedApps) {
9686                 // We managed to reclaim some memory, so get rid of the trouble
9687                 // surface and ask the app to request another one.
9688                 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
9689                 if (surface != null) {
9690                     if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
9691                             "RECOVER DESTROY", null);
9692                     surface.destroy();
9693                     winAnimator.mSurfaceShown = false;
9694                     winAnimator.mSurfaceControl = null;
9695                     winAnimator.mWin.mHasSurface = false;
9696                     scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken);
9697                 }
9698
9699                 try {
9700                     winAnimator.mWin.mClient.dispatchGetNewSurface();
9701                 } catch (RemoteException e) {
9702                 }
9703             }
9704         } finally {
9705             Binder.restoreCallingIdentity(callingIdentity);
9706         }
9707
9708         return leakedSurface || killedApps;
9709     }
9710
9711     private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
9712         WindowState newFocus = computeFocusedWindowLocked();
9713         if (mCurrentFocus != newFocus) {
9714             Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
9715             // This check makes sure that we don't already have the focus
9716             // change message pending.
9717             mH.removeMessages(H.REPORT_FOCUS_CHANGE);
9718             mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
9719             // TODO(multidisplay): Focused windows on default display only.
9720             final DisplayContent displayContent = getDefaultDisplayContentLocked();
9721             final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
9722                     mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
9723                             && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
9724             if (imWindowChanged) {
9725                 displayContent.layoutNeeded = true;
9726                 newFocus = computeFocusedWindowLocked();
9727             }
9728
9729             if (true || DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " +
9730                     mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
9731             final WindowState oldFocus = mCurrentFocus;
9732             mCurrentFocus = newFocus;
9733             mLosingFocus.remove(newFocus);
9734             int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
9735
9736             if (imWindowChanged && oldFocus != mInputMethodWindow) {
9737                 // Focus of the input method window changed. Perform layout if needed.
9738                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9739                     performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9740                     focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9741                 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
9742                     // Client will do the layout, but we need to assign layers
9743                     // for handleNewWindowLocked() below.
9744                     assignLayersLocked(displayContent.getWindowList());
9745                 }
9746             }
9747
9748             if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9749                 // The change in focus caused us to need to do a layout.  Okay.
9750                 displayContent.layoutNeeded = true;
9751                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9752                     performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9753                 }
9754             }
9755
9756             if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
9757                 // If we defer assigning layers, then the caller is responsible for
9758                 // doing this part.
9759                 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows);
9760             }
9761
9762             Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
9763             return true;
9764         }
9765         return false;
9766     }
9767
9768     private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) {
9769         mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
9770     }
9771
9772     private WindowState computeFocusedWindowLocked() {
9773         if (mAnimator.mUniverseBackground != null
9774                 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
9775             return mAnimator.mUniverseBackground.mWin;
9776         }
9777
9778         final int displayCount = mDisplayContents.size();
9779         for (int i = 0; i < displayCount; i++) {
9780             final DisplayContent displayContent = mDisplayContents.valueAt(i);
9781             WindowState win = findFocusedWindowLocked(displayContent);
9782             if (win != null) {
9783                 return win;
9784             }
9785         }
9786         return null;
9787     }
9788
9789     private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
9790         final WindowList windows = displayContent.getWindowList();
9791         for (int i = windows.size() - 1; i >= 0; i--) {
9792             final WindowState win = windows.get(i);
9793
9794             if (localLOGV || DEBUG_FOCUS) Slog.v(
9795                 TAG, "Looking for focus: " + i
9796                 + " = " + win
9797                 + ", flags=" + win.mAttrs.flags
9798                 + ", canReceive=" + win.canReceiveKeys());
9799
9800             AppWindowToken wtoken = win.mAppToken;
9801
9802             // If this window's application has been removed, just skip it.
9803             if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
9804                 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because "
9805                         + (wtoken.removed ? "removed" : "sendingToBottom"));
9806                 continue;
9807             }
9808
9809             if (!win.canReceiveKeys()) {
9810                 continue;
9811             }
9812
9813             // Descend through all of the app tokens and find the first that either matches
9814             // win.mAppToken (return win) or mFocusedApp (return null).
9815             if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
9816                     mFocusedApp != null) {
9817                 ArrayList<Task> tasks = displayContent.getTasks();
9818                 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9819                     AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9820                     int tokenNdx = tokens.size() - 1;
9821                     for ( ; tokenNdx >= 0; --tokenNdx) {
9822                         final AppWindowToken token = tokens.get(tokenNdx);
9823                         if (wtoken == token) {
9824                             break;
9825                         }
9826                         if (mFocusedApp == token) {
9827                             // Whoops, we are below the focused app...  no focus for you!
9828                             if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG,
9829                                     "findFocusedWindow: Reached focused app=" + mFocusedApp);
9830                             return null;
9831                         }
9832                     }
9833                     if (tokenNdx >= 0) {
9834                         // Early exit from loop, must have found the matching token.
9835                         break;
9836                     }
9837                 }
9838             }
9839
9840             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i +
9841                         " = " + win);
9842             return win;
9843         }
9844
9845         if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows.");
9846         return null;
9847     }
9848
9849     private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
9850         if (mDisplayFrozen) {
9851             return;
9852         }
9853
9854         if (!mDisplayReady || !mPolicy.isScreenOnFully()) {
9855             // No need to freeze the screen before the system is ready or if
9856             // the screen is off.
9857             return;
9858         }
9859
9860         mScreenFrozenLock.acquire();
9861
9862         mDisplayFrozen = true;
9863         mDisplayFreezeTime = SystemClock.elapsedRealtime();
9864         mLastFinishedFreezeSource = null;
9865
9866         mInputMonitor.freezeInputDispatchingLw();
9867
9868         // Clear the last input window -- that is just used for
9869         // clean transitions between IMEs, and if we are freezing
9870         // the screen then the whole world is changing behind the scenes.
9871         mPolicy.setLastInputMethodWindowLw(null, null);
9872
9873         if (mAppTransition.isTransitionSet()) {
9874             mAppTransition.freeze();
9875         }
9876
9877         if (PROFILE_ORIENTATION) {
9878             File file = new File("/data/system/frozen");
9879             Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
9880         }
9881
9882         if (CUSTOM_SCREEN_ROTATION) {
9883             mExitAnimId = exitAnim;
9884             mEnterAnimId = enterAnim;
9885             final DisplayContent displayContent = getDefaultDisplayContentLocked();
9886             final int displayId = displayContent.getDisplayId();
9887             ScreenRotationAnimation screenRotationAnimation =
9888                     mAnimator.getScreenRotationAnimationLocked(displayId);
9889             if (screenRotationAnimation != null) {
9890                 screenRotationAnimation.kill();
9891             }
9892
9893             // TODO(multidisplay): rotation on main screen only.
9894             screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
9895                     mFxSession, inTransaction, mPolicy.isDefaultOrientationForced());
9896             mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9897         }
9898     }
9899
9900     private void stopFreezingDisplayLocked() {
9901         if (!mDisplayFrozen) {
9902             return;
9903         }
9904
9905         if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
9906                 || mClientFreezingScreen) {
9907             if (DEBUG_ORIENTATION) Slog.d(TAG,
9908                 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
9909                 + ", mAppsFreezingScreen=" + mAppsFreezingScreen
9910                 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
9911                 + ", mClientFreezingScreen=" + mClientFreezingScreen);
9912             return;
9913         }
9914
9915         mDisplayFrozen = false;
9916         mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
9917         StringBuilder sb = new StringBuilder(128);
9918         sb.append("Screen frozen for ");
9919         TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
9920         if (mLastFinishedFreezeSource != null) {
9921             sb.append(" due to ");
9922             sb.append(mLastFinishedFreezeSource);
9923         }
9924         Slog.i(TAG, sb.toString());
9925         mH.removeMessages(H.APP_FREEZE_TIMEOUT);
9926         mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
9927         if (PROFILE_ORIENTATION) {
9928             Debug.stopMethodTracing();
9929         }
9930
9931         boolean updateRotation = false;
9932
9933         final DisplayContent displayContent = getDefaultDisplayContentLocked();
9934         final int displayId = displayContent.getDisplayId();
9935         ScreenRotationAnimation screenRotationAnimation =
9936                 mAnimator.getScreenRotationAnimationLocked(displayId);
9937         if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
9938                 && screenRotationAnimation.hasScreenshot()) {
9939             if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
9940             // TODO(multidisplay): rotation on main screen only.
9941             DisplayInfo displayInfo = displayContent.getDisplayInfo();
9942             // Get rotation animation again, with new top window
9943             boolean isDimming = displayContent.isDimming();
9944             if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
9945                 mExitAnimId = mEnterAnimId = 0;
9946             }
9947             if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
9948                     mTransitionAnimationScale, displayInfo.logicalWidth,
9949                         displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
9950                 scheduleAnimationLocked();
9951             } else {
9952                 screenRotationAnimation.kill();
9953                 screenRotationAnimation = null;
9954                 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9955                 updateRotation = true;
9956             }
9957         } else {
9958             if (screenRotationAnimation != null) {
9959                 screenRotationAnimation.kill();
9960                 screenRotationAnimation = null;
9961                 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9962             }
9963             updateRotation = true;
9964         }
9965
9966         mInputMonitor.thawInputDispatchingLw();
9967
9968         boolean configChanged;
9969
9970         // While the display is frozen we don't re-compute the orientation
9971         // to avoid inconsistent states.  However, something interesting
9972         // could have actually changed during that time so re-evaluate it
9973         // now to catch that.
9974         configChanged = updateOrientationFromAppTokensLocked(false);
9975
9976         // A little kludge: a lot could have happened while the
9977         // display was frozen, so now that we are coming back we
9978         // do a gc so that any remote references the system
9979         // processes holds on others can be released if they are
9980         // no longer needed.
9981         mH.removeMessages(H.FORCE_GC);
9982         mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
9983
9984         mScreenFrozenLock.release();
9985
9986         if (updateRotation) {
9987             if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
9988             configChanged |= updateRotationUncheckedLocked(false);
9989         }
9990
9991         if (configChanged) {
9992             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9993         }
9994     }
9995
9996     static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
9997             DisplayMetrics dm) {
9998         if (index < tokens.length) {
9999             String str = tokens[index];
10000             if (str != null && str.length() > 0) {
10001                 try {
10002                     int val = Integer.parseInt(str);
10003                     return val;
10004                 } catch (Exception e) {
10005                 }
10006             }
10007         }
10008         if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
10009             return defDps;
10010         }
10011         int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
10012         return val;
10013     }
10014
10015     void createWatermarkInTransaction() {
10016         if (mWatermark != null) {
10017             return;
10018         }
10019
10020         File file = new File("/system/etc/setup.conf");
10021         FileInputStream in = null;
10022         DataInputStream ind = null;
10023         try {
10024             in = new FileInputStream(file);
10025             ind = new DataInputStream(in);
10026             String line = ind.readLine();
10027             if (line != null) {
10028                 String[] toks = line.split("%");
10029                 if (toks != null && toks.length > 0) {
10030                     mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
10031                             mRealDisplayMetrics, mFxSession, toks);
10032                 }
10033             }
10034         } catch (FileNotFoundException e) {
10035         } catch (IOException e) {
10036         } finally {
10037             if (ind != null) {
10038                 try {
10039                     ind.close();
10040                 } catch (IOException e) {
10041                 }
10042             } else if (in != null) {
10043                 try {
10044                     in.close();
10045                 } catch (IOException e) {
10046                 }
10047             }
10048         }
10049     }
10050
10051     @Override
10052     public void statusBarVisibilityChanged(int visibility) {
10053         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
10054                 != PackageManager.PERMISSION_GRANTED) {
10055             throw new SecurityException("Caller does not hold permission "
10056                     + android.Manifest.permission.STATUS_BAR);
10057         }
10058
10059         synchronized (mWindowMap) {
10060             mLastStatusBarVisibility = visibility;
10061             visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
10062             updateStatusBarVisibilityLocked(visibility);
10063         }
10064     }
10065
10066     // TOOD(multidisplay): StatusBar on multiple screens?
10067     void updateStatusBarVisibilityLocked(int visibility) {
10068         mInputManager.setSystemUiVisibility(visibility);
10069         final WindowList windows = getDefaultWindowListLocked();
10070         final int N = windows.size();
10071         for (int i = 0; i < N; i++) {
10072             WindowState ws = windows.get(i);
10073             try {
10074                 int curValue = ws.mSystemUiVisibility;
10075                 int diff = curValue ^ visibility;
10076                 // We are only interested in differences of one of the
10077                 // clearable flags...
10078                 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
10079                 // ...if it has actually been cleared.
10080                 diff &= ~visibility;
10081                 int newValue = (curValue&~diff) | (visibility&diff);
10082                 if (newValue != curValue) {
10083                     ws.mSeq++;
10084                     ws.mSystemUiVisibility = newValue;
10085                 }
10086                 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
10087                     ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
10088                             visibility, newValue, diff);
10089                 }
10090             } catch (RemoteException e) {
10091                 // so sorry
10092             }
10093         }
10094     }
10095
10096     @Override
10097     public void reevaluateStatusBarVisibility() {
10098         synchronized (mWindowMap) {
10099             int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
10100             updateStatusBarVisibilityLocked(visibility);
10101             performLayoutAndPlaceSurfacesLocked();
10102         }
10103     }
10104
10105     @Override
10106     public FakeWindow addFakeWindow(Looper looper,
10107             InputEventReceiver.Factory inputEventReceiverFactory,
10108             String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags,
10109             boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) {
10110         synchronized (mWindowMap) {
10111             FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
10112                     name, windowType,
10113                     layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys,
10114                     hasFocus, touchFullscreen);
10115             int i=0;
10116             while (i<mFakeWindows.size()) {
10117                 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
10118                     break;
10119                 }
10120             }
10121             mFakeWindows.add(i, fw);
10122             mInputMonitor.updateInputWindowsLw(true);
10123             return fw;
10124         }
10125     }
10126
10127     boolean removeFakeWindowLocked(FakeWindow window) {
10128         synchronized (mWindowMap) {
10129             if (mFakeWindows.remove(window)) {
10130                 mInputMonitor.updateInputWindowsLw(true);
10131                 return true;
10132             }
10133             return false;
10134         }
10135     }
10136
10137     // It is assumed that this method is called only by InputMethodManagerService.
10138     public void saveLastInputMethodWindowForTransition() {
10139         synchronized (mWindowMap) {
10140             // TODO(multidisplay): Pass in the displayID.
10141             DisplayContent displayContent = getDefaultDisplayContentLocked();
10142             if (mInputMethodWindow != null) {
10143                 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
10144             }
10145         }
10146     }
10147
10148     @Override
10149     public boolean hasNavigationBar() {
10150         return mPolicy.hasNavigationBar();
10151     }
10152
10153     @Override
10154     public void lockNow(Bundle options) {
10155         mPolicy.lockNow(options);
10156     }
10157
10158     @Override
10159     public boolean isSafeModeEnabled() {
10160         return mSafeMode;
10161     }
10162
10163     void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10164         pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
10165         mPolicy.dump("    ", pw, args);
10166     }
10167
10168     void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10169         pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
10170         mAnimator.dumpLocked(pw, "    ", dumpAll);
10171     }
10172
10173     void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
10174         pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
10175         if (mTokenMap.size() > 0) {
10176             pw.println("  All tokens:");
10177             Iterator<WindowToken> it = mTokenMap.values().iterator();
10178             while (it.hasNext()) {
10179                 WindowToken token = it.next();
10180                 pw.print("  "); pw.print(token);
10181                 if (dumpAll) {
10182                     pw.println(':');
10183                     token.dump(pw, "    ");
10184                 } else {
10185                     pw.println();
10186                 }
10187             }
10188         }
10189         if (mWallpaperTokens.size() > 0) {
10190             pw.println();
10191             pw.println("  Wallpaper tokens:");
10192             for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
10193                 WindowToken token = mWallpaperTokens.get(i);
10194                 pw.print("  Wallpaper #"); pw.print(i);
10195                         pw.print(' '); pw.print(token);
10196                 if (dumpAll) {
10197                     pw.println(':');
10198                     token.dump(pw, "    ");
10199                 } else {
10200                     pw.println();
10201                 }
10202             }
10203         }
10204         if (mFinishedStarting.size() > 0) {
10205             pw.println();
10206             pw.println("  Finishing start of application tokens:");
10207             for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10208                 WindowToken token = mFinishedStarting.get(i);
10209                 pw.print("  Finished Starting #"); pw.print(i);
10210                         pw.print(' '); pw.print(token);
10211                 if (dumpAll) {
10212                     pw.println(':');
10213                     token.dump(pw, "    ");
10214                 } else {
10215                     pw.println();
10216                 }
10217             }
10218         }
10219         if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
10220             pw.println();
10221             if (mOpeningApps.size() > 0) {
10222                 pw.print("  mOpeningApps="); pw.println(mOpeningApps);
10223             }
10224             if (mClosingApps.size() > 0) {
10225                 pw.print("  mClosingApps="); pw.println(mClosingApps);
10226             }
10227         }
10228     }
10229
10230     void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
10231         pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
10232         if (mSessions.size() > 0) {
10233             Iterator<Session> it = mSessions.iterator();
10234             while (it.hasNext()) {
10235                 Session s = it.next();
10236                 pw.print("  Session "); pw.print(s); pw.println(':');
10237                 s.dump(pw, "    ");
10238             }
10239         }
10240     }
10241
10242     void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
10243         pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
10244         if (mDisplayReady) {
10245             final int numDisplays = mDisplayContents.size();
10246             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10247                 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10248                 displayContent.dump("  ", pw);
10249             }
10250         } else {
10251             pw.println("  NO DISPLAY");
10252         }
10253     }
10254
10255     void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
10256             ArrayList<WindowState> windows) {
10257         pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
10258         dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
10259     }
10260
10261     void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
10262             ArrayList<WindowState> windows) {
10263         final int numDisplays = mDisplayContents.size();
10264         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10265             final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
10266             for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10267                 final WindowState w = windowList.get(winNdx);
10268                 if (windows == null || windows.contains(w)) {
10269                     pw.print("  Window #"); pw.print(winNdx); pw.print(' ');
10270                             pw.print(w); pw.println(":");
10271                     w.dump(pw, "    ", dumpAll || windows != null);
10272                 }
10273             }
10274         }
10275         if (mInputMethodDialogs.size() > 0) {
10276             pw.println();
10277             pw.println("  Input method dialogs:");
10278             for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10279                 WindowState w = mInputMethodDialogs.get(i);
10280                 if (windows == null || windows.contains(w)) {
10281                     pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
10282                 }
10283             }
10284         }
10285         if (mPendingRemove.size() > 0) {
10286             pw.println();
10287             pw.println("  Remove pending for:");
10288             for (int i=mPendingRemove.size()-1; i>=0; i--) {
10289                 WindowState w = mPendingRemove.get(i);
10290                 if (windows == null || windows.contains(w)) {
10291                     pw.print("  Remove #"); pw.print(i); pw.print(' ');
10292                             pw.print(w);
10293                     if (dumpAll) {
10294                         pw.println(":");
10295                         w.dump(pw, "    ", true);
10296                     } else {
10297                         pw.println();
10298                     }
10299                 }
10300             }
10301         }
10302         if (mForceRemoves != null && mForceRemoves.size() > 0) {
10303             pw.println();
10304             pw.println("  Windows force removing:");
10305             for (int i=mForceRemoves.size()-1; i>=0; i--) {
10306                 WindowState w = mForceRemoves.get(i);
10307                 pw.print("  Removing #"); pw.print(i); pw.print(' ');
10308                         pw.print(w);
10309                 if (dumpAll) {
10310                     pw.println(":");
10311                     w.dump(pw, "    ", true);
10312                 } else {
10313                     pw.println();
10314                 }
10315             }
10316         }
10317         if (mDestroySurface.size() > 0) {
10318             pw.println();
10319             pw.println("  Windows waiting to destroy their surface:");
10320             for (int i=mDestroySurface.size()-1; i>=0; i--) {
10321                 WindowState w = mDestroySurface.get(i);
10322                 if (windows == null || windows.contains(w)) {
10323                     pw.print("  Destroy #"); pw.print(i); pw.print(' ');
10324                             pw.print(w);
10325                     if (dumpAll) {
10326                         pw.println(":");
10327                         w.dump(pw, "    ", true);
10328                     } else {
10329                         pw.println();
10330                     }
10331                 }
10332             }
10333         }
10334         if (mLosingFocus.size() > 0) {
10335             pw.println();
10336             pw.println("  Windows losing focus:");
10337             for (int i=mLosingFocus.size()-1; i>=0; i--) {
10338                 WindowState w = mLosingFocus.get(i);
10339                 if (windows == null || windows.contains(w)) {
10340                     pw.print("  Losing #"); pw.print(i); pw.print(' ');
10341                             pw.print(w);
10342                     if (dumpAll) {
10343                         pw.println(":");
10344                         w.dump(pw, "    ", true);
10345                     } else {
10346                         pw.println();
10347                     }
10348                 }
10349             }
10350         }
10351         if (mResizingWindows.size() > 0) {
10352             pw.println();
10353             pw.println("  Windows waiting to resize:");
10354             for (int i=mResizingWindows.size()-1; i>=0; i--) {
10355                 WindowState w = mResizingWindows.get(i);
10356                 if (windows == null || windows.contains(w)) {
10357                     pw.print("  Resizing #"); pw.print(i); pw.print(' ');
10358                             pw.print(w);
10359                     if (dumpAll) {
10360                         pw.println(":");
10361                         w.dump(pw, "    ", true);
10362                     } else {
10363                         pw.println();
10364                     }
10365                 }
10366             }
10367         }
10368         if (mWaitingForDrawn.size() > 0) {
10369             pw.println();
10370             pw.println("  Clients waiting for these windows to be drawn:");
10371             for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
10372                 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i);
10373                 pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first);
10374                         pw.print(": "); pw.println(pair.second);
10375             }
10376         }
10377         pw.println();
10378         pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
10379         pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
10380         if (mLastFocus != mCurrentFocus) {
10381             pw.print("  mLastFocus="); pw.println(mLastFocus);
10382         }
10383         pw.print("  mFocusedApp="); pw.println(mFocusedApp);
10384         if (mInputMethodTarget != null) {
10385             pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
10386         }
10387         pw.print("  mInTouchMode="); pw.print(mInTouchMode);
10388                 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
10389         pw.print("  mLastDisplayFreezeDuration=");
10390                 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
10391                 if ( mLastFinishedFreezeSource != null) {
10392                     pw.print(" due to ");
10393                     pw.print(mLastFinishedFreezeSource);
10394                 }
10395                 pw.println();
10396         if (dumpAll) {
10397             pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer);
10398                     pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
10399             if (mLastStatusBarVisibility != 0) {
10400                 pw.print("  mLastStatusBarVisibility=0x");
10401                         pw.println(Integer.toHexString(mLastStatusBarVisibility));
10402             }
10403             if (mInputMethodWindow != null) {
10404                 pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
10405             }
10406             pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
10407             if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
10408                 pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
10409                 pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
10410             }
10411             pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
10412                     pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
10413             if (mInputMethodAnimLayerAdjustment != 0 ||
10414                     mWallpaperAnimLayerAdjustment != 0) {
10415                 pw.print("  mInputMethodAnimLayerAdjustment=");
10416                         pw.print(mInputMethodAnimLayerAdjustment);
10417                         pw.print("  mWallpaperAnimLayerAdjustment=");
10418                         pw.println(mWallpaperAnimLayerAdjustment);
10419             }
10420             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
10421                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10422             if (needsLayout()) {
10423                 pw.print("  layoutNeeded on displays=");
10424                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10425                     final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10426                     if (displayContent.layoutNeeded) {
10427                         pw.print(displayContent.getDisplayId());
10428                     }
10429                 }
10430                 pw.println();
10431             }
10432             pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
10433             pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
10434                     pw.print(" windows="); pw.print(mWindowsFreezingScreen);
10435                     pw.print(" client="); pw.print(mClientFreezingScreen);
10436                     pw.print(" apps="); pw.print(mAppsFreezingScreen);
10437                     pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
10438             pw.print("  mRotation="); pw.print(mRotation);
10439                     pw.print(" mAltOrientation="); pw.println(mAltOrientation);
10440             pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
10441                     pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
10442             pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
10443             pw.print("  mWindowAnimationScale="); pw.print(mWindowAnimationScale);
10444                     pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale);
10445                     pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale);
10446             pw.print("  mTraversalScheduled="); pw.println(mTraversalScheduled);
10447             pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
10448                     pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
10449             pw.println("  mLayoutToAnim:");
10450             mAppTransition.dump(pw);
10451         }
10452     }
10453
10454     boolean dumpWindows(PrintWriter pw, String name, String[] args,
10455             int opti, boolean dumpAll) {
10456         WindowList windows = new WindowList();
10457         if ("visible".equals(name)) {
10458             synchronized(mWindowMap) {
10459                 final int numDisplays = mDisplayContents.size();
10460                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10461                     final WindowList windowList =
10462                             mDisplayContents.valueAt(displayNdx).getWindowList();
10463                     for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10464                         final WindowState w = windowList.get(winNdx);
10465                         if (w.mWinAnimator.mSurfaceShown) {
10466                             windows.add(w);
10467                         }
10468                     }
10469                 }
10470             }
10471         } else {
10472             int objectId = 0;
10473             // See if this is an object ID.
10474             try {
10475                 objectId = Integer.parseInt(name, 16);
10476                 name = null;
10477             } catch (RuntimeException e) {
10478             }
10479             synchronized(mWindowMap) {
10480                 final int numDisplays = mDisplayContents.size();
10481                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10482                     final WindowList windowList =
10483                             mDisplayContents.valueAt(displayNdx).getWindowList();
10484                     for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10485                         final WindowState w = windowList.get(winNdx);
10486                         if (name != null) {
10487                             if (w.mAttrs.getTitle().toString().contains(name)) {
10488                                 windows.add(w);
10489                             }
10490                         } else if (System.identityHashCode(w) == objectId) {
10491                             windows.add(w);
10492                         }
10493                     }
10494                 }
10495             }
10496         }
10497
10498         if (windows.size() <= 0) {
10499             return false;
10500         }
10501
10502         synchronized(mWindowMap) {
10503             dumpWindowsLocked(pw, dumpAll, windows);
10504         }
10505         return true;
10506     }
10507
10508     void dumpLastANRLocked(PrintWriter pw) {
10509         pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
10510         if (mLastANRState == null) {
10511             pw.println("  <no ANR has occurred since boot>");
10512         } else {
10513             pw.println(mLastANRState);
10514         }
10515     }
10516
10517     /**
10518      * Saves information about the state of the window manager at
10519      * the time an ANR occurred before anything else in the system changes
10520      * in response.
10521      *
10522      * @param appWindowToken The application that ANR'd, may be null.
10523      * @param windowState The window that ANR'd, may be null.
10524      * @param reason The reason for the ANR, may be null.
10525      */
10526     public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
10527             String reason) {
10528         StringWriter sw = new StringWriter();
10529         PrintWriter pw = new FastPrintWriter(sw, false, 1024);
10530         pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
10531         if (appWindowToken != null) {
10532             pw.println("  Application at fault: " + appWindowToken.stringName);
10533         }
10534         if (windowState != null) {
10535             pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
10536         }
10537         if (reason != null) {
10538             pw.println("  Reason: " + reason);
10539         }
10540         pw.println();
10541         dumpWindowsNoHeaderLocked(pw, true, null);
10542         pw.close();
10543         mLastANRState = sw.toString();
10544     }
10545
10546     @Override
10547     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10548         if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
10549                 != PackageManager.PERMISSION_GRANTED) {
10550             pw.println("Permission Denial: can't dump WindowManager from from pid="
10551                     + Binder.getCallingPid()
10552                     + ", uid=" + Binder.getCallingUid());
10553             return;
10554         }
10555
10556         boolean dumpAll = false;
10557
10558         int opti = 0;
10559         while (opti < args.length) {
10560             String opt = args[opti];
10561             if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10562                 break;
10563             }
10564             opti++;
10565             if ("-a".equals(opt)) {
10566                 dumpAll = true;
10567             } else if ("-h".equals(opt)) {
10568                 pw.println("Window manager dump options:");
10569                 pw.println("  [-a] [-h] [cmd] ...");
10570                 pw.println("  cmd may be one of:");
10571                 pw.println("    l[astanr]: last ANR information");
10572                 pw.println("    p[policy]: policy state");
10573                 pw.println("    a[animator]: animator state");
10574                 pw.println("    s[essions]: active sessions");
10575                 pw.println("    d[isplays]: active display contents");
10576                 pw.println("    t[okens]: token list");
10577                 pw.println("    w[indows]: window list");
10578                 pw.println("  cmd may also be a NAME to dump windows.  NAME may");
10579                 pw.println("    be a partial substring in a window name, a");
10580                 pw.println("    Window hex object identifier, or");
10581                 pw.println("    \"all\" for all windows, or");
10582                 pw.println("    \"visible\" for the visible windows.");
10583                 pw.println("  -a: include all available server state.");
10584                 return;
10585             } else {
10586                 pw.println("Unknown argument: " + opt + "; use -h for help");
10587             }
10588         }
10589
10590         // Is the caller requesting to dump a particular piece of data?
10591         if (opti < args.length) {
10592             String cmd = args[opti];
10593             opti++;
10594             if ("lastanr".equals(cmd) || "l".equals(cmd)) {
10595                 synchronized(mWindowMap) {
10596                     dumpLastANRLocked(pw);
10597                 }
10598                 return;
10599             } else if ("policy".equals(cmd) || "p".equals(cmd)) {
10600                 synchronized(mWindowMap) {
10601                     dumpPolicyLocked(pw, args, true);
10602                 }
10603                 return;
10604             } else if ("animator".equals(cmd) || "a".equals(cmd)) {
10605                 synchronized(mWindowMap) {
10606                     dumpAnimatorLocked(pw, args, true);
10607                 }
10608                 return;
10609             } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
10610                 synchronized(mWindowMap) {
10611                     dumpSessionsLocked(pw, true);
10612                 }
10613                 return;
10614             } else if ("displays".equals(cmd) || "d".equals(cmd)) {
10615                 synchronized(mWindowMap) {
10616                     dumpDisplayContentsLocked(pw, true);
10617                 }
10618                 return;
10619             } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
10620                 synchronized(mWindowMap) {
10621                     dumpTokensLocked(pw, true);
10622                 }
10623                 return;
10624             } else if ("windows".equals(cmd) || "w".equals(cmd)) {
10625                 synchronized(mWindowMap) {
10626                     dumpWindowsLocked(pw, true, null);
10627                 }
10628                 return;
10629             } else if ("all".equals(cmd) || "a".equals(cmd)) {
10630                 synchronized(mWindowMap) {
10631                     dumpWindowsLocked(pw, true, null);
10632                 }
10633                 return;
10634             } else {
10635                 // Dumping a single name?
10636                 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
10637                     pw.println("Bad window command, or no windows match: " + cmd);
10638                     pw.println("Use -h for help.");
10639                 }
10640                 return;
10641             }
10642         }
10643
10644         synchronized(mWindowMap) {
10645             pw.println();
10646             if (dumpAll) {
10647                 pw.println("-------------------------------------------------------------------------------");
10648             }
10649             dumpLastANRLocked(pw);
10650             pw.println();
10651             if (dumpAll) {
10652                 pw.println("-------------------------------------------------------------------------------");
10653             }
10654             dumpPolicyLocked(pw, args, dumpAll);
10655             pw.println();
10656             if (dumpAll) {
10657                 pw.println("-------------------------------------------------------------------------------");
10658             }
10659             dumpAnimatorLocked(pw, args, dumpAll);
10660             pw.println();
10661             if (dumpAll) {
10662                 pw.println("-------------------------------------------------------------------------------");
10663             }
10664             dumpSessionsLocked(pw, dumpAll);
10665             pw.println();
10666             if (dumpAll) {
10667                 pw.println("-------------------------------------------------------------------------------");
10668             }
10669             dumpDisplayContentsLocked(pw, dumpAll);
10670             pw.println();
10671             if (dumpAll) {
10672                 pw.println("-------------------------------------------------------------------------------");
10673             }
10674             dumpTokensLocked(pw, dumpAll);
10675             pw.println();
10676             if (dumpAll) {
10677                 pw.println("-------------------------------------------------------------------------------");
10678             }
10679             dumpWindowsLocked(pw, dumpAll, null);
10680         }
10681     }
10682
10683     // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
10684     @Override
10685     public void monitor() {
10686         synchronized (mWindowMap) { }
10687     }
10688
10689     public interface OnHardKeyboardStatusChangeListener {
10690         public void onHardKeyboardStatusChange(boolean available, boolean enabled);
10691     }
10692
10693     void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
10694         if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
10695             Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
10696                     Integer.toHexString(pendingLayoutChanges));
10697         }
10698     }
10699
10700     private DisplayContent newDisplayContentLocked(final Display display) {
10701         DisplayContent displayContent = new DisplayContent(display, this);
10702         final int displayId = display.getDisplayId();
10703         mDisplayContents.put(displayId, displayContent);
10704
10705         DisplayInfo displayInfo = displayContent.getDisplayInfo();
10706         final Rect rect = new Rect();
10707         mDisplaySettings.getOverscanLocked(displayInfo.name, rect);
10708         synchronized (displayContent.mDisplaySizeLock) {
10709             displayInfo.overscanLeft = rect.left;
10710             displayInfo.overscanTop = rect.top;
10711             displayInfo.overscanRight = rect.right;
10712             displayInfo.overscanBottom = rect.bottom;
10713             mDisplayManagerService.setDisplayInfoOverrideFromWindowManager(
10714                     displayId, displayInfo);
10715         }
10716         configureDisplayPolicyLocked(displayContent);
10717
10718         // TODO: Create an input channel for each display with touch capability.
10719         if (displayId == Display.DEFAULT_DISPLAY) {
10720             displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent);
10721             registerPointerEventListener(displayContent.mTapDetector);
10722         }
10723
10724         return displayContent;
10725     }
10726
10727     public void createDisplayContentLocked(final Display display) {
10728         if (display == null) {
10729             throw new IllegalArgumentException("getDisplayContent: display must not be null");
10730         }
10731         getDisplayContentLocked(display.getDisplayId());
10732     }
10733
10734     /**
10735      * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
10736      * there is a Display for the displayId.
10737      * @param displayId The display the caller is interested in.
10738      * @return The DisplayContent associated with displayId or null if there is no Display for it.
10739      */
10740     public DisplayContent getDisplayContentLocked(final int displayId) {
10741         DisplayContent displayContent = mDisplayContents.get(displayId);
10742         if (displayContent == null) {
10743             final Display display = mDisplayManager.getDisplay(displayId);
10744             if (display != null) {
10745                 displayContent = newDisplayContentLocked(display);
10746             }
10747         }
10748         return displayContent;
10749     }
10750
10751     // There is an inherent assumption that this will never return null.
10752     public DisplayContent getDefaultDisplayContentLocked() {
10753         return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
10754     }
10755
10756     public WindowList getDefaultWindowListLocked() {
10757         return getDefaultDisplayContentLocked().getWindowList();
10758     }
10759
10760     public DisplayInfo getDefaultDisplayInfoLocked() {
10761         return getDefaultDisplayContentLocked().getDisplayInfo();
10762     }
10763
10764     /**
10765      * Return the list of WindowStates associated on the passed display.
10766      * @param display The screen to return windows from.
10767      * @return The list of WindowStates on the screen, or null if the there is no screen.
10768      */
10769     public WindowList getWindowListLocked(final Display display) {
10770         return getWindowListLocked(display.getDisplayId());
10771     }
10772
10773     /**
10774      * Return the list of WindowStates associated on the passed display.
10775      * @param displayId The screen to return windows from.
10776      * @return The list of WindowStates on the screen, or null if the there is no screen.
10777      */
10778     public WindowList getWindowListLocked(final int displayId) {
10779         final DisplayContent displayContent = getDisplayContentLocked(displayId);
10780         return displayContent != null ? displayContent.getWindowList() : null;
10781     }
10782
10783     @Override
10784     public void onDisplayAdded(int displayId) {
10785         mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
10786     }
10787
10788     private void handleDisplayAddedLocked(int displayId) {
10789         final Display display = mDisplayManager.getDisplay(displayId);
10790         if (display != null) {
10791             createDisplayContentLocked(display);
10792             displayReady(displayId);
10793         }
10794     }
10795
10796     @Override
10797     public void onDisplayRemoved(int displayId) {
10798         mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
10799     }
10800
10801     private void handleDisplayRemovedLocked(int displayId) {
10802         final DisplayContent displayContent = getDisplayContentLocked(displayId);
10803         if (displayContent != null) {
10804             mDisplayContents.delete(displayId);
10805             displayContent.close();
10806             if (displayId == Display.DEFAULT_DISPLAY) {
10807                 unregisterPointerEventListener(displayContent.mTapDetector);
10808             }
10809             WindowList windows = displayContent.getWindowList();
10810             while (!windows.isEmpty()) {
10811                 final WindowState win = windows.get(windows.size() - 1);
10812                 removeWindowLocked(win.mSession, win);
10813             }
10814         }
10815         mAnimator.removeDisplayLocked(displayId);
10816     }
10817
10818     @Override
10819     public void onDisplayChanged(int displayId) {
10820         mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
10821     }
10822
10823     private void handleDisplayChangedLocked(int displayId) {
10824         final DisplayContent displayContent = getDisplayContentLocked(displayId);
10825         if (displayContent != null) {
10826             displayContent.updateDisplayInfo();
10827         }
10828     }
10829
10830     @Override
10831     public Object getWindowManagerLock() {
10832         return mWindowMap;
10833     }
10834 }