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