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