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