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