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