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