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