WindowManagerService.java revision 2e7f3bdcc9ec0b3e95b565b943ecee2210f4b937
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, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
4035            boolean scaleUp) {
4036        synchronized(mWindowMap) {
4037            mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX,
4038                    startY, targetWidth, targetHeight, startedCallback, scaleUp);
4039        }
4040    }
4041
4042    @Override
4043    public void executeAppTransition() {
4044        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4045                "executeAppTransition()")) {
4046            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4047        }
4048
4049        synchronized(mWindowMap) {
4050            if (DEBUG_APP_TRANSITIONS) Slog.w(TAG, "Execute app transition: " + mAppTransition,
4051                    new RuntimeException("here").fillInStackTrace());
4052            if (mAppTransition.isTransitionSet()) {
4053                mAppTransition.setReady();
4054                final long origId = Binder.clearCallingIdentity();
4055                try {
4056                    performLayoutAndPlaceSurfacesLocked();
4057                } finally {
4058                    Binder.restoreCallingIdentity(origId);
4059                }
4060            }
4061        }
4062    }
4063
4064    @Override
4065    public void setAppStartingWindow(IBinder token, String pkg,
4066            int theme, CompatibilityInfo compatInfo,
4067            CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
4068            int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
4069        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4070                "setAppStartingWindow()")) {
4071            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4072        }
4073
4074        synchronized(mWindowMap) {
4075            if (DEBUG_STARTING_WINDOW) Slog.v(
4076                    TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg
4077                    + " transferFrom=" + transferFrom);
4078
4079            AppWindowToken wtoken = findAppWindowToken(token);
4080            if (wtoken == null) {
4081                Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
4082                return;
4083            }
4084
4085            // If the display is frozen, we won't do anything until the
4086            // actual window is displayed so there is no reason to put in
4087            // the starting window.
4088            if (!okToDisplay()) {
4089                return;
4090            }
4091
4092            if (wtoken.startingData != null) {
4093                return;
4094            }
4095
4096            if (transferFrom != null) {
4097                AppWindowToken ttoken = findAppWindowToken(transferFrom);
4098                if (ttoken != null) {
4099                    WindowState startingWindow = ttoken.startingWindow;
4100                    if (startingWindow != null) {
4101                        if (mStartingIconInTransition) {
4102                            // In this case, the starting icon has already
4103                            // been displayed, so start letting windows get
4104                            // shown immediately without any more transitions.
4105                            mSkipAppTransitionAnimation = true;
4106                        }
4107                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
4108                                "Moving existing starting " + startingWindow + " from " + ttoken
4109                                + " to " + wtoken);
4110                        final long origId = Binder.clearCallingIdentity();
4111
4112                        // Transfer the starting window over to the new
4113                        // token.
4114                        wtoken.startingData = ttoken.startingData;
4115                        wtoken.startingView = ttoken.startingView;
4116                        wtoken.startingDisplayed = ttoken.startingDisplayed;
4117                        ttoken.startingDisplayed = false;
4118                        wtoken.startingWindow = startingWindow;
4119                        wtoken.reportedVisible = ttoken.reportedVisible;
4120                        ttoken.startingData = null;
4121                        ttoken.startingView = null;
4122                        ttoken.startingWindow = null;
4123                        ttoken.startingMoved = true;
4124                        startingWindow.mToken = wtoken;
4125                        startingWindow.mRootToken = wtoken;
4126                        startingWindow.mAppToken = wtoken;
4127                        startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator;
4128
4129                        if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
4130                            Slog.v(TAG, "Removing starting window: " + startingWindow);
4131                        }
4132                        startingWindow.getWindowList().remove(startingWindow);
4133                        mWindowsChanged = true;
4134                        if (DEBUG_ADD_REMOVE) Slog.v(TAG,
4135                                "Removing starting " + startingWindow + " from " + ttoken);
4136                        ttoken.windows.remove(startingWindow);
4137                        ttoken.allAppWindows.remove(startingWindow);
4138                        addWindowToListInOrderLocked(startingWindow, true);
4139
4140                        // Propagate other interesting state between the
4141                        // tokens.  If the old token is displayed, we should
4142                        // immediately force the new one to be displayed.  If
4143                        // it is animating, we need to move that animation to
4144                        // the new one.
4145                        if (ttoken.allDrawn) {
4146                            wtoken.allDrawn = true;
4147                            wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn;
4148                        }
4149                        if (ttoken.firstWindowDrawn) {
4150                            wtoken.firstWindowDrawn = true;
4151                        }
4152                        if (!ttoken.hidden) {
4153                            wtoken.hidden = false;
4154                            wtoken.hiddenRequested = false;
4155                            wtoken.willBeHidden = false;
4156                        }
4157                        if (wtoken.clientHidden != ttoken.clientHidden) {
4158                            wtoken.clientHidden = ttoken.clientHidden;
4159                            wtoken.sendAppVisibilityToClients();
4160                        }
4161                        final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4162                        final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4163                        if (tAppAnimator.animation != null) {
4164                            wAppAnimator.animation = tAppAnimator.animation;
4165                            wAppAnimator.animating = tAppAnimator.animating;
4166                            wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment;
4167                            tAppAnimator.animation = null;
4168                            tAppAnimator.animLayerAdjustment = 0;
4169                            wAppAnimator.updateLayers();
4170                            tAppAnimator.updateLayers();
4171                        }
4172
4173                        updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4174                                true /*updateInputWindows*/);
4175                        getDefaultDisplayContentLocked().layoutNeeded = true;
4176                        performLayoutAndPlaceSurfacesLocked();
4177                        Binder.restoreCallingIdentity(origId);
4178                        return;
4179                    } else if (ttoken.startingData != null) {
4180                        // The previous app was getting ready to show a
4181                        // starting window, but hasn't yet done so.  Steal it!
4182                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
4183                                "Moving pending starting from " + ttoken
4184                                + " to " + wtoken);
4185                        wtoken.startingData = ttoken.startingData;
4186                        ttoken.startingData = null;
4187                        ttoken.startingMoved = true;
4188                        Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4189                        // Note: we really want to do sendMessageAtFrontOfQueue() because we
4190                        // want to process the message ASAP, before any other queued
4191                        // messages.
4192                        mH.sendMessageAtFrontOfQueue(m);
4193                        return;
4194                    }
4195                    final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4196                    final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4197                    if (tAppAnimator.thumbnail != null) {
4198                        // The old token is animating with a thumbnail, transfer
4199                        // that to the new token.
4200                        if (wAppAnimator.thumbnail != null) {
4201                            wAppAnimator.thumbnail.destroy();
4202                        }
4203                        wAppAnimator.thumbnail = tAppAnimator.thumbnail;
4204                        wAppAnimator.thumbnailX = tAppAnimator.thumbnailX;
4205                        wAppAnimator.thumbnailY = tAppAnimator.thumbnailY;
4206                        wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
4207                        wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
4208                        tAppAnimator.thumbnail = null;
4209                    }
4210                }
4211            }
4212
4213            // There is no existing starting window, and the caller doesn't
4214            // want us to create one, so that's it!
4215            if (!createIfNeeded) {
4216                return;
4217            }
4218
4219            // If this is a translucent window, then don't
4220            // show a starting window -- the current effect (a full-screen
4221            // opaque starting window that fades away to the real contents
4222            // when it is ready) does not work for this.
4223            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x"
4224                    + Integer.toHexString(theme));
4225            if (theme != 0) {
4226                AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
4227                        com.android.internal.R.styleable.Window, mCurrentUserId);
4228                if (ent == null) {
4229                    // Whoops!  App doesn't exist.  Um.  Okay.  We'll just
4230                    // pretend like we didn't see that.
4231                    return;
4232                }
4233                if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent="
4234                        + ent.array.getBoolean(
4235                                com.android.internal.R.styleable.Window_windowIsTranslucent, false)
4236                        + " Floating="
4237                        + ent.array.getBoolean(
4238                                com.android.internal.R.styleable.Window_windowIsFloating, false)
4239                        + " ShowWallpaper="
4240                        + ent.array.getBoolean(
4241                                com.android.internal.R.styleable.Window_windowShowWallpaper, false));
4242                if (ent.array.getBoolean(
4243                        com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
4244                    return;
4245                }
4246                if (ent.array.getBoolean(
4247                        com.android.internal.R.styleable.Window_windowIsFloating, false)) {
4248                    return;
4249                }
4250                if (ent.array.getBoolean(
4251                        com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
4252                    if (mWallpaperTarget == null) {
4253                        // If this theme is requesting a wallpaper, and the wallpaper
4254                        // is not curently visible, then this effectively serves as
4255                        // an opaque window and our starting window transition animation
4256                        // can still work.  We just need to make sure the starting window
4257                        // is also showing the wallpaper.
4258                        windowFlags |= FLAG_SHOW_WALLPAPER;
4259                    } else {
4260                        return;
4261                    }
4262                }
4263            }
4264
4265            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData");
4266            mStartingIconInTransition = true;
4267            wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
4268                    labelRes, icon, logo, windowFlags);
4269            Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4270            // Note: we really want to do sendMessageAtFrontOfQueue() because we
4271            // want to process the message ASAP, before any other queued
4272            // messages.
4273            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
4274            mH.sendMessageAtFrontOfQueue(m);
4275        }
4276    }
4277
4278    public void removeAppStartingWindow(IBinder token) {
4279        synchronized (mWindowMap) {
4280            AppWindowToken wtoken = mTokenMap.get(token).appWindowToken;
4281            if (wtoken.startingWindow != null) {
4282                scheduleRemoveStartingWindow(wtoken);
4283            }
4284        }
4285    }
4286
4287    @Override
4288    public void setAppWillBeHidden(IBinder token) {
4289        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4290                "setAppWillBeHidden()")) {
4291            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4292        }
4293
4294        AppWindowToken wtoken;
4295
4296        synchronized(mWindowMap) {
4297            wtoken = findAppWindowToken(token);
4298            if (wtoken == null) {
4299                Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
4300                return;
4301            }
4302            wtoken.willBeHidden = true;
4303        }
4304    }
4305
4306    public void setAppFullscreen(IBinder token, boolean toOpaque) {
4307        AppWindowToken atoken = findAppWindowToken(token);
4308        if (atoken != null) {
4309            atoken.appFullscreen = toOpaque;
4310            setWindowOpaque(token, toOpaque);
4311            requestTraversal();
4312        }
4313    }
4314
4315    public void setWindowOpaque(IBinder token, boolean isOpaque) {
4316        AppWindowToken wtoken = findAppWindowToken(token);
4317        if (wtoken != null) {
4318            WindowState win = wtoken.findMainWindow();
4319            if (win != null) {
4320                win.mWinAnimator.setOpaque(isOpaque);
4321            }
4322        }
4323    }
4324
4325    boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
4326            boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
4327        boolean delayed = false;
4328
4329        if (wtoken.clientHidden == visible) {
4330            wtoken.clientHidden = !visible;
4331            wtoken.sendAppVisibilityToClients();
4332        }
4333
4334        wtoken.willBeHidden = false;
4335        if (wtoken.hidden == visible) {
4336            boolean changed = false;
4337            if (DEBUG_APP_TRANSITIONS) Slog.v(
4338                TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
4339                + " performLayout=" + performLayout);
4340
4341            boolean runningAppAnimation = false;
4342
4343            if (transit != AppTransition.TRANSIT_UNSET) {
4344                if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
4345                    wtoken.mAppAnimator.animation = null;
4346                }
4347                if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) {
4348                    delayed = runningAppAnimation = true;
4349                }
4350                WindowState window = wtoken.findMainWindow();
4351                //TODO (multidisplay): Magnification is supported only for the default display.
4352                if (window != null && mAccessibilityController != null
4353                        && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
4354                    mAccessibilityController.onAppWindowTransitionLocked(window, transit);
4355                }
4356                changed = true;
4357            }
4358
4359            final int N = wtoken.allAppWindows.size();
4360            for (int i=0; i<N; i++) {
4361                WindowState win = wtoken.allAppWindows.get(i);
4362                if (win == wtoken.startingWindow) {
4363                    continue;
4364                }
4365
4366                //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
4367                //win.dump("  ");
4368                if (visible) {
4369                    if (!win.isVisibleNow()) {
4370                        if (!runningAppAnimation) {
4371                            win.mWinAnimator.applyAnimationLocked(
4372                                    WindowManagerPolicy.TRANSIT_ENTER, true);
4373                            //TODO (multidisplay): Magnification is supported only for the default
4374                            if (mAccessibilityController != null
4375                                    && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4376                                mAccessibilityController.onWindowTransitionLocked(win,
4377                                        WindowManagerPolicy.TRANSIT_ENTER);
4378                            }
4379                        }
4380                        changed = true;
4381                        final DisplayContent displayContent = win.getDisplayContent();
4382                        if (displayContent != null) {
4383                            displayContent.layoutNeeded = true;
4384                        }
4385                    }
4386                } else if (win.isVisibleNow()) {
4387                    if (!runningAppAnimation) {
4388                        win.mWinAnimator.applyAnimationLocked(
4389                                WindowManagerPolicy.TRANSIT_EXIT, false);
4390                        //TODO (multidisplay): Magnification is supported only for the default
4391                        if (mAccessibilityController != null
4392                                && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4393                            mAccessibilityController.onWindowTransitionLocked(win,
4394                                    WindowManagerPolicy.TRANSIT_EXIT);
4395                        }
4396                    }
4397                    changed = true;
4398                    final DisplayContent displayContent = win.getDisplayContent();
4399                    if (displayContent != null) {
4400                        displayContent.layoutNeeded = true;
4401                    }
4402                }
4403            }
4404
4405            wtoken.hidden = wtoken.hiddenRequested = !visible;
4406            if (!visible) {
4407                unsetAppFreezingScreenLocked(wtoken, true, true);
4408            } else {
4409                // If we are being set visible, and the starting window is
4410                // not yet displayed, then make sure it doesn't get displayed.
4411                WindowState swin = wtoken.startingWindow;
4412                if (swin != null && !swin.isDrawnLw()) {
4413                    swin.mPolicyVisibility = false;
4414                    swin.mPolicyVisibilityAfterAnim = false;
4415                 }
4416            }
4417
4418            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
4419                      + ": hidden=" + wtoken.hidden + " hiddenRequested="
4420                      + wtoken.hiddenRequested);
4421
4422            if (changed) {
4423                mInputMonitor.setUpdateInputWindowsNeededLw();
4424                if (performLayout) {
4425                    updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4426                            false /*updateInputWindows*/);
4427                    performLayoutAndPlaceSurfacesLocked();
4428                }
4429                mInputMonitor.updateInputWindowsLw(false /*force*/);
4430            }
4431        }
4432
4433        if (wtoken.mAppAnimator.animation != null) {
4434            delayed = true;
4435        }
4436
4437        for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
4438            if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) {
4439                delayed = true;
4440            }
4441        }
4442
4443        return delayed;
4444    }
4445
4446    @Override
4447    public void setAppVisibility(IBinder token, boolean visible) {
4448        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4449                "setAppVisibility()")) {
4450            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4451        }
4452
4453        AppWindowToken wtoken;
4454
4455        synchronized(mWindowMap) {
4456            wtoken = findAppWindowToken(token);
4457            if (wtoken == null) {
4458                Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
4459                return;
4460            }
4461
4462            if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG, "setAppVisibility(" +
4463                    token + ", visible=" + visible + "): " + mAppTransition +
4464                    " hidden=" + wtoken.hidden + " hiddenRequested=" +
4465                    wtoken.hiddenRequested, HIDE_STACK_CRAWLS ?
4466                            null : new RuntimeException("here").fillInStackTrace());
4467
4468            // If we are preparing an app transition, then delay changing
4469            // the visibility of this token until we execute that transition.
4470            if (okToDisplay() && mAppTransition.isTransitionSet()) {
4471                wtoken.hiddenRequested = !visible;
4472
4473                if (!wtoken.startingDisplayed) {
4474                    if (DEBUG_APP_TRANSITIONS) Slog.v(
4475                            TAG, "Setting dummy animation on: " + wtoken);
4476                    wtoken.mAppAnimator.setDummyAnimation();
4477                }
4478                mOpeningApps.remove(wtoken);
4479                mClosingApps.remove(wtoken);
4480                wtoken.waitingToShow = wtoken.waitingToHide = false;
4481                wtoken.inPendingTransaction = true;
4482                if (visible) {
4483                    mOpeningApps.add(wtoken);
4484                    wtoken.startingMoved = false;
4485                    wtoken.mEnteringAnimation = true;
4486
4487                    // If the token is currently hidden (should be the
4488                    // common case), then we need to set up to wait for
4489                    // its windows to be ready.
4490                    if (wtoken.hidden) {
4491                        wtoken.allDrawn = false;
4492                        wtoken.deferClearAllDrawn = false;
4493                        wtoken.waitingToShow = true;
4494
4495                        if (wtoken.clientHidden) {
4496                            // In the case where we are making an app visible
4497                            // but holding off for a transition, we still need
4498                            // to tell the client to make its windows visible so
4499                            // they get drawn.  Otherwise, we will wait on
4500                            // performing the transition until all windows have
4501                            // been drawn, they never will be, and we are sad.
4502                            wtoken.clientHidden = false;
4503                            wtoken.sendAppVisibilityToClients();
4504                        }
4505                    }
4506                } else {
4507                    mClosingApps.add(wtoken);
4508                    wtoken.mEnteringAnimation = false;
4509
4510                    // If the token is currently visible (should be the
4511                    // common case), then set up to wait for it to be hidden.
4512                    if (!wtoken.hidden) {
4513                        wtoken.waitingToHide = true;
4514                    }
4515                }
4516                if (mAppTransition.getAppTransition() == AppTransition.TRANSIT_TASK_OPEN_BEHIND) {
4517                    // We're launchingBehind, add the launching activity to mOpeningApps.
4518                    final WindowState win =
4519                            findFocusedWindowLocked(getDefaultDisplayContentLocked());
4520                    if (win != null) {
4521                        final AppWindowToken focusedToken = win.mAppToken;
4522                        if (focusedToken != null) {
4523                            if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "TRANSIT_TASK_OPEN_BEHIND, " +
4524                                    " adding " + focusedToken + " to mOpeningApps");
4525                            // Force animation to be loaded.
4526                            focusedToken.hidden = true;
4527                            mOpeningApps.add(focusedToken);
4528                        }
4529                    }
4530                }
4531                return;
4532            }
4533
4534            final long origId = Binder.clearCallingIdentity();
4535            setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
4536                    true, wtoken.voiceInteraction);
4537            wtoken.updateReportedVisibilityLocked();
4538            Binder.restoreCallingIdentity(origId);
4539        }
4540    }
4541
4542    void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
4543            boolean unfreezeSurfaceNow, boolean force) {
4544        if (wtoken.mAppAnimator.freezingScreen) {
4545            if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
4546                    + " force=" + force);
4547            final int N = wtoken.allAppWindows.size();
4548            boolean unfrozeWindows = false;
4549            for (int i=0; i<N; i++) {
4550                WindowState w = wtoken.allAppWindows.get(i);
4551                if (w.mAppFreezing) {
4552                    w.mAppFreezing = false;
4553                    if (w.mHasSurface && !w.mOrientationChanging) {
4554                        if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w);
4555                        w.mOrientationChanging = true;
4556                        mInnerFields.mOrientationChangeComplete = false;
4557                    }
4558                    w.mLastFreezeDuration = 0;
4559                    unfrozeWindows = true;
4560                    final DisplayContent displayContent = w.getDisplayContent();
4561                    if (displayContent != null) {
4562                        displayContent.layoutNeeded = true;
4563                    }
4564                }
4565            }
4566            if (force || unfrozeWindows) {
4567                if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
4568                wtoken.mAppAnimator.freezingScreen = false;
4569                wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime()
4570                        - mDisplayFreezeTime);
4571                mAppsFreezingScreen--;
4572                mLastFinishedFreezeSource = wtoken;
4573            }
4574            if (unfreezeSurfaceNow) {
4575                if (unfrozeWindows) {
4576                    performLayoutAndPlaceSurfacesLocked();
4577                }
4578                stopFreezingDisplayLocked();
4579            }
4580        }
4581    }
4582
4583    private void startAppFreezingScreenLocked(AppWindowToken wtoken) {
4584        if (DEBUG_ORIENTATION) {
4585            RuntimeException e = null;
4586            if (!HIDE_STACK_CRAWLS) {
4587                e = new RuntimeException();
4588                e.fillInStackTrace();
4589            }
4590            Slog.i(TAG, "Set freezing of " + wtoken.appToken
4591                    + ": hidden=" + wtoken.hidden + " freezing="
4592                    + wtoken.mAppAnimator.freezingScreen, e);
4593        }
4594        if (!wtoken.hiddenRequested) {
4595            if (!wtoken.mAppAnimator.freezingScreen) {
4596                wtoken.mAppAnimator.freezingScreen = true;
4597                wtoken.mAppAnimator.lastFreezeDuration = 0;
4598                mAppsFreezingScreen++;
4599                if (mAppsFreezingScreen == 1) {
4600                    startFreezingDisplayLocked(false, 0, 0);
4601                    mH.removeMessages(H.APP_FREEZE_TIMEOUT);
4602                    mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000);
4603                }
4604            }
4605            final int N = wtoken.allAppWindows.size();
4606            for (int i=0; i<N; i++) {
4607                WindowState w = wtoken.allAppWindows.get(i);
4608                w.mAppFreezing = true;
4609            }
4610        }
4611    }
4612
4613    @Override
4614    public void startAppFreezingScreen(IBinder token, int configChanges) {
4615        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4616                "setAppFreezingScreen()")) {
4617            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4618        }
4619
4620        synchronized(mWindowMap) {
4621            if (configChanges == 0 && okToDisplay()) {
4622                if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
4623                return;
4624            }
4625
4626            AppWindowToken wtoken = findAppWindowToken(token);
4627            if (wtoken == null || wtoken.appToken == null) {
4628                Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
4629                return;
4630            }
4631            final long origId = Binder.clearCallingIdentity();
4632            startAppFreezingScreenLocked(wtoken);
4633            Binder.restoreCallingIdentity(origId);
4634        }
4635    }
4636
4637    @Override
4638    public void stopAppFreezingScreen(IBinder token, boolean force) {
4639        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4640                "setAppFreezingScreen()")) {
4641            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4642        }
4643
4644        synchronized(mWindowMap) {
4645            AppWindowToken wtoken = findAppWindowToken(token);
4646            if (wtoken == null || wtoken.appToken == null) {
4647                return;
4648            }
4649            final long origId = Binder.clearCallingIdentity();
4650            if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
4651                    + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
4652            unsetAppFreezingScreenLocked(wtoken, true, force);
4653            Binder.restoreCallingIdentity(origId);
4654        }
4655    }
4656
4657    void removeAppFromTaskLocked(AppWindowToken wtoken) {
4658        wtoken.removeAllWindows();
4659
4660        final Task task = mTaskIdToTask.get(wtoken.groupId);
4661        if (task != null) {
4662            if (!task.removeAppToken(wtoken)) {
4663                Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found.");
4664            }
4665        }
4666    }
4667
4668    @Override
4669    public void removeAppToken(IBinder token) {
4670        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4671                "removeAppToken()")) {
4672            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4673        }
4674
4675        AppWindowToken wtoken = null;
4676        AppWindowToken startingToken = null;
4677        boolean delayed = false;
4678
4679        final long origId = Binder.clearCallingIdentity();
4680        synchronized(mWindowMap) {
4681            WindowToken basewtoken = mTokenMap.remove(token);
4682            if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
4683                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
4684                delayed = setTokenVisibilityLocked(wtoken, null, false,
4685                        AppTransition.TRANSIT_UNSET, true, wtoken.voiceInteraction);
4686                wtoken.inPendingTransaction = false;
4687                mOpeningApps.remove(wtoken);
4688                wtoken.waitingToShow = false;
4689                if (mClosingApps.contains(wtoken)) {
4690                    delayed = true;
4691                } else if (mAppTransition.isTransitionSet()) {
4692                    mClosingApps.add(wtoken);
4693                    wtoken.waitingToHide = true;
4694                    delayed = true;
4695                }
4696                if (DEBUG_APP_TRANSITIONS) Slog.v(
4697                        TAG, "Removing app " + wtoken + " delayed=" + delayed
4698                        + " animation=" + wtoken.mAppAnimator.animation
4699                        + " animating=" + wtoken.mAppAnimator.animating);
4700                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: "
4701                        + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
4702                final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack;
4703                if (delayed) {
4704                    // set the token aside because it has an active animation to be finished
4705                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
4706                            "removeAppToken make exiting: " + wtoken);
4707                    stack.mExitingAppTokens.add(wtoken);
4708                    wtoken.mDeferRemoval = true;
4709                } else {
4710                    // Make sure there is no animation running on this token,
4711                    // so any windows associated with it will be removed as
4712                    // soon as their animations are complete
4713                    wtoken.mAppAnimator.clearAnimation();
4714                    wtoken.mAppAnimator.animating = false;
4715                    removeAppFromTaskLocked(wtoken);
4716                }
4717
4718                wtoken.removed = true;
4719                if (wtoken.startingData != null) {
4720                    startingToken = wtoken;
4721                }
4722                unsetAppFreezingScreenLocked(wtoken, true, true);
4723                if (mFocusedApp == wtoken) {
4724                    if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken);
4725                    mFocusedApp = null;
4726                    updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
4727                    mInputMonitor.setFocusedAppLw(null);
4728                }
4729            } else {
4730                Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
4731            }
4732
4733            if (!delayed && wtoken != null) {
4734                wtoken.updateReportedVisibilityLocked();
4735            }
4736        }
4737        Binder.restoreCallingIdentity(origId);
4738
4739        // Will only remove if startingToken non null.
4740        scheduleRemoveStartingWindow(startingToken);
4741    }
4742
4743    void scheduleRemoveStartingWindow(AppWindowToken wtoken) {
4744        if (wtoken != null && wtoken.startingWindow != null) {
4745            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
4746                    ": Schedule remove starting " + wtoken + (wtoken != null ?
4747                    " startingWindow=" + wtoken.startingWindow : ""));
4748            Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
4749            mH.sendMessage(m);
4750        }
4751    }
4752
4753    private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
4754        WindowList windows = token.windows;
4755        final int NW = windows.size();
4756        if (NW > 0) {
4757            mWindowsChanged = true;
4758        }
4759        for (int i = 0; i < NW; i++) {
4760            WindowState win = windows.get(i);
4761            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
4762            win.getWindowList().remove(win);
4763            int j = win.mChildWindows.size();
4764            while (j > 0) {
4765                j--;
4766                WindowState cwin = win.mChildWindows.get(j);
4767                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
4768                        "Tmp removing child window " + cwin);
4769                cwin.getWindowList().remove(cwin);
4770            }
4771        }
4772        return NW > 0;
4773    }
4774
4775    void dumpAppTokensLocked() {
4776        final int numStacks = mStackIdToStack.size();
4777        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
4778            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
4779            Slog.v(TAG, "  Stack #" + stack.mStackId + " tasks from bottom to top:");
4780            final ArrayList<Task> tasks = stack.getTasks();
4781            final int numTasks = tasks.size();
4782            for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4783                final Task task = tasks.get(taskNdx);
4784                Slog.v(TAG, "    Task #" + task.taskId + " activities from bottom to top:");
4785                AppTokenList tokens = task.mAppTokens;
4786                final int numTokens = tokens.size();
4787                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4788                    Slog.v(TAG, "      activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token);
4789                }
4790            }
4791        }
4792    }
4793
4794    void dumpWindowsLocked() {
4795        final int numDisplays = mDisplayContents.size();
4796        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4797            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
4798            Slog.v(TAG, " Display #" + displayContent.getDisplayId());
4799            final WindowList windows = displayContent.getWindowList();
4800            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
4801                Slog.v(TAG, "  #" + winNdx + ": " + windows.get(winNdx));
4802            }
4803        }
4804    }
4805
4806    private int findAppWindowInsertionPointLocked(AppWindowToken target) {
4807        final int taskId = target.groupId;
4808        Task targetTask = mTaskIdToTask.get(taskId);
4809        if (targetTask == null) {
4810            Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId="
4811                    + taskId);
4812            return 0;
4813        }
4814        DisplayContent displayContent = targetTask.getDisplayContent();
4815        if (displayContent == null) {
4816            Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target);
4817            return 0;
4818        }
4819        final WindowList windows = displayContent.getWindowList();
4820        final int NW = windows.size();
4821
4822        boolean found = false;
4823        final ArrayList<Task> tasks = displayContent.getTasks();
4824        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
4825            final Task task = tasks.get(taskNdx);
4826            if (!found && task.taskId != taskId) {
4827                continue;
4828            }
4829            AppTokenList tokens = task.mAppTokens;
4830            for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
4831                final AppWindowToken wtoken = tokens.get(tokenNdx);
4832                if (!found && wtoken == target) {
4833                    found = true;
4834                }
4835                if (found) {
4836                    // Find the first app token below the new position that has
4837                    // a window displayed.
4838                    if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token);
4839                    if (wtoken.sendingToBottom) {
4840                        if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom");
4841                        continue;
4842                    }
4843                    for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
4844                        WindowState win = wtoken.windows.get(i);
4845                        for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
4846                            WindowState cwin = win.mChildWindows.get(j);
4847                            if (cwin.mSubLayer >= 0) {
4848                                for (int pos = NW - 1; pos >= 0; pos--) {
4849                                    if (windows.get(pos) == cwin) {
4850                                        if (DEBUG_REORDER) Slog.v(TAG,
4851                                                "Found child win @" + (pos + 1));
4852                                        return pos + 1;
4853                                    }
4854                                }
4855                            }
4856                        }
4857                        for (int pos = NW - 1; pos >= 0; pos--) {
4858                            if (windows.get(pos) == win) {
4859                                if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1));
4860                                return pos + 1;
4861                            }
4862                        }
4863                    }
4864                }
4865            }
4866        }
4867        // Never put an app window underneath wallpaper.
4868        for (int pos = NW - 1; pos >= 0; pos--) {
4869            if (windows.get(pos).mIsWallpaper) {
4870                if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos);
4871                return pos + 1;
4872            }
4873        }
4874        return 0;
4875    }
4876
4877    private final int reAddWindowLocked(int index, WindowState win) {
4878        final WindowList windows = win.getWindowList();
4879        final int NCW = win.mChildWindows.size();
4880        boolean added = false;
4881        for (int j=0; j<NCW; j++) {
4882            WindowState cwin = win.mChildWindows.get(j);
4883            if (!added && cwin.mSubLayer >= 0) {
4884                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
4885                        + index + ": " + cwin);
4886                win.mRebuilding = false;
4887                windows.add(index, win);
4888                index++;
4889                added = true;
4890            }
4891            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4892                    + index + ": " + cwin);
4893            cwin.mRebuilding = false;
4894            windows.add(index, cwin);
4895            index++;
4896        }
4897        if (!added) {
4898            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4899                    + index + ": " + win);
4900            win.mRebuilding = false;
4901            windows.add(index, win);
4902            index++;
4903        }
4904        mWindowsChanged = true;
4905        return index;
4906    }
4907
4908    private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index,
4909                                            WindowToken token) {
4910        final int NW = token.windows.size();
4911        for (int i=0; i<NW; i++) {
4912            final WindowState win = token.windows.get(i);
4913            final DisplayContent winDisplayContent = win.getDisplayContent();
4914            if (winDisplayContent == displayContent || winDisplayContent == null) {
4915                win.mDisplayContent = displayContent;
4916                index = reAddWindowLocked(index, win);
4917            }
4918        }
4919        return index;
4920    }
4921
4922    void tmpRemoveTaskWindowsLocked(Task task) {
4923        AppTokenList tokens = task.mAppTokens;
4924        for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
4925            tmpRemoveAppWindowsLocked(tokens.get(tokenNdx));
4926        }
4927    }
4928
4929    void moveStackWindowsLocked(DisplayContent displayContent) {
4930        // First remove all of the windows from the list.
4931        final ArrayList<Task> tasks = displayContent.getTasks();
4932        final int numTasks = tasks.size();
4933        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4934            tmpRemoveTaskWindowsLocked(tasks.get(taskNdx));
4935        }
4936
4937        // And now add them back at the correct place.
4938        // Where to start adding?
4939        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4940            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
4941            final int numTokens = tokens.size();
4942            if (numTokens == 0) {
4943                continue;
4944            }
4945            int pos = findAppWindowInsertionPointLocked(tokens.get(0));
4946            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4947                final AppWindowToken wtoken = tokens.get(tokenNdx);
4948                if (wtoken != null) {
4949                    final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
4950                    if (newPos != pos) {
4951                        displayContent.layoutNeeded = true;
4952                    }
4953                    pos = newPos;
4954                }
4955            }
4956        }
4957
4958        if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4959                false /*updateInputWindows*/)) {
4960            assignLayersLocked(displayContent.getWindowList());
4961        }
4962
4963        mInputMonitor.setUpdateInputWindowsNeededLw();
4964        performLayoutAndPlaceSurfacesLocked();
4965        mInputMonitor.updateInputWindowsLw(false /*force*/);
4966
4967        //dump();
4968    }
4969
4970    public void moveTaskToTop(int taskId) {
4971        final long origId = Binder.clearCallingIdentity();
4972        try {
4973            synchronized(mWindowMap) {
4974                Task task = mTaskIdToTask.get(taskId);
4975                if (task == null) {
4976                    // Normal behavior, addAppToken will be called next and task will be created.
4977                    return;
4978                }
4979                final TaskStack stack = task.mStack;
4980                final DisplayContent displayContent = task.getDisplayContent();
4981                displayContent.moveStack(stack, true);
4982                if (displayContent.isDefaultDisplay) {
4983                    final TaskStack homeStack = displayContent.getHomeStack();
4984                    if (homeStack != stack) {
4985                        // When a non-home stack moves to the top, the home stack moves to the
4986                        // bottom.
4987                        displayContent.moveStack(homeStack, false);
4988                    }
4989                }
4990                stack.moveTaskToTop(task);
4991            }
4992        } finally {
4993            Binder.restoreCallingIdentity(origId);
4994        }
4995    }
4996
4997    public void moveTaskToBottom(int taskId) {
4998        final long origId = Binder.clearCallingIdentity();
4999        try {
5000            synchronized(mWindowMap) {
5001                Task task = mTaskIdToTask.get(taskId);
5002                if (task == null) {
5003                    Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId
5004                            + " not found in mTaskIdToTask");
5005                    return;
5006                }
5007                final TaskStack stack = task.mStack;
5008                stack.moveTaskToBottom(task);
5009                moveStackWindowsLocked(stack.getDisplayContent());
5010            }
5011        } finally {
5012            Binder.restoreCallingIdentity(origId);
5013        }
5014    }
5015
5016    /**
5017     * Create a new TaskStack and place it on a DisplayContent.
5018     * @param stackId The unique identifier of the new stack.
5019     * @param displayId The unique identifier of the DisplayContent.
5020     */
5021    public void attachStack(int stackId, int displayId) {
5022        final long origId = Binder.clearCallingIdentity();
5023        try {
5024            synchronized (mWindowMap) {
5025                final DisplayContent displayContent = mDisplayContents.get(displayId);
5026                if (displayContent != null) {
5027                    TaskStack stack = mStackIdToStack.get(stackId);
5028                    if (stack == null) {
5029                        if (DEBUG_STACK) Slog.d(TAG, "attachStack: stackId=" + stackId);
5030                        stack = new TaskStack(this, stackId);
5031                        mStackIdToStack.put(stackId, stack);
5032                    }
5033                    stack.attachDisplayContent(displayContent);
5034                    displayContent.attachStack(stack);
5035                    moveStackWindowsLocked(displayContent);
5036                    final WindowList windows = displayContent.getWindowList();
5037                    for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
5038                        windows.get(winNdx).reportResized();
5039                    }
5040                }
5041            }
5042        } finally {
5043            Binder.restoreCallingIdentity(origId);
5044        }
5045    }
5046
5047    void detachStackLocked(DisplayContent displayContent, TaskStack stack) {
5048        displayContent.detachStack(stack);
5049        stack.detachDisplay();
5050    }
5051
5052    public void detachStack(int stackId) {
5053        synchronized (mWindowMap) {
5054            TaskStack stack = mStackIdToStack.get(stackId);
5055            if (stack != null) {
5056                final DisplayContent displayContent = stack.getDisplayContent();
5057                if (displayContent != null) {
5058                    if (stack.isAnimating()) {
5059                        stack.mDeferDetach = true;
5060                        return;
5061                    }
5062                    detachStackLocked(displayContent, stack);
5063                }
5064            }
5065        }
5066    }
5067
5068    public void removeStack(int stackId) {
5069        mStackIdToStack.remove(stackId);
5070    }
5071
5072    void removeTaskLocked(Task task) {
5073        final int taskId = task.taskId;
5074        final TaskStack stack = task.mStack;
5075        if (stack.isAnimating()) {
5076            if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId);
5077            task.mDeferRemoval = true;
5078            return;
5079        }
5080        if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId);
5081        EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask");
5082        task.mDeferRemoval = false;
5083        task.mStack.removeTask(task);
5084        mTaskIdToTask.delete(task.taskId);
5085    }
5086
5087    public void removeTask(int taskId) {
5088        synchronized (mWindowMap) {
5089            Task task = mTaskIdToTask.get(taskId);
5090            if (task == null) {
5091                if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId);
5092                return;
5093            }
5094            removeTaskLocked(task);
5095        }
5096    }
5097
5098    public void addTask(int taskId, int stackId, boolean toTop) {
5099        synchronized (mWindowMap) {
5100            if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId
5101                    + " to " + (toTop ? "top" : "bottom"));
5102            Task task = mTaskIdToTask.get(taskId);
5103            if (task == null) {
5104                return;
5105            }
5106            TaskStack stack = mStackIdToStack.get(stackId);
5107            stack.addTask(task, toTop);
5108            final DisplayContent displayContent = stack.getDisplayContent();
5109            displayContent.layoutNeeded = true;
5110            performLayoutAndPlaceSurfacesLocked();
5111        }
5112    }
5113
5114    public void resizeStack(int stackId, Rect bounds) {
5115        synchronized (mWindowMap) {
5116            final TaskStack stack = mStackIdToStack.get(stackId);
5117            if (stack == null) {
5118                throw new IllegalArgumentException("resizeStack: stackId " + stackId
5119                        + " not found.");
5120            }
5121            if (stack.setBounds(bounds)) {
5122                stack.resizeWindows();
5123                stack.getDisplayContent().layoutNeeded = true;
5124                performLayoutAndPlaceSurfacesLocked();
5125            }
5126        }
5127    }
5128
5129    public void getStackBounds(int stackId, Rect bounds) {
5130        final TaskStack stack = mStackIdToStack.get(stackId);
5131        if (stack != null) {
5132            stack.getBounds(bounds);
5133            return;
5134        }
5135        bounds.setEmpty();
5136    }
5137
5138    // -------------------------------------------------------------
5139    // Misc IWindowSession methods
5140    // -------------------------------------------------------------
5141
5142    @Override
5143    public void startFreezingScreen(int exitAnim, int enterAnim) {
5144        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5145                "startFreezingScreen()")) {
5146            throw new SecurityException("Requires FREEZE_SCREEN permission");
5147        }
5148
5149        synchronized(mWindowMap) {
5150            if (!mClientFreezingScreen) {
5151                mClientFreezingScreen = true;
5152                final long origId = Binder.clearCallingIdentity();
5153                try {
5154                    startFreezingDisplayLocked(false, exitAnim, enterAnim);
5155                    mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
5156                    mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
5157                } finally {
5158                    Binder.restoreCallingIdentity(origId);
5159                }
5160            }
5161        }
5162    }
5163
5164    @Override
5165    public void stopFreezingScreen() {
5166        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5167                "stopFreezingScreen()")) {
5168            throw new SecurityException("Requires FREEZE_SCREEN permission");
5169        }
5170
5171        synchronized(mWindowMap) {
5172            if (mClientFreezingScreen) {
5173                mClientFreezingScreen = false;
5174                mLastFinishedFreezeSource = "client";
5175                final long origId = Binder.clearCallingIdentity();
5176                try {
5177                    stopFreezingDisplayLocked();
5178                } finally {
5179                    Binder.restoreCallingIdentity(origId);
5180                }
5181            }
5182        }
5183    }
5184
5185    @Override
5186    public void disableKeyguard(IBinder token, String tag) {
5187        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5188            != PackageManager.PERMISSION_GRANTED) {
5189            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5190        }
5191
5192        if (token == null) {
5193            throw new IllegalArgumentException("token == null");
5194        }
5195
5196        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5197                KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
5198    }
5199
5200    @Override
5201    public void reenableKeyguard(IBinder token) {
5202        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5203            != PackageManager.PERMISSION_GRANTED) {
5204            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5205        }
5206
5207        if (token == null) {
5208            throw new IllegalArgumentException("token == null");
5209        }
5210
5211        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5212                KeyguardDisableHandler.KEYGUARD_REENABLE, token));
5213    }
5214
5215    /**
5216     * @see android.app.KeyguardManager#exitKeyguardSecurely
5217     */
5218    @Override
5219    public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
5220        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5221            != PackageManager.PERMISSION_GRANTED) {
5222            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5223        }
5224
5225        if (callback == null) {
5226            throw new IllegalArgumentException("callback == null");
5227        }
5228
5229        mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
5230            @Override
5231            public void onKeyguardExitResult(boolean success) {
5232                try {
5233                    callback.onKeyguardExitResult(success);
5234                } catch (RemoteException e) {
5235                    // Client has died, we don't care.
5236                }
5237            }
5238        });
5239    }
5240
5241    @Override
5242    public boolean inKeyguardRestrictedInputMode() {
5243        return mPolicy.inKeyguardRestrictedKeyInputMode();
5244    }
5245
5246    @Override
5247    public boolean isKeyguardLocked() {
5248        return mPolicy.isKeyguardLocked();
5249    }
5250
5251    @Override
5252    public boolean isKeyguardSecure() {
5253        return mPolicy.isKeyguardSecure();
5254    }
5255
5256    @Override
5257    public void dismissKeyguard() {
5258        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5259                != PackageManager.PERMISSION_GRANTED) {
5260            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5261        }
5262        synchronized(mWindowMap) {
5263            mPolicy.dismissKeyguardLw();
5264        }
5265    }
5266
5267    @Override
5268    public void keyguardGoingAway(boolean disableWindowAnimations,
5269            boolean keyguardGoingToNotificationShade) {
5270        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5271                != PackageManager.PERMISSION_GRANTED) {
5272            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5273        }
5274        synchronized (mWindowMap) {
5275            mAnimator.mKeyguardGoingAway = true;
5276            mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade;
5277            mAnimator.mKeyguardGoingAwayDisableWindowAnimations = disableWindowAnimations;
5278            requestTraversalLocked();
5279        }
5280    }
5281
5282    public void keyguardWaitingForActivityDrawn() {
5283        synchronized (mWindowMap) {
5284            mKeyguardWaitingForActivityDrawn = true;
5285        }
5286    }
5287
5288    public void notifyActivityDrawnForKeyguard() {
5289        synchronized (mWindowMap) {
5290            if (mKeyguardWaitingForActivityDrawn) {
5291                mPolicy.notifyActivityDrawnForKeyguardLw();
5292                mKeyguardWaitingForActivityDrawn = false;
5293            }
5294        }
5295    }
5296
5297    void showGlobalActions() {
5298        mPolicy.showGlobalActions();
5299    }
5300
5301    @Override
5302    public void closeSystemDialogs(String reason) {
5303        synchronized(mWindowMap) {
5304            final int numDisplays = mDisplayContents.size();
5305            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5306                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5307                final int numWindows = windows.size();
5308                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5309                    final WindowState w = windows.get(winNdx);
5310                    if (w.mHasSurface) {
5311                        try {
5312                            w.mClient.closeSystemDialogs(reason);
5313                        } catch (RemoteException e) {
5314                        }
5315                    }
5316                }
5317            }
5318        }
5319    }
5320
5321    static float fixScale(float scale) {
5322        if (scale < 0) scale = 0;
5323        else if (scale > 20) scale = 20;
5324        return Math.abs(scale);
5325    }
5326
5327    @Override
5328    public void setAnimationScale(int which, float scale) {
5329        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5330                "setAnimationScale()")) {
5331            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5332        }
5333
5334        scale = fixScale(scale);
5335        switch (which) {
5336            case 0: mWindowAnimationScaleSetting = scale; break;
5337            case 1: mTransitionAnimationScaleSetting = scale; break;
5338            case 2: mAnimatorDurationScaleSetting = scale; break;
5339        }
5340
5341        // Persist setting
5342        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5343    }
5344
5345    @Override
5346    public void setAnimationScales(float[] scales) {
5347        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5348                "setAnimationScale()")) {
5349            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5350        }
5351
5352        if (scales != null) {
5353            if (scales.length >= 1) {
5354                mWindowAnimationScaleSetting = fixScale(scales[0]);
5355            }
5356            if (scales.length >= 2) {
5357                mTransitionAnimationScaleSetting = fixScale(scales[1]);
5358            }
5359            if (scales.length >= 3) {
5360                mAnimatorDurationScaleSetting = fixScale(scales[2]);
5361                dispatchNewAnimatorScaleLocked(null);
5362            }
5363        }
5364
5365        // Persist setting
5366        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5367    }
5368
5369    private void setAnimatorDurationScale(float scale) {
5370        mAnimatorDurationScaleSetting = scale;
5371        ValueAnimator.setDurationScale(scale);
5372    }
5373
5374    public float getWindowAnimationScaleLocked() {
5375        return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting;
5376    }
5377
5378    public float getTransitionAnimationScaleLocked() {
5379        return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting;
5380    }
5381
5382    @Override
5383    public float getAnimationScale(int which) {
5384        switch (which) {
5385            case 0: return mWindowAnimationScaleSetting;
5386            case 1: return mTransitionAnimationScaleSetting;
5387            case 2: return mAnimatorDurationScaleSetting;
5388        }
5389        return 0;
5390    }
5391
5392    @Override
5393    public float[] getAnimationScales() {
5394        return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting,
5395                mAnimatorDurationScaleSetting };
5396    }
5397
5398    @Override
5399    public float getCurrentAnimatorScale() {
5400        synchronized(mWindowMap) {
5401            return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
5402        }
5403    }
5404
5405    void dispatchNewAnimatorScaleLocked(Session session) {
5406        mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget();
5407    }
5408
5409    @Override
5410    public void registerPointerEventListener(PointerEventListener listener) {
5411        mPointerEventDispatcher.registerInputEventListener(listener);
5412    }
5413
5414    @Override
5415    public void unregisterPointerEventListener(PointerEventListener listener) {
5416        mPointerEventDispatcher.unregisterInputEventListener(listener);
5417    }
5418
5419    // Called by window manager policy. Not exposed externally.
5420    @Override
5421    public int getLidState() {
5422        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5423                InputManagerService.SW_LID);
5424        if (sw > 0) {
5425            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5426            return LID_CLOSED;
5427        } else if (sw == 0) {
5428            // Switch state: AKEY_STATE_UP.
5429            return LID_OPEN;
5430        } else {
5431            // Switch state: AKEY_STATE_UNKNOWN.
5432            return LID_ABSENT;
5433        }
5434    }
5435
5436    // Called by window manager policy. Not exposed externally.
5437    @Override
5438    public int getCameraLensCoverState() {
5439        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5440                InputManagerService.SW_CAMERA_LENS_COVER);
5441        if (sw > 0) {
5442            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5443            return CAMERA_LENS_COVERED;
5444        } else if (sw == 0) {
5445            // Switch state: AKEY_STATE_UP.
5446            return CAMERA_LENS_UNCOVERED;
5447        } else {
5448            // Switch state: AKEY_STATE_UNKNOWN.
5449            return CAMERA_LENS_COVER_ABSENT;
5450        }
5451    }
5452
5453    // Called by window manager policy.  Not exposed externally.
5454    @Override
5455    public void switchKeyboardLayout(int deviceId, int direction) {
5456        mInputManager.switchKeyboardLayout(deviceId, direction);
5457    }
5458
5459    // Called by window manager policy.  Not exposed externally.
5460    @Override
5461    public void shutdown(boolean confirm) {
5462        ShutdownThread.shutdown(mContext, confirm);
5463    }
5464
5465    // Called by window manager policy.  Not exposed externally.
5466    @Override
5467    public void rebootSafeMode(boolean confirm) {
5468        ShutdownThread.rebootSafeMode(mContext, confirm);
5469    }
5470
5471    public void setCurrentProfileIds(final int[] currentProfileIds) {
5472        synchronized (mWindowMap) {
5473            mCurrentProfileIds = currentProfileIds;
5474        }
5475    }
5476
5477    public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
5478        synchronized (mWindowMap) {
5479            mCurrentUserId = newUserId;
5480            mCurrentProfileIds = currentProfileIds;
5481            mAppTransition.setCurrentUser(newUserId);
5482            mPolicy.setCurrentUserLw(newUserId);
5483
5484            // Hide windows that should not be seen by the new user.
5485            final int numDisplays = mDisplayContents.size();
5486            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5487                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
5488                displayContent.switchUserStacks(newUserId);
5489                rebuildAppWindowListLocked(displayContent);
5490            }
5491            performLayoutAndPlaceSurfacesLocked();
5492        }
5493    }
5494
5495    /* Called by WindowState */
5496    boolean isCurrentProfileLocked(int userId) {
5497        if (userId == mCurrentUserId) return true;
5498        for (int i = 0; i < mCurrentProfileIds.length; i++) {
5499            if (mCurrentProfileIds[i] == userId) return true;
5500        }
5501        return false;
5502    }
5503
5504    public void enableScreenAfterBoot() {
5505        synchronized(mWindowMap) {
5506            if (DEBUG_BOOT) {
5507                RuntimeException here = new RuntimeException("here");
5508                here.fillInStackTrace();
5509                Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
5510                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5511                        + " mShowingBootMessages=" + mShowingBootMessages
5512                        + " mSystemBooted=" + mSystemBooted, here);
5513            }
5514            if (mSystemBooted) {
5515                return;
5516            }
5517            mSystemBooted = true;
5518            hideBootMessagesLocked();
5519            // If the screen still doesn't come up after 30 seconds, give
5520            // up and turn it on.
5521            mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
5522        }
5523
5524        mPolicy.systemBooted();
5525
5526        performEnableScreen();
5527    }
5528
5529    @Override
5530    public void enableScreenIfNeeded() {
5531        synchronized (mWindowMap) {
5532            enableScreenIfNeededLocked();
5533        }
5534    }
5535
5536    void enableScreenIfNeededLocked() {
5537        if (DEBUG_BOOT) {
5538            RuntimeException here = new RuntimeException("here");
5539            here.fillInStackTrace();
5540            Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
5541                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5542                    + " mShowingBootMessages=" + mShowingBootMessages
5543                    + " mSystemBooted=" + mSystemBooted, here);
5544        }
5545        if (mDisplayEnabled) {
5546            return;
5547        }
5548        if (!mSystemBooted && !mShowingBootMessages) {
5549            return;
5550        }
5551        mH.sendEmptyMessage(H.ENABLE_SCREEN);
5552    }
5553
5554    public void performBootTimeout() {
5555        synchronized(mWindowMap) {
5556            if (mDisplayEnabled) {
5557                return;
5558            }
5559            Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled");
5560            mForceDisplayEnabled = true;
5561        }
5562        performEnableScreen();
5563    }
5564
5565    public void performEnableScreen() {
5566        synchronized(mWindowMap) {
5567            if (DEBUG_BOOT) {
5568                RuntimeException here = new RuntimeException("here");
5569                here.fillInStackTrace();
5570                Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
5571                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5572                        + " mShowingBootMessages=" + mShowingBootMessages
5573                        + " mSystemBooted=" + mSystemBooted
5574                        + " mOnlyCore=" + mOnlyCore, here);
5575            }
5576            if (mDisplayEnabled) {
5577                return;
5578            }
5579            if (!mSystemBooted && !mShowingBootMessages) {
5580                return;
5581            }
5582
5583            if (!mForceDisplayEnabled) {
5584                // Don't enable the screen until all existing windows
5585                // have been drawn.
5586                boolean haveBootMsg = false;
5587                boolean haveApp = false;
5588                // if the wallpaper service is disabled on the device, we're never going to have
5589                // wallpaper, don't bother waiting for it
5590                boolean haveWallpaper = false;
5591                boolean wallpaperEnabled = mContext.getResources().getBoolean(
5592                        com.android.internal.R.bool.config_enableWallpaperService)
5593                        && !mOnlyCore;
5594                boolean haveKeyguard = true;
5595                // TODO(multidisplay): Expand to all displays?
5596                final WindowList windows = getDefaultWindowListLocked();
5597                final int N = windows.size();
5598                for (int i=0; i<N; i++) {
5599                    WindowState w = windows.get(i);
5600                    if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
5601                        return;
5602                    }
5603                    if (w.isDrawnLw()) {
5604                        if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
5605                            haveBootMsg = true;
5606                        } else if (w.mAttrs.type == TYPE_APPLICATION) {
5607                            haveApp = true;
5608                        } else if (w.mAttrs.type == TYPE_WALLPAPER) {
5609                            haveWallpaper = true;
5610                        } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
5611                            haveKeyguard = mPolicy.isKeyguardDrawnLw();
5612                        }
5613                    }
5614                }
5615
5616                if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
5617                    Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
5618                            + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
5619                            + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
5620                            + " haveKeyguard=" + haveKeyguard);
5621                }
5622
5623                // If we are turning on the screen to show the boot message,
5624                // don't do it until the boot message is actually displayed.
5625                if (!mSystemBooted && !haveBootMsg) {
5626                    return;
5627                }
5628
5629                // If we are turning on the screen after the boot is completed
5630                // normally, don't do so until we have the application and
5631                // wallpaper.
5632                if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
5633                        (wallpaperEnabled && !haveWallpaper))) {
5634                    return;
5635                }
5636            }
5637
5638            mDisplayEnabled = true;
5639            if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
5640            if (false) {
5641                StringWriter sw = new StringWriter();
5642                PrintWriter pw = new FastPrintWriter(sw, false, 1024);
5643                this.dump(null, pw, null);
5644                pw.flush();
5645                Slog.i(TAG, sw.toString());
5646            }
5647            try {
5648                IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5649                if (surfaceFlinger != null) {
5650                    //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5651                    Parcel data = Parcel.obtain();
5652                    data.writeInterfaceToken("android.ui.ISurfaceComposer");
5653                    surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5654                                            data, null, 0);
5655                    data.recycle();
5656                }
5657            } catch (RemoteException ex) {
5658                Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
5659            }
5660
5661            // Enable input dispatch.
5662            mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5663        }
5664
5665        mPolicy.enableScreenAfterBoot();
5666
5667        // Make sure the last requested orientation has been applied.
5668        updateRotationUnchecked(false, false);
5669    }
5670
5671    public void showBootMessage(final CharSequence msg, final boolean always) {
5672        boolean first = false;
5673        synchronized(mWindowMap) {
5674            if (DEBUG_BOOT) {
5675                RuntimeException here = new RuntimeException("here");
5676                here.fillInStackTrace();
5677                Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always
5678                        + " mAllowBootMessages=" + mAllowBootMessages
5679                        + " mShowingBootMessages=" + mShowingBootMessages
5680                        + " mSystemBooted=" + mSystemBooted, here);
5681            }
5682            if (!mAllowBootMessages) {
5683                return;
5684            }
5685            if (!mShowingBootMessages) {
5686                if (!always) {
5687                    return;
5688                }
5689                first = true;
5690            }
5691            if (mSystemBooted) {
5692                return;
5693            }
5694            mShowingBootMessages = true;
5695            mPolicy.showBootMessage(msg, always);
5696        }
5697        if (first) {
5698            performEnableScreen();
5699        }
5700    }
5701
5702    public void hideBootMessagesLocked() {
5703        if (DEBUG_BOOT) {
5704            RuntimeException here = new RuntimeException("here");
5705            here.fillInStackTrace();
5706            Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
5707                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5708                    + " mShowingBootMessages=" + mShowingBootMessages
5709                    + " mSystemBooted=" + mSystemBooted, here);
5710        }
5711        if (mShowingBootMessages) {
5712            mShowingBootMessages = false;
5713            mPolicy.hideBootMessages();
5714        }
5715    }
5716
5717    @Override
5718    public void setInTouchMode(boolean mode) {
5719        synchronized(mWindowMap) {
5720            mInTouchMode = mode;
5721        }
5722    }
5723
5724    public void showCircularDisplayMaskIfNeeded() {
5725        // we're fullscreen and not hosted in an ActivityView
5726        if (mContext.getResources().getBoolean(
5727                com.android.internal.R.bool.config_windowIsRound)
5728                && mContext.getResources().getBoolean(
5729                com.android.internal.R.bool.config_windowShowCircularMask)) {
5730            mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK));
5731        }
5732    }
5733
5734    public void showCircularMask() {
5735        synchronized(mWindowMap) {
5736
5737            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5738                    ">>> OPEN TRANSACTION showDisplayMask");
5739            SurfaceControl.openTransaction();
5740            try {
5741                // TODO(multi-display): support multiple displays
5742                if (mCircularDisplayMask == null) {
5743                    int screenOffset = (int) mContext.getResources().getDimensionPixelSize(
5744                            com.android.internal.R.dimen.circular_display_mask_offset);
5745
5746                    mCircularDisplayMask = new CircularDisplayMask(
5747                            getDefaultDisplayContentLocked().getDisplay(),
5748                            mFxSession,
5749                            mPolicy.windowTypeToLayerLw(
5750                                    WindowManager.LayoutParams.TYPE_POINTER)
5751                                    * TYPE_LAYER_MULTIPLIER + 10, screenOffset);
5752                }
5753                mCircularDisplayMask.setVisibility(true);
5754            } finally {
5755                SurfaceControl.closeTransaction();
5756                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5757                        "<<< CLOSE TRANSACTION showDisplayMask");
5758            }
5759        }
5760    }
5761
5762    // TODO: more accounting of which pid(s) turned it on, keep count,
5763    // only allow disables from pids which have count on, etc.
5764    @Override
5765    public void showStrictModeViolation(boolean on) {
5766        int pid = Binder.getCallingPid();
5767        mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
5768    }
5769
5770    private void showStrictModeViolation(int arg, int pid) {
5771        final boolean on = arg != 0;
5772        synchronized(mWindowMap) {
5773            // Ignoring requests to enable the red border from clients
5774            // which aren't on screen.  (e.g. Broadcast Receivers in
5775            // the background..)
5776            if (on) {
5777                boolean isVisible = false;
5778                final int numDisplays = mDisplayContents.size();
5779                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5780                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5781                    final int numWindows = windows.size();
5782                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5783                        final WindowState ws = windows.get(winNdx);
5784                        if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
5785                            isVisible = true;
5786                            break;
5787                        }
5788                    }
5789                }
5790                if (!isVisible) {
5791                    return;
5792                }
5793            }
5794
5795            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5796                    ">>> OPEN TRANSACTION showStrictModeViolation");
5797            SurfaceControl.openTransaction();
5798            try {
5799                // TODO(multi-display): support multiple displays
5800                if (mStrictModeFlash == null) {
5801                    mStrictModeFlash = new StrictModeFlash(
5802                            getDefaultDisplayContentLocked().getDisplay(), mFxSession);
5803                }
5804                mStrictModeFlash.setVisibility(on);
5805            } finally {
5806                SurfaceControl.closeTransaction();
5807                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5808                        "<<< CLOSE TRANSACTION showStrictModeViolation");
5809            }
5810        }
5811    }
5812
5813    @Override
5814    public void setStrictModeVisualIndicatorPreference(String value) {
5815        SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
5816    }
5817
5818    private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
5819        if (rot == Surface.ROTATION_90) {
5820            final int tmp = crop.top;
5821            crop.top = dw - crop.right;
5822            crop.right = crop.bottom;
5823            crop.bottom = dw - crop.left;
5824            crop.left = tmp;
5825        } else if (rot == Surface.ROTATION_180) {
5826            int tmp = crop.top;
5827            crop.top = dh - crop.bottom;
5828            crop.bottom = dh - tmp;
5829            tmp = crop.right;
5830            crop.right = dw - crop.left;
5831            crop.left = dw - tmp;
5832        } else if (rot == Surface.ROTATION_270) {
5833            final int tmp = crop.top;
5834            crop.top = crop.left;
5835            crop.left = dh - crop.bottom;
5836            crop.bottom = crop.right;
5837            crop.right = dh - tmp;
5838        }
5839    }
5840
5841    /**
5842     * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
5843     * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
5844     * of the target image.
5845     *
5846     * @param displayId the Display to take a screenshot of.
5847     * @param width the width of the target bitmap
5848     * @param height the height of the target bitmap
5849     * @param force565 if true the returned bitmap will be RGB_565, otherwise it
5850     *                 will be the same config as the surface
5851     */
5852    @Override
5853    public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
5854            int height, boolean force565) {
5855        if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5856                "screenshotApplications()")) {
5857            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
5858        }
5859
5860        final DisplayContent displayContent = getDisplayContentLocked(displayId);
5861        if (displayContent == null) {
5862            if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
5863                    + ": returning null. No Display for displayId=" + displayId);
5864            return null;
5865        }
5866        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5867        int dw = displayInfo.logicalWidth;
5868        int dh = displayInfo.logicalHeight;
5869        if (dw == 0 || dh == 0) {
5870            if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
5871                    + ": returning null. logical widthxheight=" + dw + "x" + dh);
5872            return null;
5873        }
5874
5875        Bitmap rawss = null;
5876
5877        int maxLayer = 0;
5878        final Rect frame = new Rect();
5879        final Rect stackBounds = new Rect();
5880
5881        float scale = 0;
5882        int rot = Surface.ROTATION_0;
5883
5884        boolean screenshotReady;
5885        int minLayer;
5886        if (appToken == null) {
5887            screenshotReady = true;
5888            minLayer = 0;
5889        } else {
5890            screenshotReady = false;
5891            minLayer = Integer.MAX_VALUE;
5892        }
5893
5894        int retryCount = 0;
5895        WindowState appWin = null;
5896
5897        final boolean appIsImTarget = mInputMethodTarget != null
5898                && mInputMethodTarget.mAppToken != null
5899                && mInputMethodTarget.mAppToken.appToken != null
5900                && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
5901
5902        final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
5903                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
5904
5905        while (true) {
5906            if (retryCount++ > 0) {
5907                try {
5908                    Thread.sleep(100);
5909                } catch (InterruptedException e) {
5910                }
5911            }
5912            synchronized(mWindowMap) {
5913                // Figure out the part of the screen that is actually the app.
5914                appWin = null;
5915                final WindowList windows = displayContent.getWindowList();
5916                for (int i = windows.size() - 1; i >= 0; i--) {
5917                    WindowState ws = windows.get(i);
5918                    if (!ws.mHasSurface) {
5919                        continue;
5920                    }
5921                    if (ws.mLayer >= aboveAppLayer) {
5922                        continue;
5923                    }
5924                    if (ws.mIsImWindow) {
5925                        if (!appIsImTarget) {
5926                            continue;
5927                        }
5928                    } else if (ws.mIsWallpaper) {
5929                        // Fall through.
5930                    } else if (appToken != null) {
5931                        if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
5932                            // This app window is of no interest if it is not associated with the
5933                            // screenshot app.
5934                            continue;
5935                        }
5936                        appWin = ws;
5937                    }
5938
5939                    // Include this window.
5940
5941                    final WindowStateAnimator winAnim = ws.mWinAnimator;
5942                    if (maxLayer < winAnim.mSurfaceLayer) {
5943                        maxLayer = winAnim.mSurfaceLayer;
5944                    }
5945                    if (minLayer > winAnim.mSurfaceLayer) {
5946                        minLayer = winAnim.mSurfaceLayer;
5947                    }
5948
5949                    // Don't include wallpaper in bounds calculation
5950                    if (!ws.mIsWallpaper) {
5951                        final Rect wf = ws.mFrame;
5952                        final Rect cr = ws.mContentInsets;
5953                        int left = wf.left + cr.left;
5954                        int top = wf.top + cr.top;
5955                        int right = wf.right - cr.right;
5956                        int bottom = wf.bottom - cr.bottom;
5957                        frame.union(left, top, right, bottom);
5958                        ws.getStackBounds(stackBounds);
5959                        frame.intersect(stackBounds);
5960                    }
5961
5962                    if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
5963                            ws.isDisplayedLw()) {
5964                        screenshotReady = true;
5965                    }
5966                }
5967
5968                if (appToken != null && appWin == null) {
5969                    // Can't find a window to snapshot.
5970                    if (DEBUG_SCREENSHOT) Slog.i(TAG,
5971                            "Screenshot: Couldn't find a surface matching " + appToken);
5972                    return null;
5973                }
5974
5975                if (!screenshotReady) {
5976                    if (retryCount > MAX_SCREENSHOT_RETRIES) {
5977                        Slog.i(TAG, "Screenshot max retries " + retryCount + " of " + appToken +
5978                                " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
5979                                appWin.mWinAnimator.mDrawState)));
5980                        return null;
5981                    }
5982
5983                    // Delay and hope that window gets drawn.
5984                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken
5985                            + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState);
5986                    continue;
5987                }
5988
5989                // Screenshot is ready to be taken. Everything from here below will continue
5990                // through the bottom of the loop and return a value. We only stay in the loop
5991                // because we don't want to release the mWindowMap lock until the screenshot is
5992                // taken.
5993
5994                if (maxLayer == 0) {
5995                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
5996                            + ": returning null maxLayer=" + maxLayer);
5997                    return null;
5998                }
5999
6000                // Constrain frame to the screen size.
6001                frame.intersect(0, 0, dw, dh);
6002
6003                // Tell surface flinger what part of the image to crop. Take the top
6004                // right part of the application, and crop the larger dimension to fit.
6005                Rect crop = new Rect(frame);
6006                if (width / (float) frame.width() < height / (float) frame.height()) {
6007                    int cropWidth = (int)((float)width / (float)height * frame.height());
6008                    crop.right = crop.left + cropWidth;
6009                } else {
6010                    int cropHeight = (int)((float)height / (float)width * frame.width());
6011                    crop.bottom = crop.top + cropHeight;
6012                }
6013
6014                // The screenshot API does not apply the current screen rotation.
6015                rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
6016                if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
6017                    final int tmp = width;
6018                    width = height;
6019                    height = tmp;
6020                    rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
6021                }
6022
6023                // Surfaceflinger is not aware of orientation, so convert our logical
6024                // crop to surfaceflinger's portrait orientation.
6025                convertCropForSurfaceFlinger(crop, rot, dw, dh);
6026
6027                if (DEBUG_SCREENSHOT) {
6028                    Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
6029                            + maxLayer + " appToken=" + appToken);
6030                    for (int i = 0; i < windows.size(); i++) {
6031                        WindowState win = windows.get(i);
6032                        Slog.i(TAG, win + ": " + win.mLayer
6033                                + " animLayer=" + win.mWinAnimator.mAnimLayer
6034                                + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
6035                    }
6036                }
6037
6038                ScreenRotationAnimation screenRotationAnimation =
6039                        mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6040                final boolean inRotation = screenRotationAnimation != null &&
6041                        screenRotationAnimation.isAnimating();
6042                if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG,
6043                        "Taking screenshot while rotating");
6044
6045                rawss = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
6046                        inRotation);
6047                if (rawss == null) {
6048                    Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
6049                            + ") to layer " + maxLayer);
6050                    return null;
6051                }
6052            }
6053
6054            break;
6055        }
6056
6057        Bitmap bm = Bitmap.createBitmap(width, height, force565 ?
6058                Config.RGB_565 : rawss.getConfig());
6059        if (DEBUG_SCREENSHOT) {
6060            bm.eraseColor(0xFF000000);
6061        }
6062        Matrix matrix = new Matrix();
6063        ScreenRotationAnimation.createRotationMatrix(rot, width, height, matrix);
6064        Canvas canvas = new Canvas(bm);
6065        canvas.drawBitmap(rawss, matrix, null);
6066        canvas.setBitmap(null);
6067
6068        if (DEBUG_SCREENSHOT) {
6069            // TEST IF IT's ALL BLACK
6070            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
6071            bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
6072            boolean allBlack = true;
6073            final int firstColor = buffer[0];
6074            for (int i = 0; i < buffer.length; i++) {
6075                if (buffer[i] != firstColor) {
6076                    allBlack = false;
6077                    break;
6078                }
6079            }
6080            if (allBlack) {
6081                Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" +
6082                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
6083                        (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") +
6084                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
6085            }
6086        }
6087
6088        rawss.recycle();
6089
6090        return bm;
6091    }
6092
6093    /**
6094     * Freeze rotation changes.  (Enable "rotation lock".)
6095     * Persists across reboots.
6096     * @param rotation The desired rotation to freeze to, or -1 to use the
6097     * current rotation.
6098     */
6099    @Override
6100    public void freezeRotation(int rotation) {
6101        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
6102                "freezeRotation()")) {
6103            throw new SecurityException("Requires SET_ORIENTATION permission");
6104        }
6105        if (rotation < -1 || rotation > Surface.ROTATION_270) {
6106            throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
6107                    + "rotation constant.");
6108        }
6109
6110        if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
6111
6112        long origId = Binder.clearCallingIdentity();
6113        try {
6114            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
6115                    rotation == -1 ? mRotation : rotation);
6116        } finally {
6117            Binder.restoreCallingIdentity(origId);
6118        }
6119
6120        updateRotationUnchecked(false, false);
6121    }
6122
6123    /**
6124     * Thaw rotation changes.  (Disable "rotation lock".)
6125     * Persists across reboots.
6126     */
6127    @Override
6128    public void thawRotation() {
6129        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
6130                "thawRotation()")) {
6131            throw new SecurityException("Requires SET_ORIENTATION permission");
6132        }
6133
6134        if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
6135
6136        long origId = Binder.clearCallingIdentity();
6137        try {
6138            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
6139                    777); // rot not used
6140        } finally {
6141            Binder.restoreCallingIdentity(origId);
6142        }
6143
6144        updateRotationUnchecked(false, false);
6145    }
6146
6147    /**
6148     * Recalculate the current rotation.
6149     *
6150     * Called by the window manager policy whenever the state of the system changes
6151     * such that the current rotation might need to be updated, such as when the
6152     * device is docked or rotated into a new posture.
6153     */
6154    @Override
6155    public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
6156        updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
6157    }
6158
6159    /**
6160     * Temporarily pauses rotation changes until resumed.
6161     *
6162     * This can be used to prevent rotation changes from occurring while the user is
6163     * performing certain operations, such as drag and drop.
6164     *
6165     * This call nests and must be matched by an equal number of calls to
6166     * {@link #resumeRotationLocked}.
6167     */
6168    void pauseRotationLocked() {
6169        mDeferredRotationPauseCount += 1;
6170    }
6171
6172    /**
6173     * Resumes normal rotation changes after being paused.
6174     */
6175    void resumeRotationLocked() {
6176        if (mDeferredRotationPauseCount > 0) {
6177            mDeferredRotationPauseCount -= 1;
6178            if (mDeferredRotationPauseCount == 0) {
6179                boolean changed = updateRotationUncheckedLocked(false);
6180                if (changed) {
6181                    mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6182                }
6183            }
6184        }
6185    }
6186
6187    public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
6188        if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
6189                   + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
6190
6191        long origId = Binder.clearCallingIdentity();
6192        boolean changed;
6193        synchronized(mWindowMap) {
6194            changed = updateRotationUncheckedLocked(false);
6195            if (!changed || forceRelayout) {
6196                getDefaultDisplayContentLocked().layoutNeeded = true;
6197                performLayoutAndPlaceSurfacesLocked();
6198            }
6199        }
6200
6201        if (changed || alwaysSendConfiguration) {
6202            sendNewConfiguration();
6203        }
6204
6205        Binder.restoreCallingIdentity(origId);
6206    }
6207
6208    // TODO(multidisplay): Rotate any display?
6209    /**
6210     * Updates the current rotation.
6211     *
6212     * Returns true if the rotation has been changed.  In this case YOU
6213     * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
6214     */
6215    public boolean updateRotationUncheckedLocked(boolean inTransaction) {
6216        if (mDeferredRotationPauseCount > 0) {
6217            // Rotation updates have been paused temporarily.  Defer the update until
6218            // updates have been resumed.
6219            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");
6220            return false;
6221        }
6222
6223        ScreenRotationAnimation screenRotationAnimation =
6224                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6225        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
6226            // Rotation updates cannot be performed while the previous rotation change
6227            // animation is still in progress.  Skip this update.  We will try updating
6228            // again after the animation is finished and the display is unfrozen.
6229            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");
6230            return false;
6231        }
6232
6233        if (!mDisplayEnabled) {
6234            // No point choosing a rotation if the display is not enabled.
6235            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");
6236            return false;
6237        }
6238
6239        // TODO: Implement forced rotation changes.
6240        //       Set mAltOrientation to indicate that the application is receiving
6241        //       an orientation that has different metrics than it expected.
6242        //       eg. Portrait instead of Landscape.
6243
6244        int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
6245        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
6246                mForcedAppOrientation, rotation);
6247
6248        if (DEBUG_ORIENTATION) {
6249            Slog.v(TAG, "Application requested orientation "
6250                    + mForcedAppOrientation + ", got rotation " + rotation
6251                    + " which has " + (altOrientation ? "incompatible" : "compatible")
6252                    + " metrics");
6253        }
6254
6255        if (mRotation == rotation && mAltOrientation == altOrientation) {
6256            // No change.
6257            return false;
6258        }
6259
6260        if (DEBUG_ORIENTATION) {
6261            Slog.v(TAG,
6262                "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
6263                + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
6264                + ", forceApp=" + mForcedAppOrientation);
6265        }
6266
6267        mRotation = rotation;
6268        mAltOrientation = altOrientation;
6269        mPolicy.setRotationLw(mRotation);
6270
6271        mWindowsFreezingScreen = true;
6272        mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
6273        mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
6274        mWaitingForConfig = true;
6275        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6276        displayContent.layoutNeeded = true;
6277        final int[] anim = new int[2];
6278        if (displayContent.isDimming()) {
6279            anim[0] = anim[1] = 0;
6280        } else {
6281            mPolicy.selectRotationAnimationLw(anim);
6282        }
6283        startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
6284        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
6285        screenRotationAnimation =
6286                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6287
6288        // We need to update our screen size information to match the new
6289        // rotation.  Note that this is redundant with the later call to
6290        // sendNewConfiguration() that must be called after this function
6291        // returns...  however we need to do the screen size part of that
6292        // before then so we have the correct size to use when initializing
6293        // the rotation animation for the new rotation.
6294        computeScreenConfigurationLocked(null);
6295
6296        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6297        if (!inTransaction) {
6298            if (SHOW_TRANSACTIONS) {
6299                Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
6300            }
6301            SurfaceControl.openTransaction();
6302        }
6303        try {
6304            // NOTE: We disable the rotation in the emulator because
6305            //       it doesn't support hardware OpenGL emulation yet.
6306            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
6307                    && screenRotationAnimation.hasScreenshot()) {
6308                if (screenRotationAnimation.setRotationInTransaction(
6309                        rotation, mFxSession,
6310                        MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(),
6311                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
6312                    scheduleAnimationLocked();
6313                }
6314            }
6315
6316            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
6317        } finally {
6318            if (!inTransaction) {
6319                SurfaceControl.closeTransaction();
6320                if (SHOW_LIGHT_TRANSACTIONS) {
6321                    Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
6322                }
6323            }
6324        }
6325
6326        final WindowList windows = displayContent.getWindowList();
6327        for (int i = windows.size() - 1; i >= 0; i--) {
6328            WindowState w = windows.get(i);
6329            if (w.mHasSurface) {
6330                if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
6331                w.mOrientationChanging = true;
6332                mInnerFields.mOrientationChangeComplete = false;
6333            }
6334            w.mLastFreezeDuration = 0;
6335        }
6336
6337        for (int i=mRotationWatchers.size()-1; i>=0; i--) {
6338            try {
6339                mRotationWatchers.get(i).watcher.onRotationChanged(rotation);
6340            } catch (RemoteException e) {
6341            }
6342        }
6343
6344        //TODO (multidisplay): Magnification is supported only for the default display.
6345        if (mAccessibilityController != null
6346                && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
6347            mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation);
6348        }
6349
6350        return true;
6351    }
6352
6353    @Override
6354    public int getRotation() {
6355        return mRotation;
6356    }
6357
6358    @Override
6359    public boolean isRotationFrozen() {
6360        return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6361    }
6362
6363    @Override
6364    public int watchRotation(IRotationWatcher watcher) {
6365        final IBinder watcherBinder = watcher.asBinder();
6366        IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6367            @Override
6368            public void binderDied() {
6369                synchronized (mWindowMap) {
6370                    for (int i=0; i<mRotationWatchers.size(); i++) {
6371                        if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) {
6372                            RotationWatcher removed = mRotationWatchers.remove(i);
6373                            IBinder binder = removed.watcher.asBinder();
6374                            if (binder != null) {
6375                                binder.unlinkToDeath(this, 0);
6376                            }
6377                            i--;
6378                        }
6379                    }
6380                }
6381            }
6382        };
6383
6384        synchronized (mWindowMap) {
6385            try {
6386                watcher.asBinder().linkToDeath(dr, 0);
6387                mRotationWatchers.add(new RotationWatcher(watcher, dr));
6388            } catch (RemoteException e) {
6389                // Client died, no cleanup needed.
6390            }
6391
6392            return mRotation;
6393        }
6394    }
6395
6396    @Override
6397    public void removeRotationWatcher(IRotationWatcher watcher) {
6398        final IBinder watcherBinder = watcher.asBinder();
6399        synchronized (mWindowMap) {
6400            for (int i=0; i<mRotationWatchers.size(); i++) {
6401                RotationWatcher rotationWatcher = mRotationWatchers.get(i);
6402                if (watcherBinder == rotationWatcher.watcher.asBinder()) {
6403                    RotationWatcher removed = mRotationWatchers.remove(i);
6404                    IBinder binder = removed.watcher.asBinder();
6405                    if (binder != null) {
6406                        binder.unlinkToDeath(removed.deathRecipient, 0);
6407                    }
6408                    i--;
6409                }
6410            }
6411        }
6412    }
6413
6414    /**
6415     * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6416     * theme attribute) on devices that feature a physical options menu key attempt to position
6417     * their menu panel window along the edge of the screen nearest the physical menu key.
6418     * This lowers the travel distance between invoking the menu panel and selecting
6419     * a menu option.
6420     *
6421     * This method helps control where that menu is placed. Its current implementation makes
6422     * assumptions about the menu key and its relationship to the screen based on whether
6423     * the device's natural orientation is portrait (width < height) or landscape.
6424     *
6425     * The menu key is assumed to be located along the bottom edge of natural-portrait
6426     * devices and along the right edge of natural-landscape devices. If these assumptions
6427     * do not hold for the target device, this method should be changed to reflect that.
6428     *
6429     * @return A {@link Gravity} value for placing the options menu window
6430     */
6431    @Override
6432    public int getPreferredOptionsPanelGravity() {
6433        synchronized (mWindowMap) {
6434            final int rotation = getRotation();
6435
6436            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6437            final DisplayContent displayContent = getDefaultDisplayContentLocked();
6438            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6439                // On devices with a natural orientation of portrait
6440                switch (rotation) {
6441                    default:
6442                    case Surface.ROTATION_0:
6443                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6444                    case Surface.ROTATION_90:
6445                        return Gravity.RIGHT | Gravity.BOTTOM;
6446                    case Surface.ROTATION_180:
6447                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6448                    case Surface.ROTATION_270:
6449                        return Gravity.START | Gravity.BOTTOM;
6450                }
6451            }
6452
6453            // On devices with a natural orientation of landscape
6454            switch (rotation) {
6455                default:
6456                case Surface.ROTATION_0:
6457                    return Gravity.RIGHT | Gravity.BOTTOM;
6458                case Surface.ROTATION_90:
6459                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6460                case Surface.ROTATION_180:
6461                    return Gravity.START | Gravity.BOTTOM;
6462                case Surface.ROTATION_270:
6463                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6464            }
6465        }
6466    }
6467
6468    /**
6469     * Starts the view server on the specified port.
6470     *
6471     * @param port The port to listener to.
6472     *
6473     * @return True if the server was successfully started, false otherwise.
6474     *
6475     * @see com.android.server.wm.ViewServer
6476     * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
6477     */
6478    @Override
6479    public boolean startViewServer(int port) {
6480        if (isSystemSecure()) {
6481            return false;
6482        }
6483
6484        if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
6485            return false;
6486        }
6487
6488        if (port < 1024) {
6489            return false;
6490        }
6491
6492        if (mViewServer != null) {
6493            if (!mViewServer.isRunning()) {
6494                try {
6495                    return mViewServer.start();
6496                } catch (IOException e) {
6497                    Slog.w(TAG, "View server did not start");
6498                }
6499            }
6500            return false;
6501        }
6502
6503        try {
6504            mViewServer = new ViewServer(this, port);
6505            return mViewServer.start();
6506        } catch (IOException e) {
6507            Slog.w(TAG, "View server did not start");
6508        }
6509        return false;
6510    }
6511
6512    private boolean isSystemSecure() {
6513        return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
6514                "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6515    }
6516
6517    /**
6518     * Stops the view server if it exists.
6519     *
6520     * @return True if the server stopped, false if it wasn't started or
6521     *         couldn't be stopped.
6522     *
6523     * @see com.android.server.wm.ViewServer
6524     */
6525    @Override
6526    public boolean stopViewServer() {
6527        if (isSystemSecure()) {
6528            return false;
6529        }
6530
6531        if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
6532            return false;
6533        }
6534
6535        if (mViewServer != null) {
6536            return mViewServer.stop();
6537        }
6538        return false;
6539    }
6540
6541    /**
6542     * Indicates whether the view server is running.
6543     *
6544     * @return True if the server is running, false otherwise.
6545     *
6546     * @see com.android.server.wm.ViewServer
6547     */
6548    @Override
6549    public boolean isViewServerRunning() {
6550        if (isSystemSecure()) {
6551            return false;
6552        }
6553
6554        if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
6555            return false;
6556        }
6557
6558        return mViewServer != null && mViewServer.isRunning();
6559    }
6560
6561    /**
6562     * Lists all availble windows in the system. The listing is written in the
6563     * specified Socket's output stream with the following syntax:
6564     * windowHashCodeInHexadecimal windowName
6565     * Each line of the ouput represents a different window.
6566     *
6567     * @param client The remote client to send the listing to.
6568     * @return False if an error occured, true otherwise.
6569     */
6570    boolean viewServerListWindows(Socket client) {
6571        if (isSystemSecure()) {
6572            return false;
6573        }
6574
6575        boolean result = true;
6576
6577        WindowList windows = new WindowList();
6578        synchronized (mWindowMap) {
6579            //noinspection unchecked
6580            final int numDisplays = mDisplayContents.size();
6581            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6582                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
6583                windows.addAll(displayContent.getWindowList());
6584            }
6585        }
6586
6587        BufferedWriter out = null;
6588
6589        // Any uncaught exception will crash the system process
6590        try {
6591            OutputStream clientStream = client.getOutputStream();
6592            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6593
6594            final int count = windows.size();
6595            for (int i = 0; i < count; i++) {
6596                final WindowState w = windows.get(i);
6597                out.write(Integer.toHexString(System.identityHashCode(w)));
6598                out.write(' ');
6599                out.append(w.mAttrs.getTitle());
6600                out.write('\n');
6601            }
6602
6603            out.write("DONE.\n");
6604            out.flush();
6605        } catch (Exception e) {
6606            result = false;
6607        } finally {
6608            if (out != null) {
6609                try {
6610                    out.close();
6611                } catch (IOException e) {
6612                    result = false;
6613                }
6614            }
6615        }
6616
6617        return result;
6618    }
6619
6620    // TODO(multidisplay): Extend to multiple displays.
6621    /**
6622     * Returns the focused window in the following format:
6623     * windowHashCodeInHexadecimal windowName
6624     *
6625     * @param client The remote client to send the listing to.
6626     * @return False if an error occurred, true otherwise.
6627     */
6628    boolean viewServerGetFocusedWindow(Socket client) {
6629        if (isSystemSecure()) {
6630            return false;
6631        }
6632
6633        boolean result = true;
6634
6635        WindowState focusedWindow = getFocusedWindow();
6636
6637        BufferedWriter out = null;
6638
6639        // Any uncaught exception will crash the system process
6640        try {
6641            OutputStream clientStream = client.getOutputStream();
6642            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6643
6644            if(focusedWindow != null) {
6645                out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
6646                out.write(' ');
6647                out.append(focusedWindow.mAttrs.getTitle());
6648            }
6649            out.write('\n');
6650            out.flush();
6651        } catch (Exception e) {
6652            result = false;
6653        } finally {
6654            if (out != null) {
6655                try {
6656                    out.close();
6657                } catch (IOException e) {
6658                    result = false;
6659                }
6660            }
6661        }
6662
6663        return result;
6664    }
6665
6666    /**
6667     * Sends a command to a target window. The result of the command, if any, will be
6668     * written in the output stream of the specified socket.
6669     *
6670     * The parameters must follow this syntax:
6671     * windowHashcode extra
6672     *
6673     * Where XX is the length in characeters of the windowTitle.
6674     *
6675     * The first parameter is the target window. The window with the specified hashcode
6676     * will be the target. If no target can be found, nothing happens. The extra parameters
6677     * will be delivered to the target window and as parameters to the command itself.
6678     *
6679     * @param client The remote client to sent the result, if any, to.
6680     * @param command The command to execute.
6681     * @param parameters The command parameters.
6682     *
6683     * @return True if the command was successfully delivered, false otherwise. This does
6684     *         not indicate whether the command itself was successful.
6685     */
6686    boolean viewServerWindowCommand(Socket client, String command, String parameters) {
6687        if (isSystemSecure()) {
6688            return false;
6689        }
6690
6691        boolean success = true;
6692        Parcel data = null;
6693        Parcel reply = null;
6694
6695        BufferedWriter out = null;
6696
6697        // Any uncaught exception will crash the system process
6698        try {
6699            // Find the hashcode of the window
6700            int index = parameters.indexOf(' ');
6701            if (index == -1) {
6702                index = parameters.length();
6703            }
6704            final String code = parameters.substring(0, index);
6705            int hashCode = (int) Long.parseLong(code, 16);
6706
6707            // Extract the command's parameter after the window description
6708            if (index < parameters.length()) {
6709                parameters = parameters.substring(index + 1);
6710            } else {
6711                parameters = "";
6712            }
6713
6714            final WindowState window = findWindow(hashCode);
6715            if (window == null) {
6716                return false;
6717            }
6718
6719            data = Parcel.obtain();
6720            data.writeInterfaceToken("android.view.IWindow");
6721            data.writeString(command);
6722            data.writeString(parameters);
6723            data.writeInt(1);
6724            ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
6725
6726            reply = Parcel.obtain();
6727
6728            final IBinder binder = window.mClient.asBinder();
6729            // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
6730            binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
6731
6732            reply.readException();
6733
6734            if (!client.isOutputShutdown()) {
6735                out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
6736                out.write("DONE\n");
6737                out.flush();
6738            }
6739
6740        } catch (Exception e) {
6741            Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
6742            success = false;
6743        } finally {
6744            if (data != null) {
6745                data.recycle();
6746            }
6747            if (reply != null) {
6748                reply.recycle();
6749            }
6750            if (out != null) {
6751                try {
6752                    out.close();
6753                } catch (IOException e) {
6754
6755                }
6756            }
6757        }
6758
6759        return success;
6760    }
6761
6762    public void addWindowChangeListener(WindowChangeListener listener) {
6763        synchronized(mWindowMap) {
6764            mWindowChangeListeners.add(listener);
6765        }
6766    }
6767
6768    public void removeWindowChangeListener(WindowChangeListener listener) {
6769        synchronized(mWindowMap) {
6770            mWindowChangeListeners.remove(listener);
6771        }
6772    }
6773
6774    private void notifyWindowsChanged() {
6775        WindowChangeListener[] windowChangeListeners;
6776        synchronized(mWindowMap) {
6777            if(mWindowChangeListeners.isEmpty()) {
6778                return;
6779            }
6780            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6781            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6782        }
6783        int N = windowChangeListeners.length;
6784        for(int i = 0; i < N; i++) {
6785            windowChangeListeners[i].windowsChanged();
6786        }
6787    }
6788
6789    private void notifyFocusChanged() {
6790        WindowChangeListener[] windowChangeListeners;
6791        synchronized(mWindowMap) {
6792            if(mWindowChangeListeners.isEmpty()) {
6793                return;
6794            }
6795            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6796            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6797        }
6798        int N = windowChangeListeners.length;
6799        for(int i = 0; i < N; i++) {
6800            windowChangeListeners[i].focusChanged();
6801        }
6802    }
6803
6804    private WindowState findWindow(int hashCode) {
6805        if (hashCode == -1) {
6806            // TODO(multidisplay): Extend to multiple displays.
6807            return getFocusedWindow();
6808        }
6809
6810        synchronized (mWindowMap) {
6811            final int numDisplays = mDisplayContents.size();
6812            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6813                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
6814                final int numWindows = windows.size();
6815                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
6816                    final WindowState w = windows.get(winNdx);
6817                    if (System.identityHashCode(w) == hashCode) {
6818                        return w;
6819                    }
6820                }
6821            }
6822        }
6823
6824        return null;
6825    }
6826
6827    /*
6828     * Instruct the Activity Manager to fetch the current configuration and broadcast
6829     * that to config-changed listeners if appropriate.
6830     */
6831    void sendNewConfiguration() {
6832        try {
6833            mActivityManager.updateConfiguration(null);
6834        } catch (RemoteException e) {
6835        }
6836    }
6837
6838    public Configuration computeNewConfiguration() {
6839        synchronized (mWindowMap) {
6840            Configuration config = computeNewConfigurationLocked();
6841            if (config == null && mWaitingForConfig) {
6842                // Nothing changed but we are waiting for something... stop that!
6843                mWaitingForConfig = false;
6844                mLastFinishedFreezeSource = "new-config";
6845                performLayoutAndPlaceSurfacesLocked();
6846            }
6847            return config;
6848        }
6849    }
6850
6851    Configuration computeNewConfigurationLocked() {
6852        Configuration config = new Configuration();
6853        config.fontScale = 0;
6854        if (!computeScreenConfigurationLocked(config)) {
6855            return null;
6856        }
6857        return config;
6858    }
6859
6860    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
6861        // TODO: Multidisplay: for now only use with default display.
6862        final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
6863        if (width < displayInfo.smallestNominalAppWidth) {
6864            displayInfo.smallestNominalAppWidth = width;
6865        }
6866        if (width > displayInfo.largestNominalAppWidth) {
6867            displayInfo.largestNominalAppWidth = width;
6868        }
6869        final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
6870        if (height < displayInfo.smallestNominalAppHeight) {
6871            displayInfo.smallestNominalAppHeight = height;
6872        }
6873        if (height > displayInfo.largestNominalAppHeight) {
6874            displayInfo.largestNominalAppHeight = height;
6875        }
6876    }
6877
6878    private int reduceConfigLayout(int curLayout, int rotation, float density,
6879            int dw, int dh) {
6880        // TODO: Multidisplay: for now only use with default display.
6881        // Get the app screen size at this rotation.
6882        int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6883        int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6884
6885        // Compute the screen layout size class for this rotation.
6886        int longSize = w;
6887        int shortSize = h;
6888        if (longSize < shortSize) {
6889            int tmp = longSize;
6890            longSize = shortSize;
6891            shortSize = tmp;
6892        }
6893        longSize = (int)(longSize/density);
6894        shortSize = (int)(shortSize/density);
6895        return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
6896    }
6897
6898    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
6899                  int dw, int dh, float density, Configuration outConfig) {
6900        // TODO: Multidisplay: for now only use with default display.
6901
6902        // We need to determine the smallest width that will occur under normal
6903        // operation.  To this, start with the base screen size and compute the
6904        // width under the different possible rotations.  We need to un-rotate
6905        // the current screen dimensions before doing this.
6906        int unrotDw, unrotDh;
6907        if (rotated) {
6908            unrotDw = dh;
6909            unrotDh = dw;
6910        } else {
6911            unrotDw = dw;
6912            unrotDh = dh;
6913        }
6914        displayInfo.smallestNominalAppWidth = 1<<30;
6915        displayInfo.smallestNominalAppHeight = 1<<30;
6916        displayInfo.largestNominalAppWidth = 0;
6917        displayInfo.largestNominalAppHeight = 0;
6918        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
6919        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
6920        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
6921        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
6922        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
6923        sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
6924        sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
6925        sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
6926        sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
6927        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
6928        outConfig.screenLayout = sl;
6929    }
6930
6931    private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
6932            int dw, int dh) {
6933        // TODO: Multidisplay: for now only use with default display.
6934        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6935        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6936        float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
6937        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
6938        if (curSize == 0 || size < curSize) {
6939            curSize = size;
6940        }
6941        return curSize;
6942    }
6943
6944    private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) {
6945        // TODO: Multidisplay: for now only use with default display.
6946        mTmpDisplayMetrics.setTo(dm);
6947        final DisplayMetrics tmpDm = mTmpDisplayMetrics;
6948        final int unrotDw, unrotDh;
6949        if (rotated) {
6950            unrotDw = dh;
6951            unrotDh = dw;
6952        } else {
6953            unrotDw = dw;
6954            unrotDh = dh;
6955        }
6956        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
6957        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
6958        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
6959        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
6960        return sw;
6961    }
6962
6963    boolean computeScreenConfigurationLocked(Configuration config) {
6964        if (!mDisplayReady) {
6965            return false;
6966        }
6967
6968        // TODO(multidisplay): For now, apply Configuration to main screen only.
6969        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6970
6971        // Use the effective "visual" dimensions based on current rotation
6972        final boolean rotated = (mRotation == Surface.ROTATION_90
6973                || mRotation == Surface.ROTATION_270);
6974        final int realdw = rotated ?
6975                displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
6976        final int realdh = rotated ?
6977                displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
6978        int dw = realdw;
6979        int dh = realdh;
6980
6981        if (mAltOrientation) {
6982            if (realdw > realdh) {
6983                // Turn landscape into portrait.
6984                int maxw = (int)(realdh/1.3f);
6985                if (maxw < realdw) {
6986                    dw = maxw;
6987                }
6988            } else {
6989                // Turn portrait into landscape.
6990                int maxh = (int)(realdw/1.3f);
6991                if (maxh < realdh) {
6992                    dh = maxh;
6993                }
6994            }
6995        }
6996
6997        if (config != null) {
6998            config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
6999                    Configuration.ORIENTATION_LANDSCAPE;
7000        }
7001
7002        // Update application display metrics.
7003        final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
7004        final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
7005        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7006        synchronized(displayContent.mDisplaySizeLock) {
7007            displayInfo.rotation = mRotation;
7008            displayInfo.logicalWidth = dw;
7009            displayInfo.logicalHeight = dh;
7010            displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
7011            displayInfo.appWidth = appWidth;
7012            displayInfo.appHeight = appHeight;
7013            displayInfo.getLogicalMetrics(mRealDisplayMetrics,
7014                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
7015            displayInfo.getAppMetrics(mDisplayMetrics);
7016            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
7017                    displayContent.getDisplayId(), displayInfo);
7018        }
7019        if (false) {
7020            Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
7021        }
7022
7023        final DisplayMetrics dm = mDisplayMetrics;
7024        mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
7025                mCompatDisplayMetrics);
7026
7027        if (config != null) {
7028            config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
7029                    / dm.density);
7030            config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
7031                    / dm.density);
7032            computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
7033
7034            config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
7035            config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
7036            config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
7037            config.densityDpi = displayContent.mBaseDisplayDensity;
7038
7039            // Update the configuration based on available input devices, lid switch,
7040            // and platform configuration.
7041            config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
7042            config.keyboard = Configuration.KEYBOARD_NOKEYS;
7043            config.navigation = Configuration.NAVIGATION_NONAV;
7044
7045            int keyboardPresence = 0;
7046            int navigationPresence = 0;
7047            final InputDevice[] devices = mInputManager.getInputDevices();
7048            final int len = devices.length;
7049            for (int i = 0; i < len; i++) {
7050                InputDevice device = devices[i];
7051                if (!device.isVirtual()) {
7052                    final int sources = device.getSources();
7053                    final int presenceFlag = device.isExternal() ?
7054                            WindowManagerPolicy.PRESENCE_EXTERNAL :
7055                                    WindowManagerPolicy.PRESENCE_INTERNAL;
7056
7057                    if (mIsTouchDevice) {
7058                        if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
7059                                InputDevice.SOURCE_TOUCHSCREEN) {
7060                            config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
7061                        }
7062                    } else {
7063                        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
7064                    }
7065
7066                    if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
7067                        config.navigation = Configuration.NAVIGATION_TRACKBALL;
7068                        navigationPresence |= presenceFlag;
7069                    } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
7070                            && config.navigation == Configuration.NAVIGATION_NONAV) {
7071                        config.navigation = Configuration.NAVIGATION_DPAD;
7072                        navigationPresence |= presenceFlag;
7073                    }
7074
7075                    if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
7076                        config.keyboard = Configuration.KEYBOARD_QWERTY;
7077                        keyboardPresence |= presenceFlag;
7078                    }
7079                }
7080            }
7081
7082            // Determine whether a hard keyboard is available and enabled.
7083            boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
7084            if (hardKeyboardAvailable != mHardKeyboardAvailable) {
7085                mHardKeyboardAvailable = hardKeyboardAvailable;
7086                mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
7087                mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
7088            }
7089            if (mShowImeWithHardKeyboard) {
7090                config.keyboard = Configuration.KEYBOARD_NOKEYS;
7091            }
7092
7093            // Let the policy update hidden states.
7094            config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
7095            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
7096            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
7097            mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
7098        }
7099
7100        return true;
7101    }
7102
7103    public boolean isHardKeyboardAvailable() {
7104        synchronized (mWindowMap) {
7105            return mHardKeyboardAvailable;
7106        }
7107    }
7108
7109    public void updateShowImeWithHardKeyboard() {
7110        boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser(
7111                mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0,
7112                mCurrentUserId) == 1;
7113        synchronized (mWindowMap) {
7114            mShowImeWithHardKeyboard = showImeWithHardKeyboard;
7115        }
7116    }
7117
7118    public void setOnHardKeyboardStatusChangeListener(
7119            OnHardKeyboardStatusChangeListener listener) {
7120        synchronized (mWindowMap) {
7121            mHardKeyboardStatusChangeListener = listener;
7122        }
7123    }
7124
7125    void notifyHardKeyboardStatusChange() {
7126        final boolean available;
7127        final OnHardKeyboardStatusChangeListener listener;
7128        synchronized (mWindowMap) {
7129            listener = mHardKeyboardStatusChangeListener;
7130            available = mHardKeyboardAvailable;
7131        }
7132        if (listener != null) {
7133            listener.onHardKeyboardStatusChange(available);
7134        }
7135    }
7136
7137    // -------------------------------------------------------------
7138    // Drag and drop
7139    // -------------------------------------------------------------
7140
7141    IBinder prepareDragSurface(IWindow window, SurfaceSession session,
7142            int flags, int width, int height, Surface outSurface) {
7143        if (DEBUG_DRAG) {
7144            Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height
7145                    + " flags=" + Integer.toHexString(flags) + " win=" + window
7146                    + " asbinder=" + window.asBinder());
7147        }
7148
7149        final int callerPid = Binder.getCallingPid();
7150        final long origId = Binder.clearCallingIdentity();
7151        IBinder token = null;
7152
7153        try {
7154            synchronized (mWindowMap) {
7155                try {
7156                    if (mDragState == null) {
7157                        // TODO(multi-display): support other displays
7158                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
7159                        final Display display = displayContent.getDisplay();
7160                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
7161                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
7162                        surface.setLayerStack(display.getLayerStack());
7163                        if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
7164                                + surface + ": CREATE");
7165                        outSurface.copyFrom(surface);
7166                        final IBinder winBinder = window.asBinder();
7167                        token = new Binder();
7168                        mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
7169                        token = mDragState.mToken = new Binder();
7170
7171                        // 5 second timeout for this window to actually begin the drag
7172                        mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
7173                        Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
7174                        mH.sendMessageDelayed(msg, 5000);
7175                    } else {
7176                        Slog.w(TAG, "Drag already in progress");
7177                    }
7178                } catch (OutOfResourcesException e) {
7179                    Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
7180                    if (mDragState != null) {
7181                        mDragState.reset();
7182                        mDragState = null;
7183                    }
7184                }
7185            }
7186        } finally {
7187            Binder.restoreCallingIdentity(origId);
7188        }
7189
7190        return token;
7191    }
7192
7193    // -------------------------------------------------------------
7194    // Input Events and Focus Management
7195    // -------------------------------------------------------------
7196
7197    final InputMonitor mInputMonitor = new InputMonitor(this);
7198    private boolean mEventDispatchingEnabled;
7199
7200    @Override
7201    public void pauseKeyDispatching(IBinder _token) {
7202        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7203                "pauseKeyDispatching()")) {
7204            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7205        }
7206
7207        synchronized (mWindowMap) {
7208            WindowToken token = mTokenMap.get(_token);
7209            if (token != null) {
7210                mInputMonitor.pauseDispatchingLw(token);
7211            }
7212        }
7213    }
7214
7215    @Override
7216    public void resumeKeyDispatching(IBinder _token) {
7217        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7218                "resumeKeyDispatching()")) {
7219            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7220        }
7221
7222        synchronized (mWindowMap) {
7223            WindowToken token = mTokenMap.get(_token);
7224            if (token != null) {
7225                mInputMonitor.resumeDispatchingLw(token);
7226            }
7227        }
7228    }
7229
7230    @Override
7231    public void setEventDispatching(boolean enabled) {
7232        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7233                "setEventDispatching()")) {
7234            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7235        }
7236
7237        synchronized (mWindowMap) {
7238            mEventDispatchingEnabled = enabled;
7239            if (mDisplayEnabled) {
7240                mInputMonitor.setEventDispatchingLw(enabled);
7241            }
7242        }
7243    }
7244
7245    private WindowState getFocusedWindow() {
7246        synchronized (mWindowMap) {
7247            return getFocusedWindowLocked();
7248        }
7249    }
7250
7251    private WindowState getFocusedWindowLocked() {
7252        return mCurrentFocus;
7253    }
7254
7255    public boolean detectSafeMode() {
7256        if (!mInputMonitor.waitForInputDevicesReady(
7257                INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
7258            Slog.w(TAG, "Devices still not ready after waiting "
7259                   + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
7260                   + " milliseconds before attempting to detect safe mode.");
7261        }
7262
7263        int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7264                KeyEvent.KEYCODE_MENU);
7265        int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
7266        int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
7267                KeyEvent.KEYCODE_DPAD_CENTER);
7268        int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
7269                InputManagerService.BTN_MOUSE);
7270        int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7271                KeyEvent.KEYCODE_VOLUME_DOWN);
7272        mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
7273                || volumeDownState > 0;
7274        try {
7275            if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
7276                mSafeMode = true;
7277                SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
7278            }
7279        } catch (IllegalArgumentException e) {
7280        }
7281        if (mSafeMode) {
7282            Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
7283                    + " dpad=" + dpadState + " trackball=" + trackballState + ")");
7284        } else {
7285            Log.i(TAG, "SAFE MODE not enabled");
7286        }
7287        mPolicy.setSafeMode(mSafeMode);
7288        return mSafeMode;
7289    }
7290
7291    public void displayReady() {
7292        displayReady(Display.DEFAULT_DISPLAY);
7293
7294        synchronized(mWindowMap) {
7295            final DisplayContent displayContent = getDefaultDisplayContentLocked();
7296            readForcedDisplaySizeAndDensityLocked(displayContent);
7297            mDisplayReady = true;
7298        }
7299
7300        try {
7301            mActivityManager.updateConfiguration(null);
7302        } catch (RemoteException e) {
7303        }
7304
7305        synchronized(mWindowMap) {
7306            mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
7307                    PackageManager.FEATURE_TOUCHSCREEN);
7308            configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
7309        }
7310
7311        try {
7312            mActivityManager.updateConfiguration(null);
7313        } catch (RemoteException e) {
7314        }
7315    }
7316
7317    private void displayReady(int displayId) {
7318        synchronized(mWindowMap) {
7319            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7320            if (displayContent != null) {
7321                mAnimator.addDisplayLocked(displayId);
7322                synchronized(displayContent.mDisplaySizeLock) {
7323                    // Bootstrap the default logical display from the display manager.
7324                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7325                    DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId);
7326                    if (newDisplayInfo != null) {
7327                        displayInfo.copyFrom(newDisplayInfo);
7328                    }
7329                    displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
7330                    displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
7331                    displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
7332                    displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
7333                    displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
7334                    displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
7335                    displayContent.mBaseDisplayRect.set(0, 0,
7336                            displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight);
7337                }
7338            }
7339        }
7340    }
7341
7342    public void systemReady() {
7343        mPolicy.systemReady();
7344    }
7345
7346    // -------------------------------------------------------------
7347    // Async Handler
7348    // -------------------------------------------------------------
7349
7350    final class H extends Handler {
7351        public static final int REPORT_FOCUS_CHANGE = 2;
7352        public static final int REPORT_LOSING_FOCUS = 3;
7353        public static final int DO_TRAVERSAL = 4;
7354        public static final int ADD_STARTING = 5;
7355        public static final int REMOVE_STARTING = 6;
7356        public static final int FINISHED_STARTING = 7;
7357        public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
7358        public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
7359        public static final int WINDOW_FREEZE_TIMEOUT = 11;
7360
7361        public static final int APP_TRANSITION_TIMEOUT = 13;
7362        public static final int PERSIST_ANIMATION_SCALE = 14;
7363        public static final int FORCE_GC = 15;
7364        public static final int ENABLE_SCREEN = 16;
7365        public static final int APP_FREEZE_TIMEOUT = 17;
7366        public static final int SEND_NEW_CONFIGURATION = 18;
7367        public static final int REPORT_WINDOWS_CHANGE = 19;
7368        public static final int DRAG_START_TIMEOUT = 20;
7369        public static final int DRAG_END_TIMEOUT = 21;
7370        public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
7371        public static final int BOOT_TIMEOUT = 23;
7372        public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
7373        public static final int SHOW_STRICT_MODE_VIOLATION = 25;
7374        public static final int DO_ANIMATION_CALLBACK = 26;
7375
7376        public static final int DO_DISPLAY_ADDED = 27;
7377        public static final int DO_DISPLAY_REMOVED = 28;
7378        public static final int DO_DISPLAY_CHANGED = 29;
7379
7380        public static final int CLIENT_FREEZE_TIMEOUT = 30;
7381        public static final int TAP_OUTSIDE_STACK = 31;
7382        public static final int NOTIFY_ACTIVITY_DRAWN = 32;
7383
7384        public static final int ALL_WINDOWS_DRAWN = 33;
7385
7386        public static final int NEW_ANIMATOR_SCALE = 34;
7387
7388        public static final int SHOW_DISPLAY_MASK = 35;
7389
7390        @Override
7391        public void handleMessage(Message msg) {
7392            if (DEBUG_WINDOW_TRACE) {
7393                Slog.v(TAG, "handleMessage: entry what=" + msg.what);
7394            }
7395            switch (msg.what) {
7396                case REPORT_FOCUS_CHANGE: {
7397                    WindowState lastFocus;
7398                    WindowState newFocus;
7399
7400                    synchronized(mWindowMap) {
7401                        lastFocus = mLastFocus;
7402                        newFocus = mCurrentFocus;
7403                        if (lastFocus == newFocus) {
7404                            // Focus is not changing, so nothing to do.
7405                            return;
7406                        }
7407                        mLastFocus = newFocus;
7408                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus +
7409                                " to " + newFocus);
7410                        if (newFocus != null && lastFocus != null
7411                                && !newFocus.isDisplayedLw()) {
7412                            //Slog.i(TAG, "Delaying loss of focus...");
7413                            mLosingFocus.add(lastFocus);
7414                            lastFocus = null;
7415                        }
7416                    }
7417
7418                    //System.out.println("Changing focus from " + lastFocus
7419                    //                   + " to " + newFocus);
7420                    if (newFocus != null) {
7421                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus);
7422                        newFocus.reportFocusChangedSerialized(true, mInTouchMode);
7423                        notifyFocusChanged();
7424                    }
7425
7426                    if (lastFocus != null) {
7427                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus);
7428                        lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
7429                    }
7430                } break;
7431
7432                case REPORT_LOSING_FOCUS: {
7433                    ArrayList<WindowState> losers;
7434
7435                    synchronized(mWindowMap) {
7436                        losers = mLosingFocus;
7437                        mLosingFocus = new ArrayList<WindowState>();
7438                    }
7439
7440                    final int N = losers.size();
7441                    for (int i=0; i<N; i++) {
7442                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " +
7443                                losers.get(i));
7444                        losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
7445                    }
7446                } break;
7447
7448                case DO_TRAVERSAL: {
7449                    synchronized(mWindowMap) {
7450                        mTraversalScheduled = false;
7451                        performLayoutAndPlaceSurfacesLocked();
7452                    }
7453                } break;
7454
7455                case ADD_STARTING: {
7456                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7457                    final StartingData sd = wtoken.startingData;
7458
7459                    if (sd == null) {
7460                        // Animation has been canceled... do nothing.
7461                        return;
7462                    }
7463
7464                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
7465                            + wtoken + ": pkg=" + sd.pkg);
7466
7467                    View view = null;
7468                    try {
7469                        view = mPolicy.addStartingWindow(
7470                            wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
7471                            sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags);
7472                    } catch (Exception e) {
7473                        Slog.w(TAG, "Exception when adding starting window", e);
7474                    }
7475
7476                    if (view != null) {
7477                        boolean abort = false;
7478
7479                        synchronized(mWindowMap) {
7480                            if (wtoken.removed || wtoken.startingData == null) {
7481                                // If the window was successfully added, then
7482                                // we need to remove it.
7483                                if (wtoken.startingWindow != null) {
7484                                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7485                                            "Aborted starting " + wtoken
7486                                            + ": removed=" + wtoken.removed
7487                                            + " startingData=" + wtoken.startingData);
7488                                    wtoken.startingWindow = null;
7489                                    wtoken.startingData = null;
7490                                    abort = true;
7491                                }
7492                            } else {
7493                                wtoken.startingView = view;
7494                            }
7495                            if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
7496                                    "Added starting " + wtoken
7497                                    + ": startingWindow="
7498                                    + wtoken.startingWindow + " startingView="
7499                                    + wtoken.startingView);
7500                        }
7501
7502                        if (abort) {
7503                            try {
7504                                mPolicy.removeStartingWindow(wtoken.token, view);
7505                            } catch (Exception e) {
7506                                Slog.w(TAG, "Exception when removing starting window", e);
7507                            }
7508                        }
7509                    }
7510                } break;
7511
7512                case REMOVE_STARTING: {
7513                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7514                    IBinder token = null;
7515                    View view = null;
7516                    synchronized (mWindowMap) {
7517                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
7518                                + wtoken + ": startingWindow="
7519                                + wtoken.startingWindow + " startingView="
7520                                + wtoken.startingView);
7521                        if (wtoken.startingWindow != null) {
7522                            view = wtoken.startingView;
7523                            token = wtoken.token;
7524                            wtoken.startingData = null;
7525                            wtoken.startingView = null;
7526                            wtoken.startingWindow = null;
7527                            wtoken.startingDisplayed = false;
7528                        }
7529                    }
7530                    if (view != null) {
7531                        try {
7532                            mPolicy.removeStartingWindow(token, view);
7533                        } catch (Exception e) {
7534                            Slog.w(TAG, "Exception when removing starting window", e);
7535                        }
7536                    }
7537                } break;
7538
7539                case FINISHED_STARTING: {
7540                    IBinder token = null;
7541                    View view = null;
7542                    while (true) {
7543                        synchronized (mWindowMap) {
7544                            final int N = mFinishedStarting.size();
7545                            if (N <= 0) {
7546                                break;
7547                            }
7548                            AppWindowToken wtoken = mFinishedStarting.remove(N-1);
7549
7550                            if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7551                                    "Finished starting " + wtoken
7552                                    + ": startingWindow=" + wtoken.startingWindow
7553                                    + " startingView=" + wtoken.startingView);
7554
7555                            if (wtoken.startingWindow == null) {
7556                                continue;
7557                            }
7558
7559                            view = wtoken.startingView;
7560                            token = wtoken.token;
7561                            wtoken.startingData = null;
7562                            wtoken.startingView = null;
7563                            wtoken.startingWindow = null;
7564                            wtoken.startingDisplayed = false;
7565                        }
7566
7567                        try {
7568                            mPolicy.removeStartingWindow(token, view);
7569                        } catch (Exception e) {
7570                            Slog.w(TAG, "Exception when removing starting window", e);
7571                        }
7572                    }
7573                } break;
7574
7575                case REPORT_APPLICATION_TOKEN_DRAWN: {
7576                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7577
7578                    try {
7579                        if (DEBUG_VISIBILITY) Slog.v(
7580                                TAG, "Reporting drawn in " + wtoken);
7581                        wtoken.appToken.windowsDrawn();
7582                    } catch (RemoteException ex) {
7583                    }
7584                } break;
7585
7586                case REPORT_APPLICATION_TOKEN_WINDOWS: {
7587                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7588
7589                    boolean nowVisible = msg.arg1 != 0;
7590                    boolean nowGone = msg.arg2 != 0;
7591
7592                    try {
7593                        if (DEBUG_VISIBILITY) Slog.v(
7594                                TAG, "Reporting visible in " + wtoken
7595                                + " visible=" + nowVisible
7596                                + " gone=" + nowGone);
7597                        if (nowVisible) {
7598                            wtoken.appToken.windowsVisible();
7599                        } else {
7600                            wtoken.appToken.windowsGone();
7601                        }
7602                    } catch (RemoteException ex) {
7603                    }
7604                } break;
7605
7606                case WINDOW_FREEZE_TIMEOUT: {
7607                    // TODO(multidisplay): Can non-default displays rotate?
7608                    synchronized (mWindowMap) {
7609                        Slog.w(TAG, "Window freeze timeout expired.");
7610                        final WindowList windows = getDefaultWindowListLocked();
7611                        int i = windows.size();
7612                        while (i > 0) {
7613                            i--;
7614                            WindowState w = windows.get(i);
7615                            if (w.mOrientationChanging) {
7616                                w.mOrientationChanging = false;
7617                                w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
7618                                        - mDisplayFreezeTime);
7619                                Slog.w(TAG, "Force clearing orientation change: " + w);
7620                            }
7621                        }
7622                        performLayoutAndPlaceSurfacesLocked();
7623                    }
7624                    break;
7625                }
7626
7627                case APP_TRANSITION_TIMEOUT: {
7628                    synchronized (mWindowMap) {
7629                        if (mAppTransition.isTransitionSet()) {
7630                            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
7631                            mAppTransition.setTimeout();
7632                            performLayoutAndPlaceSurfacesLocked();
7633                        }
7634                    }
7635                    break;
7636                }
7637
7638                case PERSIST_ANIMATION_SCALE: {
7639                    Settings.Global.putFloat(mContext.getContentResolver(),
7640                            Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
7641                    Settings.Global.putFloat(mContext.getContentResolver(),
7642                            Settings.Global.TRANSITION_ANIMATION_SCALE,
7643                            mTransitionAnimationScaleSetting);
7644                    Settings.Global.putFloat(mContext.getContentResolver(),
7645                            Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting);
7646                    break;
7647                }
7648
7649                case FORCE_GC: {
7650                    synchronized (mWindowMap) {
7651                        // Since we're holding both mWindowMap and mAnimator we don't need to
7652                        // hold mAnimator.mLayoutToAnim.
7653                        if (mAnimator.mAnimating || mAnimationScheduled) {
7654                            // If we are animating, don't do the gc now but
7655                            // delay a bit so we don't interrupt the animation.
7656                            sendEmptyMessageDelayed(H.FORCE_GC, 2000);
7657                            return;
7658                        }
7659                        // If we are currently rotating the display, it will
7660                        // schedule a new message when done.
7661                        if (mDisplayFrozen) {
7662                            return;
7663                        }
7664                    }
7665                    Runtime.getRuntime().gc();
7666                    break;
7667                }
7668
7669                case ENABLE_SCREEN: {
7670                    performEnableScreen();
7671                    break;
7672                }
7673
7674                case APP_FREEZE_TIMEOUT: {
7675                    synchronized (mWindowMap) {
7676                        Slog.w(TAG, "App freeze timeout expired.");
7677                        final int numStacks = mStackIdToStack.size();
7678                        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
7679                            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
7680                            final ArrayList<Task> tasks = stack.getTasks();
7681                            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
7682                                AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
7683                                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
7684                                    AppWindowToken tok = tokens.get(tokenNdx);
7685                                    if (tok.mAppAnimator.freezingScreen) {
7686                                        Slog.w(TAG, "Force clearing freeze: " + tok);
7687                                        unsetAppFreezingScreenLocked(tok, true, true);
7688                                    }
7689                                }
7690                            }
7691                        }
7692                    }
7693                    break;
7694                }
7695
7696                case CLIENT_FREEZE_TIMEOUT: {
7697                    synchronized (mWindowMap) {
7698                        if (mClientFreezingScreen) {
7699                            mClientFreezingScreen = false;
7700                            mLastFinishedFreezeSource = "client-timeout";
7701                            stopFreezingDisplayLocked();
7702                        }
7703                    }
7704                    break;
7705                }
7706
7707                case SEND_NEW_CONFIGURATION: {
7708                    removeMessages(SEND_NEW_CONFIGURATION);
7709                    sendNewConfiguration();
7710                    break;
7711                }
7712
7713                case REPORT_WINDOWS_CHANGE: {
7714                    if (mWindowsChanged) {
7715                        synchronized (mWindowMap) {
7716                            mWindowsChanged = false;
7717                        }
7718                        notifyWindowsChanged();
7719                    }
7720                    break;
7721                }
7722
7723                case DRAG_START_TIMEOUT: {
7724                    IBinder win = (IBinder)msg.obj;
7725                    if (DEBUG_DRAG) {
7726                        Slog.w(TAG, "Timeout starting drag by win " + win);
7727                    }
7728                    synchronized (mWindowMap) {
7729                        // !!! TODO: ANR the app that has failed to start the drag in time
7730                        if (mDragState != null) {
7731                            mDragState.unregister();
7732                            mInputMonitor.updateInputWindowsLw(true /*force*/);
7733                            mDragState.reset();
7734                            mDragState = null;
7735                        }
7736                    }
7737                    break;
7738                }
7739
7740                case DRAG_END_TIMEOUT: {
7741                    IBinder win = (IBinder)msg.obj;
7742                    if (DEBUG_DRAG) {
7743                        Slog.w(TAG, "Timeout ending drag to win " + win);
7744                    }
7745                    synchronized (mWindowMap) {
7746                        // !!! TODO: ANR the drag-receiving app
7747                        if (mDragState != null) {
7748                            mDragState.mDragResult = false;
7749                            mDragState.endDragLw();
7750                        }
7751                    }
7752                    break;
7753                }
7754
7755                case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
7756                    notifyHardKeyboardStatusChange();
7757                    break;
7758                }
7759
7760                case BOOT_TIMEOUT: {
7761                    performBootTimeout();
7762                    break;
7763                }
7764
7765                case WAITING_FOR_DRAWN_TIMEOUT: {
7766                    Runnable callback = null;
7767                    synchronized (mWindowMap) {
7768                        Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
7769                        mWaitingForDrawn.clear();
7770                        callback = mWaitingForDrawnCallback;
7771                        mWaitingForDrawnCallback = null;
7772                    }
7773                    if (callback != null) {
7774                        callback.run();
7775                    }
7776                    break;
7777                }
7778
7779                case SHOW_STRICT_MODE_VIOLATION: {
7780                    showStrictModeViolation(msg.arg1, msg.arg2);
7781                    break;
7782                }
7783
7784                case SHOW_DISPLAY_MASK: {
7785                    showCircularMask();
7786                    break;
7787                }
7788
7789                case DO_ANIMATION_CALLBACK: {
7790                    try {
7791                        ((IRemoteCallback)msg.obj).sendResult(null);
7792                    } catch (RemoteException e) {
7793                    }
7794                    break;
7795                }
7796
7797                case DO_DISPLAY_ADDED:
7798                    handleDisplayAdded(msg.arg1);
7799                    break;
7800
7801                case DO_DISPLAY_REMOVED:
7802                    synchronized (mWindowMap) {
7803                        handleDisplayRemovedLocked(msg.arg1);
7804                    }
7805                    break;
7806
7807                case DO_DISPLAY_CHANGED:
7808                    synchronized (mWindowMap) {
7809                        handleDisplayChangedLocked(msg.arg1);
7810                    }
7811                    break;
7812
7813                case TAP_OUTSIDE_STACK: {
7814                    int stackId;
7815                    synchronized (mWindowMap) {
7816                        stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
7817                    }
7818                    if (stackId >= 0) {
7819                        try {
7820                            mActivityManager.setFocusedStack(stackId);
7821                        } catch (RemoteException e) {
7822                        }
7823                    }
7824                }
7825                break;
7826                case NOTIFY_ACTIVITY_DRAWN:
7827                    try {
7828                        mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
7829                    } catch (RemoteException e) {
7830                    }
7831                    break;
7832                case ALL_WINDOWS_DRAWN: {
7833                    Runnable callback;
7834                    synchronized (mWindowMap) {
7835                        callback = mWaitingForDrawnCallback;
7836                        mWaitingForDrawnCallback = null;
7837                    }
7838                    if (callback != null) {
7839                        callback.run();
7840                    }
7841                }
7842                case NEW_ANIMATOR_SCALE: {
7843                    float scale = getCurrentAnimatorScale();
7844                    ValueAnimator.setDurationScale(scale);
7845                    Session session = (Session)msg.obj;
7846                    if (session != null) {
7847                        try {
7848                            session.mCallback.onAnimatorScaleChanged(scale);
7849                        } catch (RemoteException e) {
7850                        }
7851                    } else {
7852                        ArrayList<IWindowSessionCallback> callbacks
7853                                = new ArrayList<IWindowSessionCallback>();
7854                        synchronized (mWindowMap) {
7855                            for (int i=0; i<mSessions.size(); i++) {
7856                                callbacks.add(mSessions.valueAt(i).mCallback);
7857                            }
7858
7859                        }
7860                        for (int i=0; i<callbacks.size(); i++) {
7861                            try {
7862                                callbacks.get(i).onAnimatorScaleChanged(scale);
7863                            } catch (RemoteException e) {
7864                            }
7865                        }
7866                    }
7867                }
7868                break;
7869            }
7870            if (DEBUG_WINDOW_TRACE) {
7871                Slog.v(TAG, "handleMessage: exit");
7872            }
7873        }
7874    }
7875
7876    // -------------------------------------------------------------
7877    // IWindowManager API
7878    // -------------------------------------------------------------
7879
7880    @Override
7881    public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
7882            IInputContext inputContext) {
7883        if (client == null) throw new IllegalArgumentException("null client");
7884        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
7885        Session session = new Session(this, callback, client, inputContext);
7886        return session;
7887    }
7888
7889    @Override
7890    public boolean inputMethodClientHasFocus(IInputMethodClient client) {
7891        synchronized (mWindowMap) {
7892            // The focus for the client is the window immediately below
7893            // where we would place the input method window.
7894            int idx = findDesiredInputMethodWindowIndexLocked(false);
7895            if (idx > 0) {
7896                // TODO(multidisplay): IMEs are only supported on the default display.
7897                WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
7898                if (DEBUG_INPUT_METHOD) {
7899                    Slog.i(TAG, "Desired input method target: " + imFocus);
7900                    Slog.i(TAG, "Current focus: " + mCurrentFocus);
7901                    Slog.i(TAG, "Last focus: " + mLastFocus);
7902                }
7903                if (imFocus != null) {
7904                    // This may be a starting window, in which case we still want
7905                    // to count it as okay.
7906                    if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
7907                            && imFocus.mAppToken != null) {
7908                        // The client has definitely started, so it really should
7909                        // have a window in this app token.  Let's look for it.
7910                        for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
7911                            WindowState w = imFocus.mAppToken.windows.get(i);
7912                            if (w != imFocus) {
7913                                Log.i(TAG, "Switching to real app window: " + w);
7914                                imFocus = w;
7915                                break;
7916                            }
7917                        }
7918                    }
7919                    if (DEBUG_INPUT_METHOD) {
7920                        Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient);
7921                        if (imFocus.mSession.mClient != null) {
7922                            Slog.i(TAG, "IM target client binder: "
7923                                    + imFocus.mSession.mClient.asBinder());
7924                            Slog.i(TAG, "Requesting client binder: " + client.asBinder());
7925                        }
7926                    }
7927                    if (imFocus.mSession.mClient != null &&
7928                            imFocus.mSession.mClient.asBinder() == client.asBinder()) {
7929                        return true;
7930                    }
7931                }
7932            }
7933
7934            // Okay, how about this...  what is the current focus?
7935            // It seems in some cases we may not have moved the IM
7936            // target window, such as when it was in a pop-up window,
7937            // so let's also look at the current focus.  (An example:
7938            // go to Gmail, start searching so the keyboard goes up,
7939            // press home.  Sometimes the IME won't go down.)
7940            // Would be nice to fix this more correctly, but it's
7941            // way at the end of a release, and this should be good enough.
7942            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
7943                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
7944                return true;
7945            }
7946        }
7947        return false;
7948    }
7949
7950    @Override
7951    public void getInitialDisplaySize(int displayId, Point size) {
7952        synchronized (mWindowMap) {
7953            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7954            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7955                synchronized(displayContent.mDisplaySizeLock) {
7956                    size.x = displayContent.mInitialDisplayWidth;
7957                    size.y = displayContent.mInitialDisplayHeight;
7958                }
7959            }
7960        }
7961    }
7962
7963    @Override
7964    public void getBaseDisplaySize(int displayId, Point size) {
7965        synchronized (mWindowMap) {
7966            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7967            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7968                synchronized(displayContent.mDisplaySizeLock) {
7969                    size.x = displayContent.mBaseDisplayWidth;
7970                    size.y = displayContent.mBaseDisplayHeight;
7971                }
7972            }
7973        }
7974    }
7975
7976    @Override
7977    public void setForcedDisplaySize(int displayId, int width, int height) {
7978        if (mContext.checkCallingOrSelfPermission(
7979                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7980                PackageManager.PERMISSION_GRANTED) {
7981            throw new SecurityException("Must hold permission " +
7982                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7983        }
7984        if (displayId != Display.DEFAULT_DISPLAY) {
7985            throw new IllegalArgumentException("Can only set the default display");
7986        }
7987        final long ident = Binder.clearCallingIdentity();
7988        try {
7989            synchronized(mWindowMap) {
7990                // Set some sort of reasonable bounds on the size of the display that we
7991                // will try to emulate.
7992                final int MIN_WIDTH = 200;
7993                final int MIN_HEIGHT = 200;
7994                final int MAX_SCALE = 2;
7995                final DisplayContent displayContent = getDisplayContentLocked(displayId);
7996                if (displayContent != null) {
7997                    width = Math.min(Math.max(width, MIN_WIDTH),
7998                            displayContent.mInitialDisplayWidth * MAX_SCALE);
7999                    height = Math.min(Math.max(height, MIN_HEIGHT),
8000                            displayContent.mInitialDisplayHeight * MAX_SCALE);
8001                    setForcedDisplaySizeLocked(displayContent, width, height);
8002                    Settings.Global.putString(mContext.getContentResolver(),
8003                            Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
8004                }
8005            }
8006        } finally {
8007            Binder.restoreCallingIdentity(ident);
8008        }
8009    }
8010
8011    private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
8012        String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
8013                Settings.Global.DISPLAY_SIZE_FORCED);
8014        if (sizeStr == null || sizeStr.length() == 0) {
8015            sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
8016        }
8017        if (sizeStr != null && sizeStr.length() > 0) {
8018            final int pos = sizeStr.indexOf(',');
8019            if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
8020                int width, height;
8021                try {
8022                    width = Integer.parseInt(sizeStr.substring(0, pos));
8023                    height = Integer.parseInt(sizeStr.substring(pos+1));
8024                    synchronized(displayContent.mDisplaySizeLock) {
8025                        if (displayContent.mBaseDisplayWidth != width
8026                                || displayContent.mBaseDisplayHeight != height) {
8027                            Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
8028                            displayContent.mBaseDisplayWidth = width;
8029                            displayContent.mBaseDisplayHeight = height;
8030                        }
8031                    }
8032                } catch (NumberFormatException ex) {
8033                }
8034            }
8035        }
8036        String densityStr = Settings.Global.getString(mContext.getContentResolver(),
8037                Settings.Global.DISPLAY_DENSITY_FORCED);
8038        if (densityStr == null || densityStr.length() == 0) {
8039            densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
8040        }
8041        if (densityStr != null && densityStr.length() > 0) {
8042            int density;
8043            try {
8044                density = Integer.parseInt(densityStr);
8045                synchronized(displayContent.mDisplaySizeLock) {
8046                    if (displayContent.mBaseDisplayDensity != density) {
8047                        Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
8048                        displayContent.mBaseDisplayDensity = density;
8049                    }
8050                }
8051            } catch (NumberFormatException ex) {
8052            }
8053        }
8054    }
8055
8056    // displayContent must not be null
8057    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
8058        Slog.i(TAG, "Using new display size: " + width + "x" + height);
8059
8060        synchronized(displayContent.mDisplaySizeLock) {
8061            displayContent.mBaseDisplayWidth = width;
8062            displayContent.mBaseDisplayHeight = height;
8063        }
8064        reconfigureDisplayLocked(displayContent);
8065    }
8066
8067    @Override
8068    public void clearForcedDisplaySize(int displayId) {
8069        if (mContext.checkCallingOrSelfPermission(
8070                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8071                PackageManager.PERMISSION_GRANTED) {
8072            throw new SecurityException("Must hold permission " +
8073                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8074        }
8075        if (displayId != Display.DEFAULT_DISPLAY) {
8076            throw new IllegalArgumentException("Can only set the default display");
8077        }
8078        final long ident = Binder.clearCallingIdentity();
8079        try {
8080            synchronized(mWindowMap) {
8081                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8082                if (displayContent != null) {
8083                    setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
8084                            displayContent.mInitialDisplayHeight);
8085                    Settings.Global.putString(mContext.getContentResolver(),
8086                            Settings.Global.DISPLAY_SIZE_FORCED, "");
8087                }
8088            }
8089        } finally {
8090            Binder.restoreCallingIdentity(ident);
8091        }
8092    }
8093
8094    @Override
8095    public int getInitialDisplayDensity(int displayId) {
8096        synchronized (mWindowMap) {
8097            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8098            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8099                synchronized(displayContent.mDisplaySizeLock) {
8100                    return displayContent.mInitialDisplayDensity;
8101                }
8102            }
8103        }
8104        return -1;
8105    }
8106
8107    @Override
8108    public int getBaseDisplayDensity(int displayId) {
8109        synchronized (mWindowMap) {
8110            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8111            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8112                synchronized(displayContent.mDisplaySizeLock) {
8113                    return displayContent.mBaseDisplayDensity;
8114                }
8115            }
8116        }
8117        return -1;
8118    }
8119
8120    @Override
8121    public void setForcedDisplayDensity(int displayId, int density) {
8122        if (mContext.checkCallingOrSelfPermission(
8123                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8124                PackageManager.PERMISSION_GRANTED) {
8125            throw new SecurityException("Must hold permission " +
8126                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8127        }
8128        if (displayId != Display.DEFAULT_DISPLAY) {
8129            throw new IllegalArgumentException("Can only set the default display");
8130        }
8131        final long ident = Binder.clearCallingIdentity();
8132        try {
8133            synchronized(mWindowMap) {
8134                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8135                if (displayContent != null) {
8136                    setForcedDisplayDensityLocked(displayContent, density);
8137                    Settings.Global.putString(mContext.getContentResolver(),
8138                            Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
8139                }
8140            }
8141        } finally {
8142            Binder.restoreCallingIdentity(ident);
8143        }
8144    }
8145
8146    // displayContent must not be null
8147    private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
8148        Slog.i(TAG, "Using new display density: " + density);
8149
8150        synchronized(displayContent.mDisplaySizeLock) {
8151            displayContent.mBaseDisplayDensity = density;
8152        }
8153        reconfigureDisplayLocked(displayContent);
8154    }
8155
8156    @Override
8157    public void clearForcedDisplayDensity(int displayId) {
8158        if (mContext.checkCallingOrSelfPermission(
8159                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8160                PackageManager.PERMISSION_GRANTED) {
8161            throw new SecurityException("Must hold permission " +
8162                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8163        }
8164        if (displayId != Display.DEFAULT_DISPLAY) {
8165            throw new IllegalArgumentException("Can only set the default display");
8166        }
8167        final long ident = Binder.clearCallingIdentity();
8168        try {
8169            synchronized(mWindowMap) {
8170                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8171                if (displayContent != null) {
8172                    setForcedDisplayDensityLocked(displayContent,
8173                            displayContent.mInitialDisplayDensity);
8174                    Settings.Global.putString(mContext.getContentResolver(),
8175                            Settings.Global.DISPLAY_DENSITY_FORCED, "");
8176                }
8177            }
8178        } finally {
8179            Binder.restoreCallingIdentity(ident);
8180        }
8181    }
8182
8183    // displayContent must not be null
8184    private void reconfigureDisplayLocked(DisplayContent displayContent) {
8185        // TODO: Multidisplay: for now only use with default display.
8186        configureDisplayPolicyLocked(displayContent);
8187        displayContent.layoutNeeded = true;
8188
8189        boolean configChanged = updateOrientationFromAppTokensLocked(false);
8190        mTempConfiguration.setToDefaults();
8191        mTempConfiguration.fontScale = mCurConfiguration.fontScale;
8192        if (computeScreenConfigurationLocked(mTempConfiguration)) {
8193            if (mCurConfiguration.diff(mTempConfiguration) != 0) {
8194                configChanged = true;
8195            }
8196        }
8197
8198        if (configChanged) {
8199            mWaitingForConfig = true;
8200            startFreezingDisplayLocked(false, 0, 0);
8201            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
8202        }
8203
8204        performLayoutAndPlaceSurfacesLocked();
8205    }
8206
8207    private void configureDisplayPolicyLocked(DisplayContent displayContent) {
8208        mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
8209                displayContent.mBaseDisplayWidth,
8210                displayContent.mBaseDisplayHeight,
8211                displayContent.mBaseDisplayDensity);
8212
8213        DisplayInfo displayInfo = displayContent.getDisplayInfo();
8214        mPolicy.setDisplayOverscan(displayContent.getDisplay(),
8215                displayInfo.overscanLeft, displayInfo.overscanTop,
8216                displayInfo.overscanRight, displayInfo.overscanBottom);
8217    }
8218
8219    @Override
8220    public void setOverscan(int displayId, int left, int top, int right, int bottom) {
8221        if (mContext.checkCallingOrSelfPermission(
8222                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8223                PackageManager.PERMISSION_GRANTED) {
8224            throw new SecurityException("Must hold permission " +
8225                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8226        }
8227        final long ident = Binder.clearCallingIdentity();
8228        try {
8229            synchronized(mWindowMap) {
8230                DisplayContent displayContent = getDisplayContentLocked(displayId);
8231                if (displayContent != null) {
8232                    setOverscanLocked(displayContent, left, top, right, bottom);
8233                }
8234            }
8235        } finally {
8236            Binder.restoreCallingIdentity(ident);
8237        }
8238    }
8239
8240    private void setOverscanLocked(DisplayContent displayContent,
8241            int left, int top, int right, int bottom) {
8242        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
8243        synchronized (displayContent.mDisplaySizeLock) {
8244            displayInfo.overscanLeft = left;
8245            displayInfo.overscanTop = top;
8246            displayInfo.overscanRight = right;
8247            displayInfo.overscanBottom = bottom;
8248        }
8249
8250        mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom);
8251        mDisplaySettings.writeSettingsLocked();
8252
8253        reconfigureDisplayLocked(displayContent);
8254    }
8255
8256    // -------------------------------------------------------------
8257    // Internals
8258    // -------------------------------------------------------------
8259
8260    final WindowState windowForClientLocked(Session session, IWindow client,
8261            boolean throwOnError) {
8262        return windowForClientLocked(session, client.asBinder(), throwOnError);
8263    }
8264
8265    final WindowState windowForClientLocked(Session session, IBinder client,
8266            boolean throwOnError) {
8267        WindowState win = mWindowMap.get(client);
8268        if (localLOGV) Slog.v(
8269            TAG, "Looking up client " + client + ": " + win);
8270        if (win == null) {
8271            RuntimeException ex = new IllegalArgumentException(
8272                    "Requested window " + client + " does not exist");
8273            if (throwOnError) {
8274                throw ex;
8275            }
8276            Slog.w(TAG, "Failed looking up window", ex);
8277            return null;
8278        }
8279        if (session != null && win.mSession != session) {
8280            RuntimeException ex = new IllegalArgumentException(
8281                    "Requested window " + client + " is in session " +
8282                    win.mSession + ", not " + session);
8283            if (throwOnError) {
8284                throw ex;
8285            }
8286            Slog.w(TAG, "Failed looking up window", ex);
8287            return null;
8288        }
8289
8290        return win;
8291    }
8292
8293    final void rebuildAppWindowListLocked() {
8294        rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
8295    }
8296
8297    private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
8298        final WindowList windows = displayContent.getWindowList();
8299        int NW = windows.size();
8300        int i;
8301        int lastBelow = -1;
8302        int numRemoved = 0;
8303
8304        if (mRebuildTmp.length < NW) {
8305            mRebuildTmp = new WindowState[NW+10];
8306        }
8307
8308        // First remove all existing app windows.
8309        i=0;
8310        while (i < NW) {
8311            WindowState w = windows.get(i);
8312            if (w.mAppToken != null) {
8313                WindowState win = windows.remove(i);
8314                win.mRebuilding = true;
8315                mRebuildTmp[numRemoved] = win;
8316                mWindowsChanged = true;
8317                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win);
8318                NW--;
8319                numRemoved++;
8320                continue;
8321            } else if (lastBelow == i-1) {
8322                if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8323                    lastBelow = i;
8324                }
8325            }
8326            i++;
8327        }
8328
8329        // Keep whatever windows were below the app windows still below,
8330        // by skipping them.
8331        lastBelow++;
8332        i = lastBelow;
8333
8334        // First add all of the exiting app tokens...  these are no longer
8335        // in the main app list, but still have windows shown.  We put them
8336        // in the back because now that the animation is over we no longer
8337        // will care about them.
8338        final ArrayList<TaskStack> stacks = displayContent.getStacks();
8339        final int numStacks = stacks.size();
8340        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8341            AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens;
8342            int NT = exitingAppTokens.size();
8343            for (int j = 0; j < NT; j++) {
8344                i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
8345            }
8346        }
8347
8348        // And add in the still active app tokens in Z order.
8349        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8350            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
8351            final int numTasks = tasks.size();
8352            for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
8353                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8354                final int numTokens = tokens.size();
8355                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
8356                    final AppWindowToken wtoken = tokens.get(tokenNdx);
8357                    if (wtoken.mDeferRemoval) {
8358                        continue;
8359                    }
8360                    i = reAddAppWindowsLocked(displayContent, i, wtoken);
8361                }
8362            }
8363        }
8364
8365        i -= lastBelow;
8366        if (i != numRemoved) {
8367            Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " +
8368                    numRemoved + " windows but added " + i,
8369                    new RuntimeException("here").fillInStackTrace());
8370            for (i=0; i<numRemoved; i++) {
8371                WindowState ws = mRebuildTmp[i];
8372                if (ws.mRebuilding) {
8373                    StringWriter sw = new StringWriter();
8374                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
8375                    ws.dump(pw, "", true);
8376                    pw.flush();
8377                    Slog.w(TAG, "This window was lost: " + ws);
8378                    Slog.w(TAG, sw.toString());
8379                    ws.mWinAnimator.destroySurfaceLocked();
8380                }
8381            }
8382            Slog.w(TAG, "Current app token list:");
8383            dumpAppTokensLocked();
8384            Slog.w(TAG, "Final window list:");
8385            dumpWindowsLocked();
8386        }
8387    }
8388
8389    private final void assignLayersLocked(WindowList windows) {
8390        int N = windows.size();
8391        int curBaseLayer = 0;
8392        int curLayer = 0;
8393        int i;
8394
8395        if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows,
8396                new RuntimeException("here").fillInStackTrace());
8397
8398        boolean anyLayerChanged = false;
8399
8400        for (i=0; i<N; i++) {
8401            final WindowState w = windows.get(i);
8402            final WindowStateAnimator winAnimator = w.mWinAnimator;
8403            boolean layerChanged = false;
8404            int oldLayer = w.mLayer;
8405            if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
8406                    || (i > 0 && w.mIsWallpaper)) {
8407                curLayer += WINDOW_LAYER_MULTIPLIER;
8408                w.mLayer = curLayer;
8409            } else {
8410                curBaseLayer = curLayer = w.mBaseLayer;
8411                w.mLayer = curLayer;
8412            }
8413            if (w.mLayer != oldLayer) {
8414                layerChanged = true;
8415                anyLayerChanged = true;
8416            }
8417            final AppWindowToken wtoken = w.mAppToken;
8418            oldLayer = winAnimator.mAnimLayer;
8419            if (w.mTargetAppToken != null) {
8420                winAnimator.mAnimLayer =
8421                        w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
8422            } else if (wtoken != null) {
8423                winAnimator.mAnimLayer =
8424                        w.mLayer + wtoken.mAppAnimator.animLayerAdjustment;
8425            } else {
8426                winAnimator.mAnimLayer = w.mLayer;
8427            }
8428            if (w.mIsImWindow) {
8429                winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
8430            } else if (w.mIsWallpaper) {
8431                winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
8432            }
8433            if (winAnimator.mAnimLayer != oldLayer) {
8434                layerChanged = true;
8435                anyLayerChanged = true;
8436            }
8437            if (layerChanged && w.getStack().isDimming(winAnimator)) {
8438                // Force an animation pass just to update the mDimLayer layer.
8439                scheduleAnimationLocked();
8440            }
8441            if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
8442                    + "mBase=" + w.mBaseLayer
8443                    + " mLayer=" + w.mLayer
8444                    + (wtoken == null ?
8445                            "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment)
8446                    + " =mAnimLayer=" + winAnimator.mAnimLayer);
8447            //System.out.println(
8448            //    "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
8449        }
8450
8451        //TODO (multidisplay): Magnification is supported only for the default display.
8452        if (mAccessibilityController != null && anyLayerChanged
8453                && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
8454            mAccessibilityController.onWindowLayersChangedLocked();
8455        }
8456    }
8457
8458    private final void performLayoutAndPlaceSurfacesLocked() {
8459        int loopCount = 6;
8460        do {
8461            mTraversalScheduled = false;
8462            performLayoutAndPlaceSurfacesLockedLoop();
8463            mH.removeMessages(H.DO_TRAVERSAL);
8464            loopCount--;
8465        } while (mTraversalScheduled && loopCount > 0);
8466        mInnerFields.mWallpaperActionPending = false;
8467    }
8468
8469    private boolean mInLayout = false;
8470    private final void performLayoutAndPlaceSurfacesLockedLoop() {
8471        if (mInLayout) {
8472            if (DEBUG) {
8473                throw new RuntimeException("Recursive call!");
8474            }
8475            Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
8476                    + Debug.getCallers(3));
8477            return;
8478        }
8479
8480        if (mWaitingForConfig) {
8481            // Our configuration has changed (most likely rotation), but we
8482            // don't yet have the complete configuration to report to
8483            // applications.  Don't do any window layout until we have it.
8484            return;
8485        }
8486
8487        if (!mDisplayReady) {
8488            // Not yet initialized, nothing to do.
8489            return;
8490        }
8491
8492        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
8493        mInLayout = true;
8494        boolean recoveringMemory = false;
8495
8496        try {
8497            if (mForceRemoves != null) {
8498                recoveringMemory = true;
8499                // Wait a little bit for things to settle down, and off we go.
8500                for (int i=0; i<mForceRemoves.size(); i++) {
8501                    WindowState ws = mForceRemoves.get(i);
8502                    Slog.i(TAG, "Force removing: " + ws);
8503                    removeWindowInnerLocked(ws.mSession, ws);
8504                }
8505                mForceRemoves = null;
8506                Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
8507                Object tmp = new Object();
8508                synchronized (tmp) {
8509                    try {
8510                        tmp.wait(250);
8511                    } catch (InterruptedException e) {
8512                    }
8513                }
8514            }
8515        } catch (RuntimeException e) {
8516            Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
8517        }
8518
8519        try {
8520            performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
8521
8522            mInLayout = false;
8523
8524            if (needsLayout()) {
8525                if (++mLayoutRepeatCount < 6) {
8526                    requestTraversalLocked();
8527                } else {
8528                    Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
8529                    mLayoutRepeatCount = 0;
8530                }
8531            } else {
8532                mLayoutRepeatCount = 0;
8533            }
8534
8535            if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
8536                mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
8537                mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE);
8538            }
8539        } catch (RuntimeException e) {
8540            mInLayout = false;
8541            Log.wtf(TAG, "Unhandled exception while laying out windows", e);
8542        }
8543
8544        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
8545    }
8546
8547    private final void performLayoutLockedInner(final DisplayContent displayContent,
8548                                    boolean initial, boolean updateInputWindows) {
8549        if (!displayContent.layoutNeeded) {
8550            return;
8551        }
8552        displayContent.layoutNeeded = false;
8553        WindowList windows = displayContent.getWindowList();
8554        boolean isDefaultDisplay = displayContent.isDefaultDisplay;
8555
8556        DisplayInfo displayInfo = displayContent.getDisplayInfo();
8557        final int dw = displayInfo.logicalWidth;
8558        final int dh = displayInfo.logicalHeight;
8559
8560        final int NFW = mFakeWindows.size();
8561        for (int i=0; i<NFW; i++) {
8562            mFakeWindows.get(i).layout(dw, dh);
8563        }
8564
8565        final int N = windows.size();
8566        int i;
8567
8568        if (DEBUG_LAYOUT) {
8569            Slog.v(TAG, "-------------------------------------");
8570            Slog.v(TAG, "performLayout: needed="
8571                    + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
8572        }
8573
8574        WindowStateAnimator universeBackground = null;
8575
8576        mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
8577        if (isDefaultDisplay) {
8578            // Not needed on non-default displays.
8579            mSystemDecorLayer = mPolicy.getSystemDecorLayerLw();
8580            mScreenRect.set(0, 0, dw, dh);
8581        }
8582
8583        mPolicy.getContentRectLw(mTmpContentRect);
8584        displayContent.resize(mTmpContentRect);
8585
8586        int seq = mLayoutSeq+1;
8587        if (seq < 0) seq = 0;
8588        mLayoutSeq = seq;
8589
8590        boolean behindDream = false;
8591
8592        // First perform layout of any root windows (not attached
8593        // to another window).
8594        int topAttached = -1;
8595        for (i = N-1; i >= 0; i--) {
8596            final WindowState win = windows.get(i);
8597
8598            // Don't do layout of a window if it is not visible, or
8599            // soon won't be visible, to avoid wasting time and funky
8600            // changes while a window is animating away.
8601            final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
8602                    || win.isGoneForLayoutLw();
8603
8604            if (DEBUG_LAYOUT && !win.mLayoutAttached) {
8605                Slog.v(TAG, "1ST PASS " + win
8606                        + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
8607                        + " mLayoutAttached=" + win.mLayoutAttached
8608                        + " screen changed=" + win.isConfigChanged());
8609                final AppWindowToken atoken = win.mAppToken;
8610                if (gone) Slog.v(TAG, "  GONE: mViewVisibility="
8611                        + win.mViewVisibility + " mRelayoutCalled="
8612                        + win.mRelayoutCalled + " hidden="
8613                        + win.mRootToken.hidden + " hiddenRequested="
8614                        + (atoken != null && atoken.hiddenRequested)
8615                        + " mAttachedHidden=" + win.mAttachedHidden);
8616                else Slog.v(TAG, "  VIS: mViewVisibility="
8617                        + win.mViewVisibility + " mRelayoutCalled="
8618                        + win.mRelayoutCalled + " hidden="
8619                        + win.mRootToken.hidden + " hiddenRequested="
8620                        + (atoken != null && atoken.hiddenRequested)
8621                        + " mAttachedHidden=" + win.mAttachedHidden);
8622            }
8623
8624            // If this view is GONE, then skip it -- keep the current
8625            // frame, and let the caller know so they can ignore it
8626            // if they want.  (We do the normal layout for INVISIBLE
8627            // windows, since that means "perform layout as normal,
8628            // just don't display").
8629            if (!gone || !win.mHaveFrame || win.mLayoutNeeded
8630                    || ((win.isConfigChanged() || win.setInsetsChanged()) &&
8631                            ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
8632                            win.mAppToken != null && win.mAppToken.layoutConfigChanges))
8633                    || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8634                if (!win.mLayoutAttached) {
8635                    if (initial) {
8636                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8637                        win.mContentChanged = false;
8638                    }
8639                    if (win.mAttrs.type == TYPE_DREAM) {
8640                        // Don't layout windows behind a dream, so that if it
8641                        // does stuff like hide the status bar we won't get a
8642                        // bad transition when it goes away.
8643                        behindDream = true;
8644                    }
8645                    win.mLayoutNeeded = false;
8646                    win.prelayout();
8647                    mPolicy.layoutWindowLw(win, null);
8648                    win.mLayoutSeq = seq;
8649                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8650                            + win.mFrame + " mContainingFrame="
8651                            + win.mContainingFrame + " mDisplayFrame="
8652                            + win.mDisplayFrame);
8653                } else {
8654                    if (topAttached < 0) topAttached = i;
8655                }
8656            }
8657            if (win.mViewVisibility == View.VISIBLE
8658                    && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
8659                    && universeBackground == null) {
8660                universeBackground = win.mWinAnimator;
8661            }
8662        }
8663
8664        if (mAnimator.mUniverseBackground  != universeBackground) {
8665            mFocusMayChange = true;
8666            mAnimator.mUniverseBackground = universeBackground;
8667        }
8668
8669        boolean attachedBehindDream = false;
8670
8671        // Now perform layout of attached windows, which usually
8672        // depend on the position of the window they are attached to.
8673        // XXX does not deal with windows that are attached to windows
8674        // that are themselves attached.
8675        for (i = topAttached; i >= 0; i--) {
8676            final WindowState win = windows.get(i);
8677
8678            if (win.mLayoutAttached) {
8679                if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
8680                        + " mHaveFrame=" + win.mHaveFrame
8681                        + " mViewVisibility=" + win.mViewVisibility
8682                        + " mRelayoutCalled=" + win.mRelayoutCalled);
8683                // If this view is GONE, then skip it -- keep the current
8684                // frame, and let the caller know so they can ignore it
8685                // if they want.  (We do the normal layout for INVISIBLE
8686                // windows, since that means "perform layout as normal,
8687                // just don't display").
8688                if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
8689                    continue;
8690                }
8691                if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
8692                        || !win.mHaveFrame || win.mLayoutNeeded) {
8693                    if (initial) {
8694                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8695                        win.mContentChanged = false;
8696                    }
8697                    win.mLayoutNeeded = false;
8698                    win.prelayout();
8699                    mPolicy.layoutWindowLw(win, win.mAttachedWindow);
8700                    win.mLayoutSeq = seq;
8701                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8702                            + win.mFrame + " mContainingFrame="
8703                            + win.mContainingFrame + " mDisplayFrame="
8704                            + win.mDisplayFrame);
8705                }
8706            } else if (win.mAttrs.type == TYPE_DREAM) {
8707                // Don't layout windows behind a dream, so that if it
8708                // does stuff like hide the status bar we won't get a
8709                // bad transition when it goes away.
8710                attachedBehindDream = behindDream;
8711            }
8712        }
8713
8714        // Window frames may have changed.  Tell the input dispatcher about it.
8715        mInputMonitor.setUpdateInputWindowsNeededLw();
8716        if (updateInputWindows) {
8717            mInputMonitor.updateInputWindowsLw(false /*force*/);
8718        }
8719
8720        mPolicy.finishLayoutLw();
8721    }
8722
8723    void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
8724        // If the screen is currently frozen or off, then keep
8725        // it frozen/off until this window draws at its new
8726        // orientation.
8727        if (!okToDisplay()) {
8728            if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w);
8729            w.mOrientationChanging = true;
8730            w.mLastFreezeDuration = 0;
8731            mInnerFields.mOrientationChangeComplete = false;
8732            if (!mWindowsFreezingScreen) {
8733                mWindowsFreezingScreen = true;
8734                // XXX should probably keep timeout from
8735                // when we first froze the display.
8736                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8737                mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
8738                        WINDOW_FREEZE_TIMEOUT_DURATION);
8739            }
8740        }
8741    }
8742
8743    /**
8744     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8745     * @param windows List of windows on default display.
8746     * @return bitmap indicating if another pass through layout must be made.
8747     */
8748    public int handleAppTransitionReadyLocked(WindowList windows) {
8749        int changes = 0;
8750        int i;
8751        int NN = mOpeningApps.size();
8752        boolean goodToGo = true;
8753        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8754                "Checking " + NN + " opening apps (frozen="
8755                + mDisplayFrozen + " timeout="
8756                + mAppTransition.isTimeout() + ")...");
8757        if (!mDisplayFrozen && !mAppTransition.isTimeout()) {
8758            // If the display isn't frozen, wait to do anything until
8759            // all of the apps are ready.  Otherwise just go because
8760            // we'll unfreeze the display when everyone is ready.
8761            for (i=0; i<NN && goodToGo; i++) {
8762                AppWindowToken wtoken = mOpeningApps.valueAt(i);
8763                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8764                        "Check opening app=" + wtoken + ": allDrawn="
8765                        + wtoken.allDrawn + " startingDisplayed="
8766                        + wtoken.startingDisplayed + " startingMoved="
8767                        + wtoken.startingMoved);
8768                if (!wtoken.allDrawn && !wtoken.startingDisplayed
8769                        && !wtoken.startingMoved) {
8770                    goodToGo = false;
8771                }
8772            }
8773        }
8774        if (goodToGo) {
8775            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
8776            int transit = mAppTransition.getAppTransition();
8777            if (mSkipAppTransitionAnimation) {
8778                transit = AppTransition.TRANSIT_UNSET;
8779            }
8780            mAppTransition.goodToGo();
8781            mStartingIconInTransition = false;
8782            mSkipAppTransitionAnimation = false;
8783
8784            mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
8785
8786            rebuildAppWindowListLocked();
8787
8788            // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
8789            WindowState oldWallpaper =
8790                    mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
8791                        && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
8792                    ? null : mWallpaperTarget;
8793
8794            mInnerFields.mWallpaperMayChange = false;
8795
8796            // The top-most window will supply the layout params,
8797            // and we will determine it below.
8798            LayoutParams animLp = null;
8799            int bestAnimLayer = -1;
8800            boolean fullscreenAnim = false;
8801            boolean voiceInteraction = false;
8802
8803            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8804                    "New wallpaper target=" + mWallpaperTarget
8805                    + ", oldWallpaper=" + oldWallpaper
8806                    + ", lower target=" + mLowerWallpaperTarget
8807                    + ", upper target=" + mUpperWallpaperTarget);
8808
8809            boolean openingAppHasWallpaper = false;
8810            boolean closingAppHasWallpaper = false;
8811            final AppWindowToken lowerWallpaperAppToken;
8812            final AppWindowToken upperWallpaperAppToken;
8813            if (mLowerWallpaperTarget == null) {
8814                lowerWallpaperAppToken = upperWallpaperAppToken = null;
8815            } else {
8816                lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
8817                upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
8818            }
8819
8820            // Do a first pass through the tokens for two
8821            // things:
8822            // (1) Determine if both the closing and opening
8823            // app token sets are wallpaper targets, in which
8824            // case special animations are needed
8825            // (since the wallpaper needs to stay static
8826            // behind them).
8827            // (2) Find the layout params of the top-most
8828            // application window in the tokens, which is
8829            // what will control the animation theme.
8830            final int NC = mClosingApps.size();
8831            NN = NC + mOpeningApps.size();
8832            for (i=0; i<NN; i++) {
8833                final AppWindowToken wtoken;
8834                if (i < NC) {
8835                    wtoken = mClosingApps.valueAt(i);
8836                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8837                        closingAppHasWallpaper = true;
8838                    }
8839                } else {
8840                    wtoken = mOpeningApps.valueAt(i - NC);
8841                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8842                        openingAppHasWallpaper = true;
8843                    }
8844                }
8845
8846                voiceInteraction |= wtoken.voiceInteraction;
8847
8848                if (wtoken.appFullscreen) {
8849                    WindowState ws = wtoken.findMainWindow();
8850                    if (ws != null) {
8851                        animLp = ws.mAttrs;
8852                        bestAnimLayer = ws.mLayer;
8853                        fullscreenAnim = true;
8854                    }
8855                } else if (!fullscreenAnim) {
8856                    WindowState ws = wtoken.findMainWindow();
8857                    if (ws != null) {
8858                        if (ws.mLayer > bestAnimLayer) {
8859                            animLp = ws.mAttrs;
8860                            bestAnimLayer = ws.mLayer;
8861                        }
8862                    }
8863                }
8864            }
8865
8866            mAnimateWallpaperWithTarget = false;
8867            if (closingAppHasWallpaper && openingAppHasWallpaper) {
8868                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
8869                switch (transit) {
8870                    case AppTransition.TRANSIT_ACTIVITY_OPEN:
8871                    case AppTransition.TRANSIT_TASK_OPEN:
8872                    case AppTransition.TRANSIT_TASK_TO_FRONT:
8873                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
8874                        break;
8875                    case AppTransition.TRANSIT_ACTIVITY_CLOSE:
8876                    case AppTransition.TRANSIT_TASK_CLOSE:
8877                    case AppTransition.TRANSIT_TASK_TO_BACK:
8878                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
8879                        break;
8880                }
8881                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
8882            } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
8883                    && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
8884                // We are transitioning from an activity with
8885                // a wallpaper to one without.
8886                transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
8887                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8888                        "New transit away from wallpaper: " + transit);
8889            } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
8890                // We are transitioning from an activity without
8891                // a wallpaper to now showing the wallpaper
8892                transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
8893                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8894                        "New transit into wallpaper: " + transit);
8895            } else {
8896                mAnimateWallpaperWithTarget = true;
8897            }
8898
8899            // If all closing windows are obscured, then there is
8900            // no need to do an animation.  This is the case, for
8901            // example, when this transition is being done behind
8902            // the lock screen.
8903            if (!mPolicy.allowAppAnimationsLw()) {
8904                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8905                        "Animations disallowed by keyguard or dream.");
8906                animLp = null;
8907            }
8908
8909            AppWindowToken topOpeningApp = null;
8910            AppWindowToken topClosingApp = null;
8911            int topOpeningLayer = 0;
8912            int topClosingLayer = 0;
8913
8914            NN = mOpeningApps.size();
8915            for (i=0; i<NN; i++) {
8916                AppWindowToken wtoken = mOpeningApps.valueAt(i);
8917                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
8918                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
8919                appAnimator.clearThumbnail();
8920                appAnimator.animation = null;
8921                wtoken.inPendingTransaction = false;
8922                setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction);
8923                wtoken.updateReportedVisibilityLocked();
8924                wtoken.waitingToShow = false;
8925
8926                appAnimator.mAllAppWinAnimators.clear();
8927                final int N = wtoken.allAppWindows.size();
8928                for (int j = 0; j < N; j++) {
8929                    appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
8930                }
8931                mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
8932
8933                if (animLp != null) {
8934                    int layer = -1;
8935                    for (int j=0; j<wtoken.windows.size(); j++) {
8936                        WindowState win = wtoken.windows.get(j);
8937                        if (win.mWinAnimator.mAnimLayer > layer) {
8938                            layer = win.mWinAnimator.mAnimLayer;
8939                        }
8940                    }
8941                    if (topOpeningApp == null || layer > topOpeningLayer) {
8942                        topOpeningApp = wtoken;
8943                        topOpeningLayer = layer;
8944                    }
8945                }
8946            }
8947            NN = mClosingApps.size();
8948            for (i=0; i<NN; i++) {
8949                AppWindowToken wtoken = mClosingApps.valueAt(i);
8950                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
8951                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
8952                appAnimator.clearThumbnail();
8953                appAnimator.animation = null;
8954                wtoken.inPendingTransaction = false;
8955                setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction);
8956                wtoken.updateReportedVisibilityLocked();
8957                wtoken.waitingToHide = false;
8958                // Force the allDrawn flag, because we want to start
8959                // this guy's animations regardless of whether it's
8960                // gotten drawn.
8961                wtoken.allDrawn = true;
8962                wtoken.deferClearAllDrawn = false;
8963
8964                if (animLp != null) {
8965                    int layer = -1;
8966                    for (int j=0; j<wtoken.windows.size(); j++) {
8967                        WindowState win = wtoken.windows.get(j);
8968                        if (win.mWinAnimator.mAnimLayer > layer) {
8969                            layer = win.mWinAnimator.mAnimLayer;
8970                        }
8971                    }
8972                    if (topClosingApp == null || layer > topClosingLayer) {
8973                        topClosingApp = wtoken;
8974                        topClosingLayer = layer;
8975                    }
8976                }
8977            }
8978
8979            AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null :
8980                    topOpeningApp.mAppAnimator;
8981            AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
8982                    topClosingApp.mAppAnimator;
8983            Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
8984            if (nextAppTransitionThumbnail != null
8985                    && openingAppAnimator != null && openingAppAnimator.animation != null &&
8986                    nextAppTransitionThumbnail.getConfig() != Config.ALPHA_8) {
8987                // This thumbnail animation is very special, we need to have
8988                // an extra surface with the thumbnail included with the animation.
8989                Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
8990                        nextAppTransitionThumbnail.getHeight());
8991                try {
8992                    // TODO(multi-display): support other displays
8993                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
8994                    final Display display = displayContent.getDisplay();
8995                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
8996
8997                    // Create a new surface for the thumbnail
8998                    SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
8999                            "thumbnail anim", dirty.width(), dirty.height(),
9000                            PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
9001                    surfaceControl.setLayerStack(display.getLayerStack());
9002                    if (SHOW_TRANSACTIONS) {
9003                        Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
9004                    }
9005
9006                    // Draw the thumbnail onto the surface
9007                    Surface drawSurface = new Surface();
9008                    drawSurface.copyFrom(surfaceControl);
9009                    Canvas c = drawSurface.lockCanvas(dirty);
9010                    c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
9011                    drawSurface.unlockCanvasAndPost(c);
9012                    drawSurface.release();
9013
9014                    // Get the thumbnail animation
9015                    Animation anim;
9016                    if (mAppTransition.isNextThumbnailTransitionAspectScaled()) {
9017                        // For the new aspect-scaled transition, we want it to always show
9018                        // above the animating opening/closing window, and we want to
9019                        // synchronize its thumbnail surface with the surface for the
9020                        // open/close animation (only on the way down)
9021                        anim = mAppTransition.createThumbnailAspectScaleAnimationLocked(
9022                                displayInfo.appWidth, displayInfo.appHeight,
9023                                displayInfo.logicalWidth, transit);
9024                        openingAppAnimator.thumbnailForceAboveLayer = Math.max(topOpeningLayer,
9025                                topClosingLayer);
9026                        openingAppAnimator.deferThumbnailDestruction =
9027                                !mAppTransition.isNextThumbnailTransitionScaleUp();
9028                        if (openingAppAnimator.deferThumbnailDestruction) {
9029                            if (closingAppAnimator != null &&
9030                                    closingAppAnimator.animation != null) {
9031                                closingAppAnimator.deferredThumbnail = surfaceControl;
9032                            }
9033                        }
9034                    } else {
9035                        anim = mAppTransition.createThumbnailScaleAnimationLocked(
9036                                displayInfo.appWidth, displayInfo.appHeight, transit);
9037                    }
9038                    anim.restrictDuration(MAX_ANIMATION_DURATION);
9039                    anim.scaleCurrentDuration(getTransitionAnimationScaleLocked());
9040
9041                    openingAppAnimator.thumbnail = surfaceControl;
9042                    openingAppAnimator.thumbnailLayer = topOpeningLayer;
9043                    openingAppAnimator.thumbnailAnimation = anim;
9044                    openingAppAnimator.thumbnailX = mAppTransition.getStartingX();
9045                    openingAppAnimator.thumbnailY = mAppTransition.getStartingY();
9046                } catch (OutOfResourcesException e) {
9047                    Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
9048                            + " h=" + dirty.height(), e);
9049                    openingAppAnimator.clearThumbnail();
9050                }
9051            }
9052
9053            mAppTransition.postAnimationCallback();
9054            mAppTransition.clear();
9055
9056            mOpeningApps.clear();
9057            mClosingApps.clear();
9058
9059            // This has changed the visibility of windows, so perform
9060            // a new layout to get them all up-to-date.
9061            changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
9062                    | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
9063            getDefaultDisplayContentLocked().layoutNeeded = true;
9064
9065            // TODO(multidisplay): IMEs are only supported on the default display.
9066            if (windows == getDefaultWindowListLocked()
9067                    && !moveInputMethodWindowsIfNeededLocked(true)) {
9068                assignLayersLocked(windows);
9069            }
9070            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, true /*updateInputWindows*/);
9071            mFocusMayChange = false;
9072        }
9073
9074        return changes;
9075    }
9076
9077    /**
9078     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
9079     * @return bitmap indicating if another pass through layout must be made.
9080     */
9081    private int handleAnimatingStoppedAndTransitionLocked() {
9082        int changes = 0;
9083
9084        mAppTransition.setIdle();
9085        // Restore window app tokens to the ActivityManager views
9086        ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks();
9087        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
9088            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9089            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9090                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9091                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9092                    tokens.get(tokenNdx).sendingToBottom = false;
9093                }
9094            }
9095        }
9096        rebuildAppWindowListLocked();
9097
9098        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
9099        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
9100                "Wallpaper layer changed: assigning layers + relayout");
9101        moveInputMethodWindowsIfNeededLocked(true);
9102        mInnerFields.mWallpaperMayChange = true;
9103        // Since the window list has been rebuilt, focus might
9104        // have to be recomputed since the actual order of windows
9105        // might have changed again.
9106        mFocusMayChange = true;
9107
9108        return changes;
9109    }
9110
9111    private void updateResizingWindows(final WindowState w) {
9112        final WindowStateAnimator winAnimator = w.mWinAnimator;
9113        if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
9114            w.setInsetsChanged();
9115            boolean configChanged = w.isConfigChanged();
9116            if (DEBUG_CONFIGURATION && configChanged) {
9117                Slog.v(TAG, "Win " + w + " config changed: "
9118                        + mCurConfiguration);
9119            }
9120            if (localLOGV) Slog.v(TAG, "Resizing " + w
9121                    + ": configChanged=" + configChanged
9122                    + " last=" + w.mLastFrame + " frame=" + w.mFrame);
9123            w.mLastFrame.set(w.mFrame);
9124            if (w.mContentInsetsChanged
9125                    || w.mVisibleInsetsChanged
9126                    || winAnimator.mSurfaceResized
9127                    || configChanged) {
9128                if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
9129                    Slog.v(TAG, "Resize reasons for w=" + w + ": "
9130                            + " contentInsetsChanged=" + w.mContentInsetsChanged
9131                            + " " + w.mContentInsets.toShortString()
9132                            + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
9133                            + " " + w.mVisibleInsets.toShortString()
9134                            + " stableInsetsChanged=" + w.mStableInsetsChanged
9135                            + " " + w.mStableInsets.toShortString()
9136                            + " surfaceResized=" + winAnimator.mSurfaceResized
9137                            + " configChanged=" + configChanged);
9138                }
9139
9140                w.mLastOverscanInsets.set(w.mOverscanInsets);
9141                w.mLastContentInsets.set(w.mContentInsets);
9142                w.mLastVisibleInsets.set(w.mVisibleInsets);
9143                w.mLastStableInsets.set(w.mStableInsets);
9144                makeWindowFreezingScreenIfNeededLocked(w);
9145                // If the orientation is changing, then we need to
9146                // hold off on unfreezing the display until this
9147                // window has been redrawn; to do that, we need
9148                // to go through the process of getting informed
9149                // by the application when it has finished drawing.
9150                if (w.mOrientationChanging) {
9151                    if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
9152                            "Orientation start waiting for draw mDrawState=DRAW_PENDING in "
9153                            + w + ", surface " + winAnimator.mSurfaceControl);
9154                    winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
9155                    if (w.mAppToken != null) {
9156                        w.mAppToken.allDrawn = false;
9157                        w.mAppToken.deferClearAllDrawn = false;
9158                    }
9159                }
9160                if (!mResizingWindows.contains(w)) {
9161                    if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
9162                            "Resizing window " + w + " to " + winAnimator.mSurfaceW
9163                            + "x" + winAnimator.mSurfaceH);
9164                    mResizingWindows.add(w);
9165                }
9166            } else if (w.mOrientationChanging) {
9167                if (w.isDrawnLw()) {
9168                    if (DEBUG_ORIENTATION) Slog.v(TAG,
9169                            "Orientation not waiting for draw in "
9170                            + w + ", surface " + winAnimator.mSurfaceControl);
9171                    w.mOrientationChanging = false;
9172                    w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
9173                            - mDisplayFreezeTime);
9174                }
9175            }
9176        }
9177    }
9178
9179    /**
9180     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
9181     *
9182     * @param w WindowState this method is applied to.
9183     * @param currentTime The time which animations use for calculating transitions.
9184     * @param innerDw Width of app window.
9185     * @param innerDh Height of app window.
9186     */
9187    private void handleNotObscuredLocked(final WindowState w, final long currentTime,
9188                                         final int innerDw, final int innerDh) {
9189        final WindowManager.LayoutParams attrs = w.mAttrs;
9190        final int attrFlags = attrs.flags;
9191        final boolean canBeSeen = w.isDisplayedLw();
9192        final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
9193
9194        if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
9195            // This window completely covers everything behind it,
9196            // so we want to leave all of them as undimmed (for
9197            // performance reasons).
9198            mInnerFields.mObscured = true;
9199        }
9200
9201        if (w.mHasSurface) {
9202            if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
9203                mInnerFields.mHoldScreen = w.mSession;
9204            }
9205            if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0
9206                    && mInnerFields.mScreenBrightness < 0) {
9207                mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness;
9208            }
9209            if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0
9210                    && mInnerFields.mButtonBrightness < 0) {
9211                mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
9212            }
9213            if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
9214                    && mInnerFields.mUserActivityTimeout < 0) {
9215                mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
9216            }
9217
9218            final int type = attrs.type;
9219            if (canBeSeen
9220                    && (type == TYPE_SYSTEM_DIALOG
9221                     || type == TYPE_RECENTS_OVERLAY
9222                     || type == TYPE_SYSTEM_ERROR
9223                     || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
9224                mInnerFields.mSyswin = true;
9225            }
9226
9227            if (canBeSeen) {
9228                // This function assumes that the contents of the default display are
9229                // processed first before secondary displays.
9230                final DisplayContent displayContent = w.getDisplayContent();
9231                if (displayContent != null && displayContent.isDefaultDisplay) {
9232                    // While a dream or keyguard is showing, obscure ordinary application
9233                    // content on secondary displays (by forcibly enabling mirroring unless
9234                    // there is other content we want to show) but still allow opaque
9235                    // keyguard dialogs to be shown.
9236                    if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
9237                        mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true;
9238                    }
9239                    mInnerFields.mDisplayHasContent = true;
9240                } else if (displayContent != null &&
9241                        (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays
9242                        || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) {
9243                    // Allow full screen keyguard presentation dialogs to be seen.
9244                    mInnerFields.mDisplayHasContent = true;
9245                }
9246                if (mInnerFields.mPreferredRefreshRate == 0
9247                        && w.mAttrs.preferredRefreshRate != 0) {
9248                    mInnerFields.mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
9249                }
9250            }
9251        }
9252    }
9253
9254    private void handleFlagDimBehind(WindowState w) {
9255        final WindowManager.LayoutParams attrs = w.mAttrs;
9256        if ((attrs.flags & FLAG_DIM_BEHIND) != 0
9257                && w.isDisplayedLw()
9258                && !w.mExiting) {
9259            final WindowStateAnimator winAnimator = w.mWinAnimator;
9260            final TaskStack stack = w.getStack();
9261            stack.setDimmingTag();
9262            if (!stack.isDimming(winAnimator)) {
9263                if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
9264                stack.startDimmingIfNeeded(winAnimator);
9265            }
9266        }
9267    }
9268
9269    private void updateAllDrawnLocked(DisplayContent displayContent) {
9270        // See if any windows have been drawn, so they (and others
9271        // associated with them) can now be shown.
9272        ArrayList<TaskStack> stacks = displayContent.getStacks();
9273        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
9274            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9275            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9276                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9277                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9278                    final AppWindowToken wtoken = tokens.get(tokenNdx);
9279                    if (!wtoken.allDrawn) {
9280                        int numInteresting = wtoken.numInterestingWindows;
9281                        if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
9282                            if (DEBUG_VISIBILITY) Slog.v(TAG,
9283                                    "allDrawn: " + wtoken
9284                                    + " interesting=" + numInteresting
9285                                    + " drawn=" + wtoken.numDrawnWindows);
9286                            wtoken.allDrawn = true;
9287                            mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
9288                        }
9289                    }
9290                }
9291            }
9292        }
9293    }
9294
9295    // "Something has changed!  Let's make it correct now."
9296    private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
9297        if (DEBUG_WINDOW_TRACE) {
9298            Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
9299                    + Debug.getCallers(3));
9300        }
9301
9302        final long currentTime = SystemClock.uptimeMillis();
9303
9304        int i;
9305        boolean updateInputWindowsNeeded = false;
9306
9307        if (mFocusMayChange) {
9308            mFocusMayChange = false;
9309            updateInputWindowsNeeded = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
9310                    false /*updateInputWindows*/);
9311        }
9312
9313        // Initialize state of exiting tokens.
9314        final int numDisplays = mDisplayContents.size();
9315        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9316            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9317            for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
9318                displayContent.mExitingTokens.get(i).hasVisible = false;
9319            }
9320        }
9321
9322        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
9323            // Initialize state of exiting applications.
9324            final AppTokenList exitingAppTokens =
9325                    mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
9326            for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9327                exitingAppTokens.get(tokenNdx).hasVisible = false;
9328            }
9329        }
9330
9331        mInnerFields.mHoldScreen = null;
9332        mInnerFields.mScreenBrightness = -1;
9333        mInnerFields.mButtonBrightness = -1;
9334        mInnerFields.mUserActivityTimeout = -1;
9335        mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false;
9336
9337        mTransactionSequence++;
9338
9339        final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
9340        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
9341        final int defaultDw = defaultInfo.logicalWidth;
9342        final int defaultDh = defaultInfo.logicalHeight;
9343
9344        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9345                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
9346        SurfaceControl.openTransaction();
9347        try {
9348
9349            if (mWatermark != null) {
9350                mWatermark.positionSurface(defaultDw, defaultDh);
9351            }
9352            if (mStrictModeFlash != null) {
9353                mStrictModeFlash.positionSurface(defaultDw, defaultDh);
9354            }
9355            if (mCircularDisplayMask != null) {
9356                mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation);
9357            }
9358
9359            boolean focusDisplayed = false;
9360
9361            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9362                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9363                boolean updateAllDrawn = false;
9364                WindowList windows = displayContent.getWindowList();
9365                DisplayInfo displayInfo = displayContent.getDisplayInfo();
9366                final int displayId = displayContent.getDisplayId();
9367                final int dw = displayInfo.logicalWidth;
9368                final int dh = displayInfo.logicalHeight;
9369                final int innerDw = displayInfo.appWidth;
9370                final int innerDh = displayInfo.appHeight;
9371                final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
9372
9373                // Reset for each display.
9374                mInnerFields.mDisplayHasContent = false;
9375                mInnerFields.mPreferredRefreshRate = 0;
9376
9377                int repeats = 0;
9378                do {
9379                    repeats++;
9380                    if (repeats > 6) {
9381                        Slog.w(TAG, "Animation repeat aborted after too many iterations");
9382                        displayContent.layoutNeeded = false;
9383                        break;
9384                    }
9385
9386                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
9387                        displayContent.pendingLayoutChanges);
9388
9389                    if ((displayContent.pendingLayoutChanges &
9390                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
9391                            (adjustWallpaperWindowsLocked() &
9392                                    ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
9393                        assignLayersLocked(windows);
9394                        displayContent.layoutNeeded = true;
9395                    }
9396
9397                    if (isDefaultDisplay && (displayContent.pendingLayoutChanges
9398                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
9399                        if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
9400                        if (updateOrientationFromAppTokensLocked(true)) {
9401                            displayContent.layoutNeeded = true;
9402                            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9403                        }
9404                    }
9405
9406                    if ((displayContent.pendingLayoutChanges
9407                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9408                        displayContent.layoutNeeded = true;
9409                    }
9410
9411                    // FIRST LOOP: Perform a layout, if needed.
9412                    if (repeats < 4) {
9413                        performLayoutLockedInner(displayContent, repeats == 1,
9414                                false /*updateInputWindows*/);
9415                    } else {
9416                        Slog.w(TAG, "Layout repeat skipped after too many iterations");
9417                    }
9418
9419                    // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
9420                    // it is animating.
9421                    displayContent.pendingLayoutChanges = 0;
9422
9423                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
9424                            + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
9425
9426                    if (isDefaultDisplay) {
9427                        mPolicy.beginPostLayoutPolicyLw(dw, dh);
9428                        for (i = windows.size() - 1; i >= 0; i--) {
9429                            WindowState w = windows.get(i);
9430                            if (w.mHasSurface) {
9431                                mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs);
9432                            }
9433                        }
9434                        displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
9435                        if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
9436                            "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
9437                    }
9438                } while (displayContent.pendingLayoutChanges != 0);
9439
9440                mInnerFields.mObscured = false;
9441                mInnerFields.mSyswin = false;
9442                displayContent.resetDimming();
9443
9444                // Only used if default window
9445                final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
9446
9447                final int N = windows.size();
9448                for (i=N-1; i>=0; i--) {
9449                    WindowState w = windows.get(i);
9450                    final TaskStack stack = w.getStack();
9451                    if (stack == null) {
9452                        continue;
9453                    }
9454
9455                    final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
9456
9457                    // Update effect.
9458                    w.mObscured = mInnerFields.mObscured;
9459                    if (!mInnerFields.mObscured) {
9460                        handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
9461                    }
9462
9463                    if (!stack.testDimmingTag()) {
9464                        handleFlagDimBehind(w);
9465                    }
9466
9467                    if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
9468                            && w.isVisibleLw()) {
9469                        // This is the wallpaper target and its obscured state
9470                        // changed... make sure the current wallaper's visibility
9471                        // has been updated accordingly.
9472                        updateWallpaperVisibilityLocked();
9473                    }
9474
9475                    final WindowStateAnimator winAnimator = w.mWinAnimator;
9476
9477                    // If the window has moved due to its containing
9478                    // content frame changing, then we'd like to animate
9479                    // it.
9480                    if (w.mHasSurface && w.shouldAnimateMove()) {
9481                        // Frame has moved, containing content frame
9482                        // has also moved, and we're not currently animating...
9483                        // let's do something.
9484                        Animation a = AnimationUtils.loadAnimation(mContext,
9485                                com.android.internal.R.anim.window_move_from_decor);
9486                        winAnimator.setAnimation(a);
9487                        winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
9488                        winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
9489
9490                        //TODO (multidisplay): Accessibility supported only for the default display.
9491                        if (mAccessibilityController != null
9492                                && displayId == Display.DEFAULT_DISPLAY) {
9493                            mAccessibilityController.onSomeWindowResizedOrMovedLocked();
9494                        }
9495
9496                        try {
9497                            w.mClient.moved(w.mFrame.left, w.mFrame.top);
9498                        } catch (RemoteException e) {
9499                        }
9500                    }
9501
9502                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
9503                    w.mContentChanged = false;
9504
9505                    // Moved from updateWindowsAndWallpaperLocked().
9506                    if (w.mHasSurface) {
9507                        // Take care of the window being ready to display.
9508                        final boolean committed =
9509                                winAnimator.commitFinishDrawingLocked(currentTime);
9510                        if (isDefaultDisplay && committed) {
9511                            if (w.mAttrs.type == TYPE_DREAM) {
9512                                // HACK: When a dream is shown, it may at that
9513                                // point hide the lock screen.  So we need to
9514                                // redo the layout to let the phone window manager
9515                                // make this happen.
9516                                displayContent.pendingLayoutChanges |=
9517                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9518                                if (DEBUG_LAYOUT_REPEATS) {
9519                                    debugLayoutRepeats(
9520                                        "dream and commitFinishDrawingLocked true",
9521                                        displayContent.pendingLayoutChanges);
9522                                }
9523                            }
9524                            if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
9525                                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
9526                                        "First draw done in potential wallpaper target " + w);
9527                                mInnerFields.mWallpaperMayChange = true;
9528                                displayContent.pendingLayoutChanges |=
9529                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9530                                if (DEBUG_LAYOUT_REPEATS) {
9531                                    debugLayoutRepeats(
9532                                        "wallpaper and commitFinishDrawingLocked true",
9533                                        displayContent.pendingLayoutChanges);
9534                                }
9535                            }
9536                        }
9537
9538                        winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
9539
9540                        final AppWindowToken atoken = w.mAppToken;
9541                        if (DEBUG_STARTING_WINDOW && atoken != null
9542                                && w == atoken.startingWindow) {
9543                            Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
9544                                + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
9545                                + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
9546                        }
9547                        if (atoken != null
9548                                && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
9549                            if (atoken.lastTransactionSequence != mTransactionSequence) {
9550                                atoken.lastTransactionSequence = mTransactionSequence;
9551                                atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9552                                atoken.startingDisplayed = false;
9553                            }
9554                            if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
9555                                    && !w.mExiting && !w.mDestroying) {
9556                                if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
9557                                    Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
9558                                            + ", isAnimating=" + winAnimator.isAnimating());
9559                                    if (!w.isDrawnLw()) {
9560                                        Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
9561                                                + " pv=" + w.mPolicyVisibility
9562                                                + " mDrawState=" + winAnimator.mDrawState
9563                                                + " ah=" + w.mAttachedHidden
9564                                                + " th=" + atoken.hiddenRequested
9565                                                + " a=" + winAnimator.mAnimating);
9566                                    }
9567                                }
9568                                if (w != atoken.startingWindow) {
9569                                    if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
9570                                        atoken.numInterestingWindows++;
9571                                        if (w.isDrawnLw()) {
9572                                            atoken.numDrawnWindows++;
9573                                            if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
9574                                                    "tokenMayBeDrawn: " + atoken
9575                                                    + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
9576                                                    + " mAppFreezing=" + w.mAppFreezing);
9577                                            updateAllDrawn = true;
9578                                        }
9579                                    }
9580                                } else if (w.isDrawnLw()) {
9581                                    atoken.startingDisplayed = true;
9582                                }
9583                            }
9584                        }
9585                    }
9586
9587                    if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
9588                            && w.isDisplayedLw()) {
9589                        focusDisplayed = true;
9590                    }
9591
9592                    updateResizingWindows(w);
9593                }
9594
9595                mDisplayManagerInternal.setDisplayProperties(displayId,
9596                        mInnerFields.mDisplayHasContent, mInnerFields.mPreferredRefreshRate,
9597                        true /* inTraversal, must call performTraversalInTrans... below */);
9598
9599                getDisplayContentLocked(displayId).stopDimmingIfNeeded();
9600
9601                if (updateAllDrawn) {
9602                    updateAllDrawnLocked(displayContent);
9603                }
9604            }
9605
9606            if (focusDisplayed) {
9607                mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
9608            }
9609
9610            // Give the display manager a chance to adjust properties
9611            // like display rotation if it needs to.
9612            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
9613
9614        } catch (RuntimeException e) {
9615            Log.wtf(TAG, "Unhandled exception in Window Manager", e);
9616        } finally {
9617            SurfaceControl.closeTransaction();
9618            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9619                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
9620        }
9621
9622        final WindowList defaultWindows = defaultDisplay.getWindowList();
9623
9624        // If we are ready to perform an app transition, check through
9625        // all of the app tokens to be shown and see if they are ready
9626        // to go.
9627        if (mAppTransition.isReady()) {
9628            defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
9629            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
9630                    defaultDisplay.pendingLayoutChanges);
9631        }
9632
9633        if (!mAnimator.mAnimating && mAppTransition.isRunning()) {
9634            // We have finished the animation of an app transition.  To do
9635            // this, we have delayed a lot of operations like showing and
9636            // hiding apps, moving apps in Z-order, etc.  The app token list
9637            // reflects the correct Z-order, but the window list may now
9638            // be out of sync with it.  So here we will just rebuild the
9639            // entire app window list.  Fun!
9640            defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
9641            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
9642                defaultDisplay.pendingLayoutChanges);
9643        }
9644
9645        if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
9646                && !mAppTransition.isReady()) {
9647            // At this point, there was a window with a wallpaper that
9648            // was force hiding other windows behind it, but now it
9649            // is going away.  This may be simple -- just animate
9650            // away the wallpaper and its window -- or it may be
9651            // hard -- the wallpaper now needs to be shown behind
9652            // something that was hidden.
9653            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9654            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
9655                defaultDisplay.pendingLayoutChanges);
9656        }
9657        mInnerFields.mWallpaperForceHidingChanged = false;
9658
9659        if (mInnerFields.mWallpaperMayChange) {
9660            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
9661            defaultDisplay.pendingLayoutChanges |=
9662                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9663            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
9664                    defaultDisplay.pendingLayoutChanges);
9665        }
9666
9667        if (mFocusMayChange) {
9668            mFocusMayChange = false;
9669            if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
9670                    false /*updateInputWindows*/)) {
9671                updateInputWindowsNeeded = true;
9672                defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
9673            }
9674        }
9675
9676        if (needsLayout()) {
9677            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9678            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
9679                    defaultDisplay.pendingLayoutChanges);
9680        }
9681
9682        for (i = mResizingWindows.size() - 1; i >= 0; i--) {
9683            WindowState win = mResizingWindows.get(i);
9684            if (win.mAppFreezing) {
9685                // Don't remove this window until rotation has completed.
9686                continue;
9687            }
9688            win.reportResized();
9689            mResizingWindows.remove(i);
9690        }
9691
9692        if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
9693                "With display frozen, orientationChangeComplete="
9694                + mInnerFields.mOrientationChangeComplete);
9695        if (mInnerFields.mOrientationChangeComplete) {
9696            if (mWindowsFreezingScreen) {
9697                mWindowsFreezingScreen = false;
9698                mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource;
9699                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9700            }
9701            stopFreezingDisplayLocked();
9702        }
9703
9704        // Destroy the surface of any windows that are no longer visible.
9705        boolean wallpaperDestroyed = false;
9706        i = mDestroySurface.size();
9707        if (i > 0) {
9708            do {
9709                i--;
9710                WindowState win = mDestroySurface.get(i);
9711                win.mDestroying = false;
9712                if (mInputMethodWindow == win) {
9713                    mInputMethodWindow = null;
9714                }
9715                if (win == mWallpaperTarget) {
9716                    wallpaperDestroyed = true;
9717                }
9718                win.mWinAnimator.destroySurfaceLocked();
9719            } while (i > 0);
9720            mDestroySurface.clear();
9721        }
9722
9723        // Time to remove any exiting tokens?
9724        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9725            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9726            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
9727            for (i = exitingTokens.size() - 1; i >= 0; i--) {
9728                WindowToken token = exitingTokens.get(i);
9729                if (!token.hasVisible) {
9730                    exitingTokens.remove(i);
9731                    if (token.windowType == TYPE_WALLPAPER) {
9732                        mWallpaperTokens.remove(token);
9733                    }
9734                }
9735            }
9736        }
9737
9738        // Time to remove any exiting applications?
9739        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
9740            // Initialize state of exiting applications.
9741            final AppTokenList exitingAppTokens =
9742                    mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
9743            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
9744                AppWindowToken token = exitingAppTokens.get(i);
9745                if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) {
9746                    // Make sure there is no animation running on this token,
9747                    // so any windows associated with it will be removed as
9748                    // soon as their animations are complete
9749                    token.mAppAnimator.clearAnimation();
9750                    token.mAppAnimator.animating = false;
9751                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
9752                            "performLayout: App token exiting now removed" + token);
9753                    removeAppFromTaskLocked(token);
9754                    exitingAppTokens.remove(i);
9755                }
9756            }
9757        }
9758
9759        if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
9760            for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
9761                try {
9762                    mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
9763                } catch (RemoteException e) {
9764                }
9765            }
9766            mRelayoutWhileAnimating.clear();
9767        }
9768
9769        if (wallpaperDestroyed) {
9770            defaultDisplay.pendingLayoutChanges |=
9771                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9772            defaultDisplay.layoutNeeded = true;
9773        }
9774
9775        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9776            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9777            if (displayContent.pendingLayoutChanges != 0) {
9778                displayContent.layoutNeeded = true;
9779            }
9780        }
9781
9782        // Finally update all input windows now that the window changes have stabilized.
9783        mInputMonitor.updateInputWindowsLw(true /*force*/);
9784
9785        setHoldScreenLocked(mInnerFields.mHoldScreen);
9786        if (!mDisplayFrozen) {
9787            if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
9788                mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
9789            } else {
9790                mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
9791                        toBrightnessOverride(mInnerFields.mScreenBrightness));
9792            }
9793            if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
9794                mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
9795            } else {
9796                mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
9797                        toBrightnessOverride(mInnerFields.mButtonBrightness));
9798            }
9799            mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
9800                    mInnerFields.mUserActivityTimeout);
9801        }
9802
9803        if (mTurnOnScreen) {
9804            if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
9805            mPowerManager.wakeUp(SystemClock.uptimeMillis());
9806            mTurnOnScreen = false;
9807        }
9808
9809        if (mInnerFields.mUpdateRotation) {
9810            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
9811            if (updateRotationUncheckedLocked(false)) {
9812                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9813            } else {
9814                mInnerFields.mUpdateRotation = false;
9815            }
9816        }
9817
9818        if (mWaitingForDrawnCallback != null ||
9819                (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&
9820                        !mInnerFields.mUpdateRotation)) {
9821            checkDrawnWindowsLocked();
9822        }
9823
9824        final int N = mPendingRemove.size();
9825        if (N > 0) {
9826            if (mPendingRemoveTmp.length < N) {
9827                mPendingRemoveTmp = new WindowState[N+10];
9828            }
9829            mPendingRemove.toArray(mPendingRemoveTmp);
9830            mPendingRemove.clear();
9831            DisplayContentList displayList = new DisplayContentList();
9832            for (i = 0; i < N; i++) {
9833                WindowState w = mPendingRemoveTmp[i];
9834                removeWindowInnerLocked(w.mSession, w);
9835                final DisplayContent displayContent = w.getDisplayContent();
9836                if (displayContent != null && !displayList.contains(displayContent)) {
9837                    displayList.add(displayContent);
9838                }
9839            }
9840
9841            for (DisplayContent displayContent : displayList) {
9842                assignLayersLocked(displayContent.getWindowList());
9843                displayContent.layoutNeeded = true;
9844            }
9845        }
9846
9847        // Remove all deferred displays stacks, tasks, and activities.
9848        for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
9849            mDisplayContents.valueAt(displayNdx).checkForDeferredActions();
9850        }
9851
9852        if (updateInputWindowsNeeded) {
9853            mInputMonitor.updateInputWindowsLw(false /*force*/);
9854        }
9855        setFocusedStackFrame();
9856
9857        // Check to see if we are now in a state where the screen should
9858        // be enabled, because the window obscured flags have changed.
9859        enableScreenIfNeededLocked();
9860
9861        scheduleAnimationLocked();
9862
9863        if (DEBUG_WINDOW_TRACE) {
9864            Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
9865                    + mAnimator.mAnimating);
9866        }
9867    }
9868
9869    private int toBrightnessOverride(float value) {
9870        return (int)(value * PowerManager.BRIGHTNESS_ON);
9871    }
9872
9873    void checkDrawnWindowsLocked() {
9874        if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
9875            return;
9876        }
9877        for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
9878            WindowState win = mWaitingForDrawn.get(j);
9879            if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win +
9880                    ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
9881                    " mHasSurface=" + win.mHasSurface +
9882                    " drawState=" + win.mWinAnimator.mDrawState);
9883            if (win.mRemoved || !win.mHasSurface) {
9884                // Window has been removed; no draw will now happen, so stop waiting.
9885                if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win);
9886                mWaitingForDrawn.remove(win);
9887            } else if (win.hasDrawnLw()) {
9888                // Window is now drawn (and shown).
9889                if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win);
9890                mWaitingForDrawn.remove(win);
9891            }
9892        }
9893        if (mWaitingForDrawn.isEmpty()) {
9894            if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!");
9895            mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
9896            mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
9897        }
9898    }
9899
9900    void setHoldScreenLocked(final Session newHoldScreen) {
9901        final boolean hold = newHoldScreen != null;
9902
9903        if (hold && mHoldingScreenOn != newHoldScreen) {
9904            mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
9905        }
9906        mHoldingScreenOn = newHoldScreen;
9907
9908        final boolean state = mHoldingScreenWakeLock.isHeld();
9909        if (hold != state) {
9910            if (hold) {
9911                mHoldingScreenWakeLock.acquire();
9912                mPolicy.keepScreenOnStartedLw();
9913            } else {
9914                mPolicy.keepScreenOnStoppedLw();
9915                mHoldingScreenWakeLock.release();
9916            }
9917        }
9918    }
9919
9920    void requestTraversal() {
9921        synchronized (mWindowMap) {
9922            requestTraversalLocked();
9923        }
9924    }
9925
9926    void requestTraversalLocked() {
9927        if (!mTraversalScheduled) {
9928            mTraversalScheduled = true;
9929            mH.sendEmptyMessage(H.DO_TRAVERSAL);
9930        }
9931    }
9932
9933    /** Note that Locked in this case is on mLayoutToAnim */
9934    void scheduleAnimationLocked() {
9935        if (!mAnimationScheduled) {
9936            mAnimationScheduled = true;
9937            mChoreographer.postCallback(
9938                    Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
9939        }
9940    }
9941
9942    private boolean needsLayout() {
9943        final int numDisplays = mDisplayContents.size();
9944        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9945            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9946            if (displayContent.layoutNeeded) {
9947                return true;
9948            }
9949        }
9950        return false;
9951    }
9952
9953    boolean copyAnimToLayoutParamsLocked() {
9954        boolean doRequest = false;
9955
9956        final int bulkUpdateParams = mAnimator.mBulkUpdateParams;
9957        if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
9958            mInnerFields.mUpdateRotation = true;
9959            doRequest = true;
9960        }
9961        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
9962            mInnerFields.mWallpaperMayChange = true;
9963            doRequest = true;
9964        }
9965        if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
9966            mInnerFields.mWallpaperForceHidingChanged = true;
9967            doRequest = true;
9968        }
9969        if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
9970            mInnerFields.mOrientationChangeComplete = false;
9971        } else {
9972            mInnerFields.mOrientationChangeComplete = true;
9973            mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource;
9974            if (mWindowsFreezingScreen) {
9975                doRequest = true;
9976            }
9977        }
9978        if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
9979            mTurnOnScreen = true;
9980        }
9981        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) {
9982            mInnerFields.mWallpaperActionPending = true;
9983        }
9984
9985        return doRequest;
9986    }
9987
9988    /** If a window that has an animation specifying a colored background and the current wallpaper
9989     * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
9990     * suddenly disappear. */
9991    int adjustAnimationBackground(WindowStateAnimator winAnimator) {
9992        WindowList windows = winAnimator.mWin.getWindowList();
9993        for (int i = windows.size() - 1; i >= 0; --i) {
9994            WindowState testWin = windows.get(i);
9995            if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
9996                return testWin.mWinAnimator.mAnimLayer;
9997            }
9998        }
9999        return winAnimator.mAnimLayer;
10000    }
10001
10002    boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
10003                                           boolean secure) {
10004        final SurfaceControl surface = winAnimator.mSurfaceControl;
10005        boolean leakedSurface = false;
10006        boolean killedApps = false;
10007
10008        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
10009                winAnimator.mSession.mPid, operation);
10010
10011        if (mForceRemoves == null) {
10012            mForceRemoves = new ArrayList<WindowState>();
10013        }
10014
10015        long callingIdentity = Binder.clearCallingIdentity();
10016        try {
10017            // There was some problem...   first, do a sanity check of the
10018            // window list to make sure we haven't left any dangling surfaces
10019            // around.
10020
10021            Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
10022            final int numDisplays = mDisplayContents.size();
10023            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10024                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
10025                final int numWindows = windows.size();
10026                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
10027                    final WindowState ws = windows.get(winNdx);
10028                    WindowStateAnimator wsa = ws.mWinAnimator;
10029                    if (wsa.mSurfaceControl != null) {
10030                        if (!mSessions.contains(wsa.mSession)) {
10031                            Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
10032                                    + ws + " surface=" + wsa.mSurfaceControl
10033                                    + " token=" + ws.mToken
10034                                    + " pid=" + ws.mSession.mPid
10035                                    + " uid=" + ws.mSession.mUid);
10036                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
10037                            wsa.mSurfaceControl.destroy();
10038                            wsa.mSurfaceShown = false;
10039                            wsa.mSurfaceControl = null;
10040                            ws.mHasSurface = false;
10041                            mForceRemoves.add(ws);
10042                            leakedSurface = true;
10043                        } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
10044                            Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
10045                                    + ws + " surface=" + wsa.mSurfaceControl
10046                                    + " token=" + ws.mAppToken);
10047                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
10048                            wsa.mSurfaceControl.destroy();
10049                            wsa.mSurfaceShown = false;
10050                            wsa.mSurfaceControl = null;
10051                            ws.mHasSurface = false;
10052                            leakedSurface = true;
10053                        }
10054                    }
10055                }
10056            }
10057
10058            if (!leakedSurface) {
10059                Slog.w(TAG, "No leaked surfaces; killing applicatons!");
10060                SparseIntArray pidCandidates = new SparseIntArray();
10061                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10062                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
10063                    final int numWindows = windows.size();
10064                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
10065                        final WindowState ws = windows.get(winNdx);
10066                        if (mForceRemoves.contains(ws)) {
10067                            continue;
10068                        }
10069                        WindowStateAnimator wsa = ws.mWinAnimator;
10070                        if (wsa.mSurfaceControl != null) {
10071                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
10072                        }
10073                    }
10074                    if (pidCandidates.size() > 0) {
10075                        int[] pids = new int[pidCandidates.size()];
10076                        for (int i=0; i<pids.length; i++) {
10077                            pids[i] = pidCandidates.keyAt(i);
10078                        }
10079                        try {
10080                            if (mActivityManager.killPids(pids, "Free memory", secure)) {
10081                                killedApps = true;
10082                            }
10083                        } catch (RemoteException e) {
10084                        }
10085                    }
10086                }
10087            }
10088
10089            if (leakedSurface || killedApps) {
10090                // We managed to reclaim some memory, so get rid of the trouble
10091                // surface and ask the app to request another one.
10092                Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
10093                if (surface != null) {
10094                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
10095                            "RECOVER DESTROY", null);
10096                    surface.destroy();
10097                    winAnimator.mSurfaceShown = false;
10098                    winAnimator.mSurfaceControl = null;
10099                    winAnimator.mWin.mHasSurface = false;
10100                    scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken);
10101                }
10102
10103                try {
10104                    winAnimator.mWin.mClient.dispatchGetNewSurface();
10105                } catch (RemoteException e) {
10106                }
10107            }
10108        } finally {
10109            Binder.restoreCallingIdentity(callingIdentity);
10110        }
10111
10112        return leakedSurface || killedApps;
10113    }
10114
10115    private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
10116        WindowState newFocus = computeFocusedWindowLocked();
10117        if (mCurrentFocus != newFocus) {
10118            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
10119            // This check makes sure that we don't already have the focus
10120            // change message pending.
10121            mH.removeMessages(H.REPORT_FOCUS_CHANGE);
10122            mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
10123            // TODO(multidisplay): Focused windows on default display only.
10124            final DisplayContent displayContent = getDefaultDisplayContentLocked();
10125            final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
10126                    mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
10127                            && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
10128            if (imWindowChanged) {
10129                displayContent.layoutNeeded = true;
10130                newFocus = computeFocusedWindowLocked();
10131            }
10132
10133            if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " +
10134                    mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
10135            final WindowState oldFocus = mCurrentFocus;
10136            mCurrentFocus = newFocus;
10137            mLosingFocus.remove(newFocus);
10138
10139            // TODO(multidisplay): Accessibilty supported only of default desiplay.
10140            if (mAccessibilityController != null
10141                    && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
10142                mAccessibilityController.onWindowFocusChangedLocked();
10143            }
10144
10145            int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
10146
10147            if (imWindowChanged && oldFocus != mInputMethodWindow) {
10148                // Focus of the input method window changed. Perform layout if needed.
10149                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
10150                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
10151                    focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
10152                } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
10153                    // Client will do the layout, but we need to assign layers
10154                    // for handleNewWindowLocked() below.
10155                    assignLayersLocked(displayContent.getWindowList());
10156                }
10157            }
10158
10159            if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
10160                // The change in focus caused us to need to do a layout.  Okay.
10161                displayContent.layoutNeeded = true;
10162                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
10163                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
10164                }
10165            }
10166
10167            if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
10168                // If we defer assigning layers, then the caller is responsible for
10169                // doing this part.
10170                mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
10171            }
10172
10173            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
10174            return true;
10175        }
10176        return false;
10177    }
10178
10179    private WindowState computeFocusedWindowLocked() {
10180        if (mAnimator.mUniverseBackground != null
10181                && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
10182            return mAnimator.mUniverseBackground.mWin;
10183        }
10184
10185        final int displayCount = mDisplayContents.size();
10186        for (int i = 0; i < displayCount; i++) {
10187            final DisplayContent displayContent = mDisplayContents.valueAt(i);
10188            WindowState win = findFocusedWindowLocked(displayContent);
10189            if (win != null) {
10190                return win;
10191            }
10192        }
10193        return null;
10194    }
10195
10196    private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
10197        final WindowList windows = displayContent.getWindowList();
10198        for (int i = windows.size() - 1; i >= 0; i--) {
10199            final WindowState win = windows.get(i);
10200
10201            if (localLOGV || DEBUG_FOCUS) Slog.v(
10202                TAG, "Looking for focus: " + i
10203                + " = " + win
10204                + ", flags=" + win.mAttrs.flags
10205                + ", canReceive=" + win.canReceiveKeys());
10206
10207            AppWindowToken wtoken = win.mAppToken;
10208
10209            // If this window's application has been removed, just skip it.
10210            if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
10211                if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because "
10212                        + (wtoken.removed ? "removed" : "sendingToBottom"));
10213                continue;
10214            }
10215
10216            if (!win.canReceiveKeys()) {
10217                continue;
10218            }
10219
10220            // Descend through all of the app tokens and find the first that either matches
10221            // win.mAppToken (return win) or mFocusedApp (return null).
10222            if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
10223                    mFocusedApp != null) {
10224                ArrayList<Task> tasks = displayContent.getTasks();
10225                for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
10226                    AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
10227                    int tokenNdx = tokens.size() - 1;
10228                    for ( ; tokenNdx >= 0; --tokenNdx) {
10229                        final AppWindowToken token = tokens.get(tokenNdx);
10230                        if (wtoken == token) {
10231                            break;
10232                        }
10233                        if (mFocusedApp == token) {
10234                            // Whoops, we are below the focused app...  no focus for you!
10235                            if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG,
10236                                    "findFocusedWindow: Reached focused app=" + mFocusedApp);
10237                            return null;
10238                        }
10239                    }
10240                    if (tokenNdx >= 0) {
10241                        // Early exit from loop, must have found the matching token.
10242                        break;
10243                    }
10244                }
10245            }
10246
10247            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i +
10248                        " = " + win);
10249            return win;
10250        }
10251
10252        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows.");
10253        return null;
10254    }
10255
10256    private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
10257        if (mDisplayFrozen) {
10258            return;
10259        }
10260
10261        if (!mDisplayReady || !mPolicy.isScreenOnFully()) {
10262            // No need to freeze the screen before the system is ready or if
10263            // the screen is off.
10264            return;
10265        }
10266
10267        mScreenFrozenLock.acquire();
10268
10269        mDisplayFrozen = true;
10270        mDisplayFreezeTime = SystemClock.elapsedRealtime();
10271        mLastFinishedFreezeSource = null;
10272
10273        mInputMonitor.freezeInputDispatchingLw();
10274
10275        // Clear the last input window -- that is just used for
10276        // clean transitions between IMEs, and if we are freezing
10277        // the screen then the whole world is changing behind the scenes.
10278        mPolicy.setLastInputMethodWindowLw(null, null);
10279
10280        if (mAppTransition.isTransitionSet()) {
10281            mAppTransition.freeze();
10282        }
10283
10284        if (PROFILE_ORIENTATION) {
10285            File file = new File("/data/system/frozen");
10286            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
10287        }
10288
10289        if (CUSTOM_SCREEN_ROTATION) {
10290            mExitAnimId = exitAnim;
10291            mEnterAnimId = enterAnim;
10292            final DisplayContent displayContent = getDefaultDisplayContentLocked();
10293            final int displayId = displayContent.getDisplayId();
10294            ScreenRotationAnimation screenRotationAnimation =
10295                    mAnimator.getScreenRotationAnimationLocked(displayId);
10296            if (screenRotationAnimation != null) {
10297                screenRotationAnimation.kill();
10298            }
10299
10300            // Check whether the current screen contains any secure content.
10301            boolean isSecure = false;
10302            final WindowList windows = getDefaultWindowListLocked();
10303            final int N = windows.size();
10304            for (int i = 0; i < N; i++) {
10305                WindowState ws = windows.get(i);
10306                if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
10307                    isSecure = true;
10308                    break;
10309                }
10310            }
10311
10312            // TODO(multidisplay): rotation on main screen only.
10313            displayContent.updateDisplayInfo();
10314            screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
10315                    mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure);
10316            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10317        }
10318    }
10319
10320    private void stopFreezingDisplayLocked() {
10321        if (!mDisplayFrozen) {
10322            return;
10323        }
10324
10325        if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
10326                || mClientFreezingScreen) {
10327            if (DEBUG_ORIENTATION) Slog.d(TAG,
10328                "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
10329                + ", mAppsFreezingScreen=" + mAppsFreezingScreen
10330                + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
10331                + ", mClientFreezingScreen=" + mClientFreezingScreen);
10332            return;
10333        }
10334
10335        mDisplayFrozen = false;
10336        mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
10337        StringBuilder sb = new StringBuilder(128);
10338        sb.append("Screen frozen for ");
10339        TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
10340        if (mLastFinishedFreezeSource != null) {
10341            sb.append(" due to ");
10342            sb.append(mLastFinishedFreezeSource);
10343        }
10344        Slog.i(TAG, sb.toString());
10345        mH.removeMessages(H.APP_FREEZE_TIMEOUT);
10346        mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
10347        if (PROFILE_ORIENTATION) {
10348            Debug.stopMethodTracing();
10349        }
10350
10351        boolean updateRotation = false;
10352
10353        final DisplayContent displayContent = getDefaultDisplayContentLocked();
10354        final int displayId = displayContent.getDisplayId();
10355        ScreenRotationAnimation screenRotationAnimation =
10356                mAnimator.getScreenRotationAnimationLocked(displayId);
10357        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
10358                && screenRotationAnimation.hasScreenshot()) {
10359            if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
10360            // TODO(multidisplay): rotation on main screen only.
10361            DisplayInfo displayInfo = displayContent.getDisplayInfo();
10362            // Get rotation animation again, with new top window
10363            boolean isDimming = displayContent.isDimming();
10364            if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
10365                mExitAnimId = mEnterAnimId = 0;
10366            }
10367            if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
10368                    getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
10369                        displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
10370                scheduleAnimationLocked();
10371            } else {
10372                screenRotationAnimation.kill();
10373                screenRotationAnimation = null;
10374                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10375                updateRotation = true;
10376            }
10377        } else {
10378            if (screenRotationAnimation != null) {
10379                screenRotationAnimation.kill();
10380                screenRotationAnimation = null;
10381                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10382            }
10383            updateRotation = true;
10384        }
10385
10386        mInputMonitor.thawInputDispatchingLw();
10387
10388        boolean configChanged;
10389
10390        // While the display is frozen we don't re-compute the orientation
10391        // to avoid inconsistent states.  However, something interesting
10392        // could have actually changed during that time so re-evaluate it
10393        // now to catch that.
10394        configChanged = updateOrientationFromAppTokensLocked(false);
10395
10396        // A little kludge: a lot could have happened while the
10397        // display was frozen, so now that we are coming back we
10398        // do a gc so that any remote references the system
10399        // processes holds on others can be released if they are
10400        // no longer needed.
10401        mH.removeMessages(H.FORCE_GC);
10402        mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
10403
10404        mScreenFrozenLock.release();
10405
10406        if (updateRotation) {
10407            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
10408            configChanged |= updateRotationUncheckedLocked(false);
10409        }
10410
10411        if (configChanged) {
10412            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
10413        }
10414    }
10415
10416    static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
10417            DisplayMetrics dm) {
10418        if (index < tokens.length) {
10419            String str = tokens[index];
10420            if (str != null && str.length() > 0) {
10421                try {
10422                    int val = Integer.parseInt(str);
10423                    return val;
10424                } catch (Exception e) {
10425                }
10426            }
10427        }
10428        if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
10429            return defDps;
10430        }
10431        int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
10432        return val;
10433    }
10434
10435    void createWatermarkInTransaction() {
10436        if (mWatermark != null) {
10437            return;
10438        }
10439
10440        File file = new File("/system/etc/setup.conf");
10441        FileInputStream in = null;
10442        DataInputStream ind = null;
10443        try {
10444            in = new FileInputStream(file);
10445            ind = new DataInputStream(in);
10446            String line = ind.readLine();
10447            if (line != null) {
10448                String[] toks = line.split("%");
10449                if (toks != null && toks.length > 0) {
10450                    mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
10451                            mRealDisplayMetrics, mFxSession, toks);
10452                }
10453            }
10454        } catch (FileNotFoundException e) {
10455        } catch (IOException e) {
10456        } finally {
10457            if (ind != null) {
10458                try {
10459                    ind.close();
10460                } catch (IOException e) {
10461                }
10462            } else if (in != null) {
10463                try {
10464                    in.close();
10465                } catch (IOException e) {
10466                }
10467            }
10468        }
10469    }
10470
10471    @Override
10472    public void statusBarVisibilityChanged(int visibility) {
10473        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
10474                != PackageManager.PERMISSION_GRANTED) {
10475            throw new SecurityException("Caller does not hold permission "
10476                    + android.Manifest.permission.STATUS_BAR);
10477        }
10478
10479        synchronized (mWindowMap) {
10480            mLastStatusBarVisibility = visibility;
10481            visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
10482            updateStatusBarVisibilityLocked(visibility);
10483        }
10484    }
10485
10486    // TOOD(multidisplay): StatusBar on multiple screens?
10487    void updateStatusBarVisibilityLocked(int visibility) {
10488        mInputManager.setSystemUiVisibility(visibility);
10489        final WindowList windows = getDefaultWindowListLocked();
10490        final int N = windows.size();
10491        for (int i = 0; i < N; i++) {
10492            WindowState ws = windows.get(i);
10493            try {
10494                int curValue = ws.mSystemUiVisibility;
10495                int diff = curValue ^ visibility;
10496                // We are only interested in differences of one of the
10497                // clearable flags...
10498                diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
10499                // ...if it has actually been cleared.
10500                diff &= ~visibility;
10501                int newValue = (curValue&~diff) | (visibility&diff);
10502                if (newValue != curValue) {
10503                    ws.mSeq++;
10504                    ws.mSystemUiVisibility = newValue;
10505                }
10506                if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
10507                    ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
10508                            visibility, newValue, diff);
10509                }
10510            } catch (RemoteException e) {
10511                // so sorry
10512            }
10513        }
10514    }
10515
10516    @Override
10517    public void reevaluateStatusBarVisibility() {
10518        synchronized (mWindowMap) {
10519            int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
10520            updateStatusBarVisibilityLocked(visibility);
10521            performLayoutAndPlaceSurfacesLocked();
10522        }
10523    }
10524
10525    @Override
10526    public FakeWindow addFakeWindow(Looper looper,
10527            InputEventReceiver.Factory inputEventReceiverFactory,
10528            String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags,
10529            boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) {
10530        synchronized (mWindowMap) {
10531            FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
10532                    name, windowType,
10533                    layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys,
10534                    hasFocus, touchFullscreen);
10535            int i=0;
10536            while (i<mFakeWindows.size()) {
10537                if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
10538                    break;
10539                }
10540            }
10541            mFakeWindows.add(i, fw);
10542            mInputMonitor.updateInputWindowsLw(true);
10543            return fw;
10544        }
10545    }
10546
10547    boolean removeFakeWindowLocked(FakeWindow window) {
10548        synchronized (mWindowMap) {
10549            if (mFakeWindows.remove(window)) {
10550                mInputMonitor.updateInputWindowsLw(true);
10551                return true;
10552            }
10553            return false;
10554        }
10555    }
10556
10557    // It is assumed that this method is called only by InputMethodManagerService.
10558    public void saveLastInputMethodWindowForTransition() {
10559        synchronized (mWindowMap) {
10560            // TODO(multidisplay): Pass in the displayID.
10561            DisplayContent displayContent = getDefaultDisplayContentLocked();
10562            if (mInputMethodWindow != null) {
10563                mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
10564            }
10565        }
10566    }
10567
10568    public int getInputMethodWindowVisibleHeight() {
10569        synchronized (mWindowMap) {
10570            return mPolicy.getInputMethodWindowVisibleHeightLw();
10571        }
10572    }
10573
10574    @Override
10575    public boolean hasNavigationBar() {
10576        return mPolicy.hasNavigationBar();
10577    }
10578
10579    @Override
10580    public void lockNow(Bundle options) {
10581        mPolicy.lockNow(options);
10582    }
10583
10584    public void showRecentApps() {
10585        mPolicy.showRecentApps();
10586    }
10587
10588    @Override
10589    public boolean isSafeModeEnabled() {
10590        return mSafeMode;
10591    }
10592
10593    @Override
10594    public boolean clearWindowContentFrameStats(IBinder token) {
10595        if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10596                "clearWindowContentFrameStats()")) {
10597            throw new SecurityException("Requires FRAME_STATS permission");
10598        }
10599        synchronized (mWindowMap) {
10600            WindowState windowState = mWindowMap.get(token);
10601            if (windowState == null) {
10602                return false;
10603            }
10604            SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
10605            if (surfaceControl == null) {
10606                return false;
10607            }
10608            return surfaceControl.clearContentFrameStats();
10609        }
10610    }
10611
10612    @Override
10613    public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
10614        if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10615                "getWindowContentFrameStats()")) {
10616            throw new SecurityException("Requires FRAME_STATS permission");
10617        }
10618        synchronized (mWindowMap) {
10619            WindowState windowState = mWindowMap.get(token);
10620            if (windowState == null) {
10621                return null;
10622            }
10623            SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
10624            if (surfaceControl == null) {
10625                return null;
10626            }
10627            if (mTempWindowRenderStats == null) {
10628                mTempWindowRenderStats = new WindowContentFrameStats();
10629            }
10630            WindowContentFrameStats stats = mTempWindowRenderStats;
10631            if (!surfaceControl.getContentFrameStats(stats)) {
10632                return null;
10633            }
10634            return stats;
10635        }
10636    }
10637
10638    void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10639        pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
10640        mPolicy.dump("    ", pw, args);
10641    }
10642
10643    void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10644        pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
10645        mAnimator.dumpLocked(pw, "    ", dumpAll);
10646    }
10647
10648    void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
10649        pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
10650        if (mTokenMap.size() > 0) {
10651            pw.println("  All tokens:");
10652            Iterator<WindowToken> it = mTokenMap.values().iterator();
10653            while (it.hasNext()) {
10654                WindowToken token = it.next();
10655                pw.print("  "); pw.print(token);
10656                if (dumpAll) {
10657                    pw.println(':');
10658                    token.dump(pw, "    ");
10659                } else {
10660                    pw.println();
10661                }
10662            }
10663        }
10664        if (mWallpaperTokens.size() > 0) {
10665            pw.println();
10666            pw.println("  Wallpaper tokens:");
10667            for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
10668                WindowToken token = mWallpaperTokens.get(i);
10669                pw.print("  Wallpaper #"); pw.print(i);
10670                        pw.print(' '); pw.print(token);
10671                if (dumpAll) {
10672                    pw.println(':');
10673                    token.dump(pw, "    ");
10674                } else {
10675                    pw.println();
10676                }
10677            }
10678        }
10679        if (mFinishedStarting.size() > 0) {
10680            pw.println();
10681            pw.println("  Finishing start of application tokens:");
10682            for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10683                WindowToken token = mFinishedStarting.get(i);
10684                pw.print("  Finished Starting #"); pw.print(i);
10685                        pw.print(' '); pw.print(token);
10686                if (dumpAll) {
10687                    pw.println(':');
10688                    token.dump(pw, "    ");
10689                } else {
10690                    pw.println();
10691                }
10692            }
10693        }
10694        if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
10695            pw.println();
10696            if (mOpeningApps.size() > 0) {
10697                pw.print("  mOpeningApps="); pw.println(mOpeningApps);
10698            }
10699            if (mClosingApps.size() > 0) {
10700                pw.print("  mClosingApps="); pw.println(mClosingApps);
10701            }
10702        }
10703    }
10704
10705    void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
10706        pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
10707        for (int i=0; i<mSessions.size(); i++) {
10708            Session s = mSessions.valueAt(i);
10709            pw.print("  Session "); pw.print(s); pw.println(':');
10710            s.dump(pw, "    ");
10711        }
10712    }
10713
10714    void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
10715        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
10716        if (mDisplayReady) {
10717            final int numDisplays = mDisplayContents.size();
10718            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10719                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10720                displayContent.dump("  ", pw);
10721            }
10722        } else {
10723            pw.println("  NO DISPLAY");
10724        }
10725    }
10726
10727    void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
10728            ArrayList<WindowState> windows) {
10729        pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
10730        dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
10731    }
10732
10733    void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
10734            ArrayList<WindowState> windows) {
10735        final int numDisplays = mDisplayContents.size();
10736        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10737            final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
10738            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10739                final WindowState w = windowList.get(winNdx);
10740                if (windows == null || windows.contains(w)) {
10741                    pw.print("  Window #"); pw.print(winNdx); pw.print(' ');
10742                            pw.print(w); pw.println(":");
10743                    w.dump(pw, "    ", dumpAll || windows != null);
10744                }
10745            }
10746        }
10747        if (mInputMethodDialogs.size() > 0) {
10748            pw.println();
10749            pw.println("  Input method dialogs:");
10750            for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10751                WindowState w = mInputMethodDialogs.get(i);
10752                if (windows == null || windows.contains(w)) {
10753                    pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
10754                }
10755            }
10756        }
10757        if (mPendingRemove.size() > 0) {
10758            pw.println();
10759            pw.println("  Remove pending for:");
10760            for (int i=mPendingRemove.size()-1; i>=0; i--) {
10761                WindowState w = mPendingRemove.get(i);
10762                if (windows == null || windows.contains(w)) {
10763                    pw.print("  Remove #"); pw.print(i); pw.print(' ');
10764                            pw.print(w);
10765                    if (dumpAll) {
10766                        pw.println(":");
10767                        w.dump(pw, "    ", true);
10768                    } else {
10769                        pw.println();
10770                    }
10771                }
10772            }
10773        }
10774        if (mForceRemoves != null && mForceRemoves.size() > 0) {
10775            pw.println();
10776            pw.println("  Windows force removing:");
10777            for (int i=mForceRemoves.size()-1; i>=0; i--) {
10778                WindowState w = mForceRemoves.get(i);
10779                pw.print("  Removing #"); pw.print(i); pw.print(' ');
10780                        pw.print(w);
10781                if (dumpAll) {
10782                    pw.println(":");
10783                    w.dump(pw, "    ", true);
10784                } else {
10785                    pw.println();
10786                }
10787            }
10788        }
10789        if (mDestroySurface.size() > 0) {
10790            pw.println();
10791            pw.println("  Windows waiting to destroy their surface:");
10792            for (int i=mDestroySurface.size()-1; i>=0; i--) {
10793                WindowState w = mDestroySurface.get(i);
10794                if (windows == null || windows.contains(w)) {
10795                    pw.print("  Destroy #"); pw.print(i); pw.print(' ');
10796                            pw.print(w);
10797                    if (dumpAll) {
10798                        pw.println(":");
10799                        w.dump(pw, "    ", true);
10800                    } else {
10801                        pw.println();
10802                    }
10803                }
10804            }
10805        }
10806        if (mLosingFocus.size() > 0) {
10807            pw.println();
10808            pw.println("  Windows losing focus:");
10809            for (int i=mLosingFocus.size()-1; i>=0; i--) {
10810                WindowState w = mLosingFocus.get(i);
10811                if (windows == null || windows.contains(w)) {
10812                    pw.print("  Losing #"); pw.print(i); pw.print(' ');
10813                            pw.print(w);
10814                    if (dumpAll) {
10815                        pw.println(":");
10816                        w.dump(pw, "    ", true);
10817                    } else {
10818                        pw.println();
10819                    }
10820                }
10821            }
10822        }
10823        if (mResizingWindows.size() > 0) {
10824            pw.println();
10825            pw.println("  Windows waiting to resize:");
10826            for (int i=mResizingWindows.size()-1; i>=0; i--) {
10827                WindowState w = mResizingWindows.get(i);
10828                if (windows == null || windows.contains(w)) {
10829                    pw.print("  Resizing #"); pw.print(i); pw.print(' ');
10830                            pw.print(w);
10831                    if (dumpAll) {
10832                        pw.println(":");
10833                        w.dump(pw, "    ", true);
10834                    } else {
10835                        pw.println();
10836                    }
10837                }
10838            }
10839        }
10840        if (mWaitingForDrawn.size() > 0) {
10841            pw.println();
10842            pw.println("  Clients waiting for these windows to be drawn:");
10843            for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
10844                WindowState win = mWaitingForDrawn.get(i);
10845                pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
10846            }
10847        }
10848        pw.println();
10849        pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
10850        pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
10851        if (mLastFocus != mCurrentFocus) {
10852            pw.print("  mLastFocus="); pw.println(mLastFocus);
10853        }
10854        pw.print("  mFocusedApp="); pw.println(mFocusedApp);
10855        if (mInputMethodTarget != null) {
10856            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
10857        }
10858        pw.print("  mInTouchMode="); pw.print(mInTouchMode);
10859                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
10860        pw.print("  mLastDisplayFreezeDuration=");
10861                TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
10862                if ( mLastFinishedFreezeSource != null) {
10863                    pw.print(" due to ");
10864                    pw.print(mLastFinishedFreezeSource);
10865                }
10866                pw.println();
10867        if (dumpAll) {
10868            pw.print("  mSystemDecorLayer="); pw.print(mSystemDecorLayer);
10869                    pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
10870            if (mLastStatusBarVisibility != 0) {
10871                pw.print("  mLastStatusBarVisibility=0x");
10872                        pw.println(Integer.toHexString(mLastStatusBarVisibility));
10873            }
10874            if (mInputMethodWindow != null) {
10875                pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
10876            }
10877            pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
10878            if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
10879                pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
10880                pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
10881            }
10882            pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
10883                    pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
10884            if (mInputMethodAnimLayerAdjustment != 0 ||
10885                    mWallpaperAnimLayerAdjustment != 0) {
10886                pw.print("  mInputMethodAnimLayerAdjustment=");
10887                        pw.print(mInputMethodAnimLayerAdjustment);
10888                        pw.print("  mWallpaperAnimLayerAdjustment=");
10889                        pw.println(mWallpaperAnimLayerAdjustment);
10890            }
10891            pw.print("  mSystemBooted="); pw.print(mSystemBooted);
10892                    pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10893            if (needsLayout()) {
10894                pw.print("  layoutNeeded on displays=");
10895                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10896                    final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10897                    if (displayContent.layoutNeeded) {
10898                        pw.print(displayContent.getDisplayId());
10899                    }
10900                }
10901                pw.println();
10902            }
10903            pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
10904            pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
10905                    pw.print(" windows="); pw.print(mWindowsFreezingScreen);
10906                    pw.print(" client="); pw.print(mClientFreezingScreen);
10907                    pw.print(" apps="); pw.print(mAppsFreezingScreen);
10908                    pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
10909            pw.print("  mRotation="); pw.print(mRotation);
10910                    pw.print(" mAltOrientation="); pw.println(mAltOrientation);
10911            pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
10912                    pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
10913            pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
10914            pw.print("  Animation settings: disabled="); pw.print(mAnimationsDisabled);
10915                    pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
10916                    pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
10917                    pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
10918            pw.print("  mTraversalScheduled="); pw.println(mTraversalScheduled);
10919            pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
10920                    pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
10921            pw.println("  mLayoutToAnim:");
10922            mAppTransition.dump(pw);
10923        }
10924    }
10925
10926    boolean dumpWindows(PrintWriter pw, String name, String[] args,
10927            int opti, boolean dumpAll) {
10928        WindowList windows = new WindowList();
10929        if ("visible".equals(name)) {
10930            synchronized(mWindowMap) {
10931                final int numDisplays = mDisplayContents.size();
10932                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10933                    final WindowList windowList =
10934                            mDisplayContents.valueAt(displayNdx).getWindowList();
10935                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10936                        final WindowState w = windowList.get(winNdx);
10937                        if (w.mWinAnimator.mSurfaceShown) {
10938                            windows.add(w);
10939                        }
10940                    }
10941                }
10942            }
10943        } else {
10944            int objectId = 0;
10945            // See if this is an object ID.
10946            try {
10947                objectId = Integer.parseInt(name, 16);
10948                name = null;
10949            } catch (RuntimeException e) {
10950            }
10951            synchronized(mWindowMap) {
10952                final int numDisplays = mDisplayContents.size();
10953                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10954                    final WindowList windowList =
10955                            mDisplayContents.valueAt(displayNdx).getWindowList();
10956                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10957                        final WindowState w = windowList.get(winNdx);
10958                        if (name != null) {
10959                            if (w.mAttrs.getTitle().toString().contains(name)) {
10960                                windows.add(w);
10961                            }
10962                        } else if (System.identityHashCode(w) == objectId) {
10963                            windows.add(w);
10964                        }
10965                    }
10966                }
10967            }
10968        }
10969
10970        if (windows.size() <= 0) {
10971            return false;
10972        }
10973
10974        synchronized(mWindowMap) {
10975            dumpWindowsLocked(pw, dumpAll, windows);
10976        }
10977        return true;
10978    }
10979
10980    void dumpLastANRLocked(PrintWriter pw) {
10981        pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
10982        if (mLastANRState == null) {
10983            pw.println("  <no ANR has occurred since boot>");
10984        } else {
10985            pw.println(mLastANRState);
10986        }
10987    }
10988
10989    /**
10990     * Saves information about the state of the window manager at
10991     * the time an ANR occurred before anything else in the system changes
10992     * in response.
10993     *
10994     * @param appWindowToken The application that ANR'd, may be null.
10995     * @param windowState The window that ANR'd, may be null.
10996     * @param reason The reason for the ANR, may be null.
10997     */
10998    public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
10999            String reason) {
11000        StringWriter sw = new StringWriter();
11001        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
11002        pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
11003        if (appWindowToken != null) {
11004            pw.println("  Application at fault: " + appWindowToken.stringName);
11005        }
11006        if (windowState != null) {
11007            pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
11008        }
11009        if (reason != null) {
11010            pw.println("  Reason: " + reason);
11011        }
11012        pw.println();
11013        dumpWindowsNoHeaderLocked(pw, true, null);
11014        pw.close();
11015        mLastANRState = sw.toString();
11016    }
11017
11018    @Override
11019    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
11020        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
11021                != PackageManager.PERMISSION_GRANTED) {
11022            pw.println("Permission Denial: can't dump WindowManager from from pid="
11023                    + Binder.getCallingPid()
11024                    + ", uid=" + Binder.getCallingUid());
11025            return;
11026        }
11027
11028        boolean dumpAll = false;
11029
11030        int opti = 0;
11031        while (opti < args.length) {
11032            String opt = args[opti];
11033            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
11034                break;
11035            }
11036            opti++;
11037            if ("-a".equals(opt)) {
11038                dumpAll = true;
11039            } else if ("-h".equals(opt)) {
11040                pw.println("Window manager dump options:");
11041                pw.println("  [-a] [-h] [cmd] ...");
11042                pw.println("  cmd may be one of:");
11043                pw.println("    l[astanr]: last ANR information");
11044                pw.println("    p[policy]: policy state");
11045                pw.println("    a[animator]: animator state");
11046                pw.println("    s[essions]: active sessions");
11047                pw.println("    d[isplays]: active display contents");
11048                pw.println("    t[okens]: token list");
11049                pw.println("    w[indows]: window list");
11050                pw.println("  cmd may also be a NAME to dump windows.  NAME may");
11051                pw.println("    be a partial substring in a window name, a");
11052                pw.println("    Window hex object identifier, or");
11053                pw.println("    \"all\" for all windows, or");
11054                pw.println("    \"visible\" for the visible windows.");
11055                pw.println("  -a: include all available server state.");
11056                return;
11057            } else {
11058                pw.println("Unknown argument: " + opt + "; use -h for help");
11059            }
11060        }
11061
11062        // Is the caller requesting to dump a particular piece of data?
11063        if (opti < args.length) {
11064            String cmd = args[opti];
11065            opti++;
11066            if ("lastanr".equals(cmd) || "l".equals(cmd)) {
11067                synchronized(mWindowMap) {
11068                    dumpLastANRLocked(pw);
11069                }
11070                return;
11071            } else if ("policy".equals(cmd) || "p".equals(cmd)) {
11072                synchronized(mWindowMap) {
11073                    dumpPolicyLocked(pw, args, true);
11074                }
11075                return;
11076            } else if ("animator".equals(cmd) || "a".equals(cmd)) {
11077                synchronized(mWindowMap) {
11078                    dumpAnimatorLocked(pw, args, true);
11079                }
11080                return;
11081            } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
11082                synchronized(mWindowMap) {
11083                    dumpSessionsLocked(pw, true);
11084                }
11085                return;
11086            } else if ("displays".equals(cmd) || "d".equals(cmd)) {
11087                synchronized(mWindowMap) {
11088                    dumpDisplayContentsLocked(pw, true);
11089                }
11090                return;
11091            } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
11092                synchronized(mWindowMap) {
11093                    dumpTokensLocked(pw, true);
11094                }
11095                return;
11096            } else if ("windows".equals(cmd) || "w".equals(cmd)) {
11097                synchronized(mWindowMap) {
11098                    dumpWindowsLocked(pw, true, null);
11099                }
11100                return;
11101            } else if ("all".equals(cmd) || "a".equals(cmd)) {
11102                synchronized(mWindowMap) {
11103                    dumpWindowsLocked(pw, true, null);
11104                }
11105                return;
11106            } else {
11107                // Dumping a single name?
11108                if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
11109                    pw.println("Bad window command, or no windows match: " + cmd);
11110                    pw.println("Use -h for help.");
11111                }
11112                return;
11113            }
11114        }
11115
11116        synchronized(mWindowMap) {
11117            pw.println();
11118            if (dumpAll) {
11119                pw.println("-------------------------------------------------------------------------------");
11120            }
11121            dumpLastANRLocked(pw);
11122            pw.println();
11123            if (dumpAll) {
11124                pw.println("-------------------------------------------------------------------------------");
11125            }
11126            dumpPolicyLocked(pw, args, dumpAll);
11127            pw.println();
11128            if (dumpAll) {
11129                pw.println("-------------------------------------------------------------------------------");
11130            }
11131            dumpAnimatorLocked(pw, args, dumpAll);
11132            pw.println();
11133            if (dumpAll) {
11134                pw.println("-------------------------------------------------------------------------------");
11135            }
11136            dumpSessionsLocked(pw, dumpAll);
11137            pw.println();
11138            if (dumpAll) {
11139                pw.println("-------------------------------------------------------------------------------");
11140            }
11141            dumpDisplayContentsLocked(pw, dumpAll);
11142            pw.println();
11143            if (dumpAll) {
11144                pw.println("-------------------------------------------------------------------------------");
11145            }
11146            dumpTokensLocked(pw, dumpAll);
11147            pw.println();
11148            if (dumpAll) {
11149                pw.println("-------------------------------------------------------------------------------");
11150            }
11151            dumpWindowsLocked(pw, dumpAll, null);
11152        }
11153    }
11154
11155    // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
11156    @Override
11157    public void monitor() {
11158        synchronized (mWindowMap) { }
11159    }
11160
11161    public interface OnHardKeyboardStatusChangeListener {
11162        public void onHardKeyboardStatusChange(boolean available);
11163    }
11164
11165    void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
11166        if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
11167            Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
11168                    Integer.toHexString(pendingLayoutChanges));
11169        }
11170    }
11171
11172    private DisplayContent newDisplayContentLocked(final Display display) {
11173        DisplayContent displayContent = new DisplayContent(display, this);
11174        final int displayId = display.getDisplayId();
11175        if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display);
11176        mDisplayContents.put(displayId, displayContent);
11177
11178        DisplayInfo displayInfo = displayContent.getDisplayInfo();
11179        final Rect rect = new Rect();
11180        mDisplaySettings.getOverscanLocked(displayInfo.name, rect);
11181        synchronized (displayContent.mDisplaySizeLock) {
11182            displayInfo.overscanLeft = rect.left;
11183            displayInfo.overscanTop = rect.top;
11184            displayInfo.overscanRight = rect.right;
11185            displayInfo.overscanBottom = rect.bottom;
11186            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
11187                    displayId, displayInfo);
11188        }
11189        configureDisplayPolicyLocked(displayContent);
11190
11191        // TODO: Create an input channel for each display with touch capability.
11192        if (displayId == Display.DEFAULT_DISPLAY) {
11193            displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent);
11194            registerPointerEventListener(displayContent.mTapDetector);
11195        }
11196
11197        return displayContent;
11198    }
11199
11200    public void createDisplayContentLocked(final Display display) {
11201        if (display == null) {
11202            throw new IllegalArgumentException("getDisplayContent: display must not be null");
11203        }
11204        getDisplayContentLocked(display.getDisplayId());
11205    }
11206
11207    /**
11208     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
11209     * there is a Display for the displayId.
11210     * @param displayId The display the caller is interested in.
11211     * @return The DisplayContent associated with displayId or null if there is no Display for it.
11212     */
11213    public DisplayContent getDisplayContentLocked(final int displayId) {
11214        DisplayContent displayContent = mDisplayContents.get(displayId);
11215        if (displayContent == null) {
11216            final Display display = mDisplayManager.getDisplay(displayId);
11217            if (display != null) {
11218                displayContent = newDisplayContentLocked(display);
11219            }
11220        }
11221        return displayContent;
11222    }
11223
11224    // There is an inherent assumption that this will never return null.
11225    public DisplayContent getDefaultDisplayContentLocked() {
11226        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
11227    }
11228
11229    public WindowList getDefaultWindowListLocked() {
11230        return getDefaultDisplayContentLocked().getWindowList();
11231    }
11232
11233    public DisplayInfo getDefaultDisplayInfoLocked() {
11234        return getDefaultDisplayContentLocked().getDisplayInfo();
11235    }
11236
11237    /**
11238     * Return the list of WindowStates associated on the passed display.
11239     * @param display The screen to return windows from.
11240     * @return The list of WindowStates on the screen, or null if the there is no screen.
11241     */
11242    public WindowList getWindowListLocked(final Display display) {
11243        return getWindowListLocked(display.getDisplayId());
11244    }
11245
11246    /**
11247     * Return the list of WindowStates associated on the passed display.
11248     * @param displayId The screen to return windows from.
11249     * @return The list of WindowStates on the screen, or null if the there is no screen.
11250     */
11251    public WindowList getWindowListLocked(final int displayId) {
11252        final DisplayContent displayContent = getDisplayContentLocked(displayId);
11253        return displayContent != null ? displayContent.getWindowList() : null;
11254    }
11255
11256    public void onDisplayAdded(int displayId) {
11257        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
11258    }
11259
11260    public void handleDisplayAdded(int displayId) {
11261        synchronized (mWindowMap) {
11262            final Display display = mDisplayManager.getDisplay(displayId);
11263            if (display != null) {
11264                createDisplayContentLocked(display);
11265                displayReady(displayId);
11266            }
11267        }
11268    }
11269
11270    public void onDisplayRemoved(int displayId) {
11271        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
11272    }
11273
11274    private void handleDisplayRemovedLocked(int displayId) {
11275        final DisplayContent displayContent = getDisplayContentLocked(displayId);
11276        if (displayContent != null) {
11277            if (displayContent.isAnimating()) {
11278                displayContent.mDeferredRemoval = true;
11279                return;
11280            }
11281            if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent);
11282            mDisplayContents.delete(displayId);
11283            displayContent.close();
11284            if (displayId == Display.DEFAULT_DISPLAY) {
11285                unregisterPointerEventListener(displayContent.mTapDetector);
11286            }
11287        }
11288        mAnimator.removeDisplayLocked(displayId);
11289    }
11290
11291    public void onDisplayChanged(int displayId) {
11292        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
11293    }
11294
11295    private void handleDisplayChangedLocked(int displayId) {
11296        final DisplayContent displayContent = getDisplayContentLocked(displayId);
11297        if (displayContent != null) {
11298            displayContent.updateDisplayInfo();
11299        }
11300    }
11301
11302    @Override
11303    public Object getWindowManagerLock() {
11304        return mWindowMap;
11305    }
11306
11307    private final class LocalService extends WindowManagerInternal {
11308        @Override
11309        public void requestTraversalFromDisplayManager() {
11310            requestTraversal();
11311        }
11312
11313        @Override
11314        public void setMagnificationSpec(MagnificationSpec spec) {
11315            synchronized (mWindowMap) {
11316                if (mAccessibilityController != null) {
11317                    mAccessibilityController.setMagnificationSpecLocked(spec);
11318                } else {
11319                    throw new IllegalStateException("Magnification callbacks not set!");
11320                }
11321            }
11322            if (Binder.getCallingPid() != android.os.Process.myPid()) {
11323                spec.recycle();
11324            }
11325        }
11326
11327        @Override
11328        public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
11329            synchronized (mWindowMap) {
11330                WindowState windowState = mWindowMap.get(windowToken);
11331                if (windowState == null) {
11332                    return null;
11333                }
11334                MagnificationSpec spec = null;
11335                if (mAccessibilityController != null) {
11336                    spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState);
11337                }
11338                if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
11339                    return null;
11340                }
11341                spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
11342                spec.scale *= windowState.mGlobalScale;
11343                return spec;
11344            }
11345        }
11346
11347        @Override
11348        public void setMagnificationCallbacks(MagnificationCallbacks callbacks) {
11349            synchronized (mWindowMap) {
11350                if (mAccessibilityController == null) {
11351                    mAccessibilityController = new AccessibilityController(
11352                            WindowManagerService.this);
11353                }
11354                mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
11355                if (!mAccessibilityController.hasCallbacksLocked()) {
11356                    mAccessibilityController = null;
11357                }
11358            }
11359        }
11360
11361        @Override
11362        public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
11363            synchronized (mWindowMap) {
11364                if (mAccessibilityController == null) {
11365                    mAccessibilityController = new AccessibilityController(
11366                            WindowManagerService.this);
11367                }
11368                mAccessibilityController.setWindowsForAccessibilityCallback(callback);
11369                if (!mAccessibilityController.hasCallbacksLocked()) {
11370                    mAccessibilityController = null;
11371                }
11372            }
11373        }
11374
11375        @Override
11376        public void setInputFilter(IInputFilter filter) {
11377            mInputManager.setInputFilter(filter);
11378        }
11379
11380        @Override
11381        public IBinder getFocusedWindowToken() {
11382            synchronized (mWindowMap) {
11383                WindowState windowState = getFocusedWindowLocked();
11384                if (windowState != null) {
11385                    return windowState.mClient.asBinder();
11386                }
11387                return null;
11388            }
11389        }
11390
11391        @Override
11392        public boolean isKeyguardLocked() {
11393            return WindowManagerService.this.isKeyguardLocked();
11394        }
11395
11396        @Override
11397        public void showGlobalActions() {
11398            WindowManagerService.this.showGlobalActions();
11399        }
11400
11401        @Override
11402        public void getWindowFrame(IBinder token, Rect outBounds) {
11403            synchronized (mWindowMap) {
11404                WindowState windowState = mWindowMap.get(token);
11405                if (windowState != null) {
11406                    outBounds.set(windowState.mFrame);
11407                } else {
11408                    outBounds.setEmpty();
11409                }
11410            }
11411        }
11412
11413        public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
11414            synchronized (mWindowMap) {
11415                mWaitingForDrawnCallback = callback;
11416                final WindowList windows = getDefaultWindowListLocked();
11417                for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
11418                    final WindowState win = windows.get(winNdx);
11419                    if (win.mHasSurface
11420                            && (win.mAppToken != null || mPolicy.isForceHiding(win.mAttrs))) {
11421                        win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
11422                        // Force add to mResizingWindows.
11423                        win.mLastContentInsets.set(-1, -1, -1, -1);
11424                        mWaitingForDrawn.add(win);
11425                    }
11426                }
11427                requestTraversalLocked();
11428            }
11429            mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
11430            if (mWaitingForDrawn.isEmpty()) {
11431                callback.run();
11432            } else {
11433                mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
11434                checkDrawnWindowsLocked();
11435            }
11436        }
11437    }
11438}
11439