OSDN Git Service

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