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