WindowManagerService.java revision a6c05d5151027f902c5c56bded008cbe15bd6301
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 hide keyguard");
5350            return;
5351        }
5352
5353        if (token == null) {
5354            throw new IllegalArgumentException("token == null");
5355        }
5356
5357        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5358                KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
5359    }
5360
5361    @Override
5362    public void reenableKeyguard(IBinder token) {
5363        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5364            != PackageManager.PERMISSION_GRANTED) {
5365            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5366        }
5367
5368        if (token == null) {
5369            throw new IllegalArgumentException("token == null");
5370        }
5371
5372        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5373                KeyguardDisableHandler.KEYGUARD_REENABLE, token));
5374    }
5375
5376    /**
5377     * @see android.app.KeyguardManager#exitKeyguardSecurely
5378     */
5379    @Override
5380    public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
5381        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5382            != PackageManager.PERMISSION_GRANTED) {
5383            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5384        }
5385
5386        if (callback == null) {
5387            throw new IllegalArgumentException("callback == null");
5388        }
5389
5390        mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
5391            @Override
5392            public void onKeyguardExitResult(boolean success) {
5393                try {
5394                    callback.onKeyguardExitResult(success);
5395                } catch (RemoteException e) {
5396                    // Client has died, we don't care.
5397                }
5398            }
5399        });
5400    }
5401
5402    @Override
5403    public boolean inKeyguardRestrictedInputMode() {
5404        return mPolicy.inKeyguardRestrictedKeyInputMode();
5405    }
5406
5407    @Override
5408    public boolean isKeyguardLocked() {
5409        return mPolicy.isKeyguardLocked();
5410    }
5411
5412    @Override
5413    public boolean isKeyguardSecure() {
5414        int userId = UserHandle.getCallingUserId();
5415        long origId = Binder.clearCallingIdentity();
5416        try {
5417            return mPolicy.isKeyguardSecure(userId);
5418        } finally {
5419            Binder.restoreCallingIdentity(origId);
5420        }
5421    }
5422
5423    @Override
5424    public void dismissKeyguard() {
5425        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5426                != PackageManager.PERMISSION_GRANTED) {
5427            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5428        }
5429        synchronized(mWindowMap) {
5430            mPolicy.dismissKeyguardLw();
5431        }
5432    }
5433
5434    @Override
5435    public void keyguardGoingAway(int flags) {
5436        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5437                != PackageManager.PERMISSION_GRANTED) {
5438            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5439        }
5440        if (DEBUG_KEYGUARD) Slog.d(TAG_WM,
5441                "keyguardGoingAway: flags=0x" + Integer.toHexString(flags));
5442        synchronized (mWindowMap) {
5443            mAnimator.mKeyguardGoingAway = true;
5444            mAnimator.mKeyguardGoingAwayFlags = flags;
5445            mWindowPlacerLocked.requestTraversal();
5446        }
5447    }
5448
5449    public void keyguardWaitingForActivityDrawn() {
5450        if (DEBUG_KEYGUARD) Slog.d(TAG_WM, "keyguardWaitingForActivityDrawn");
5451        synchronized (mWindowMap) {
5452            mKeyguardWaitingForActivityDrawn = true;
5453        }
5454    }
5455
5456    public void notifyActivityDrawnForKeyguard() {
5457        if (DEBUG_KEYGUARD) Slog.d(TAG_WM, "notifyActivityDrawnForKeyguard: waiting="
5458                + mKeyguardWaitingForActivityDrawn + " Callers=" + Debug.getCallers(5));
5459        synchronized (mWindowMap) {
5460            if (mKeyguardWaitingForActivityDrawn) {
5461                mPolicy.notifyActivityDrawnForKeyguardLw();
5462                mKeyguardWaitingForActivityDrawn = false;
5463            }
5464        }
5465    }
5466
5467    void showGlobalActions() {
5468        mPolicy.showGlobalActions();
5469    }
5470
5471    @Override
5472    public void closeSystemDialogs(String reason) {
5473        synchronized(mWindowMap) {
5474            final int numDisplays = mDisplayContents.size();
5475            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5476                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5477                final int numWindows = windows.size();
5478                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5479                    final WindowState w = windows.get(winNdx);
5480                    if (w.mHasSurface) {
5481                        try {
5482                            w.mClient.closeSystemDialogs(reason);
5483                        } catch (RemoteException e) {
5484                        }
5485                    }
5486                }
5487            }
5488        }
5489    }
5490
5491    static float fixScale(float scale) {
5492        if (scale < 0) scale = 0;
5493        else if (scale > 20) scale = 20;
5494        return Math.abs(scale);
5495    }
5496
5497    @Override
5498    public void setAnimationScale(int which, float scale) {
5499        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5500                "setAnimationScale()")) {
5501            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5502        }
5503
5504        scale = fixScale(scale);
5505        switch (which) {
5506            case 0: mWindowAnimationScaleSetting = scale; break;
5507            case 1: mTransitionAnimationScaleSetting = scale; break;
5508            case 2: mAnimatorDurationScaleSetting = scale; break;
5509        }
5510
5511        // Persist setting
5512        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5513    }
5514
5515    @Override
5516    public void setAnimationScales(float[] scales) {
5517        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5518                "setAnimationScale()")) {
5519            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5520        }
5521
5522        if (scales != null) {
5523            if (scales.length >= 1) {
5524                mWindowAnimationScaleSetting = fixScale(scales[0]);
5525            }
5526            if (scales.length >= 2) {
5527                mTransitionAnimationScaleSetting = fixScale(scales[1]);
5528            }
5529            if (scales.length >= 3) {
5530                mAnimatorDurationScaleSetting = fixScale(scales[2]);
5531                dispatchNewAnimatorScaleLocked(null);
5532            }
5533        }
5534
5535        // Persist setting
5536        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5537    }
5538
5539    private void setAnimatorDurationScale(float scale) {
5540        mAnimatorDurationScaleSetting = scale;
5541        ValueAnimator.setDurationScale(scale);
5542    }
5543
5544    public float getWindowAnimationScaleLocked() {
5545        return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting;
5546    }
5547
5548    public float getTransitionAnimationScaleLocked() {
5549        return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting;
5550    }
5551
5552    @Override
5553    public float getAnimationScale(int which) {
5554        switch (which) {
5555            case 0: return mWindowAnimationScaleSetting;
5556            case 1: return mTransitionAnimationScaleSetting;
5557            case 2: return mAnimatorDurationScaleSetting;
5558        }
5559        return 0;
5560    }
5561
5562    @Override
5563    public float[] getAnimationScales() {
5564        return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting,
5565                mAnimatorDurationScaleSetting };
5566    }
5567
5568    @Override
5569    public float getCurrentAnimatorScale() {
5570        synchronized(mWindowMap) {
5571            return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
5572        }
5573    }
5574
5575    void dispatchNewAnimatorScaleLocked(Session session) {
5576        mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget();
5577    }
5578
5579    @Override
5580    public void registerPointerEventListener(PointerEventListener listener) {
5581        mPointerEventDispatcher.registerInputEventListener(listener);
5582    }
5583
5584    @Override
5585    public void unregisterPointerEventListener(PointerEventListener listener) {
5586        mPointerEventDispatcher.unregisterInputEventListener(listener);
5587    }
5588
5589    // Called by window manager policy. Not exposed externally.
5590    @Override
5591    public int getLidState() {
5592        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5593                InputManagerService.SW_LID);
5594        if (sw > 0) {
5595            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5596            return LID_CLOSED;
5597        } else if (sw == 0) {
5598            // Switch state: AKEY_STATE_UP.
5599            return LID_OPEN;
5600        } else {
5601            // Switch state: AKEY_STATE_UNKNOWN.
5602            return LID_ABSENT;
5603        }
5604    }
5605
5606    // Called by window manager policy. Not exposed externally.
5607    @Override
5608    public void lockDeviceNow() {
5609        lockNow(null);
5610    }
5611
5612    // Called by window manager policy. Not exposed externally.
5613    @Override
5614    public int getCameraLensCoverState() {
5615        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5616                InputManagerService.SW_CAMERA_LENS_COVER);
5617        if (sw > 0) {
5618            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5619            return CAMERA_LENS_COVERED;
5620        } else if (sw == 0) {
5621            // Switch state: AKEY_STATE_UP.
5622            return CAMERA_LENS_UNCOVERED;
5623        } else {
5624            // Switch state: AKEY_STATE_UNKNOWN.
5625            return CAMERA_LENS_COVER_ABSENT;
5626        }
5627    }
5628
5629    // Called by window manager policy.  Not exposed externally.
5630    @Override
5631    public void switchInputMethod(boolean forwardDirection) {
5632        final InputMethodManagerInternal inputMethodManagerInternal =
5633                LocalServices.getService(InputMethodManagerInternal.class);
5634        if (inputMethodManagerInternal != null) {
5635            inputMethodManagerInternal.switchInputMethod(forwardDirection);
5636        }
5637    }
5638
5639    // Called by window manager policy.  Not exposed externally.
5640    @Override
5641    public void shutdown(boolean confirm) {
5642        ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
5643    }
5644
5645    // Called by window manager policy.  Not exposed externally.
5646    @Override
5647    public void rebootSafeMode(boolean confirm) {
5648        ShutdownThread.rebootSafeMode(mContext, confirm);
5649    }
5650
5651    public void setCurrentProfileIds(final int[] currentProfileIds) {
5652        synchronized (mWindowMap) {
5653            mCurrentProfileIds = currentProfileIds;
5654        }
5655    }
5656
5657    public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
5658        synchronized (mWindowMap) {
5659            mCurrentUserId = newUserId;
5660            mCurrentProfileIds = currentProfileIds;
5661            mAppTransition.setCurrentUser(newUserId);
5662            mPolicy.setCurrentUserLw(newUserId);
5663
5664            // Hide windows that should not be seen by the new user.
5665            final int numDisplays = mDisplayContents.size();
5666            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5667                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
5668                displayContent.switchUserStacks();
5669                rebuildAppWindowListLocked(displayContent);
5670            }
5671            mWindowPlacerLocked.performSurfacePlacement();
5672
5673            // Notify whether the docked stack exists for the current user
5674            final DisplayContent displayContent = getDefaultDisplayContentLocked();
5675            displayContent.mDividerControllerLocked
5676                    .notifyDockedStackExistsChanged(hasDockedTasksForUser(newUserId));
5677
5678            // If the display is already prepared, update the density.
5679            // Otherwise, we'll update it when it's prepared.
5680            if (mDisplayReady) {
5681                final int forcedDensity = getForcedDisplayDensityForUserLocked(newUserId);
5682                final int targetDensity = forcedDensity != 0 ? forcedDensity
5683                        : displayContent.mInitialDisplayDensity;
5684                setForcedDisplayDensityLocked(displayContent, targetDensity);
5685            }
5686        }
5687    }
5688
5689    /**
5690     * Returns whether there is a docked task for the current user.
5691     */
5692    boolean hasDockedTasksForUser(int userId) {
5693        final TaskStack stack = mStackIdToStack.get(DOCKED_STACK_ID);
5694        if (stack == null) {
5695            return false;
5696        }
5697
5698        final ArrayList<Task> tasks = stack.getTasks();
5699        boolean hasUserTask = false;
5700        for (int i = tasks.size() - 1; i >= 0 && !hasUserTask; i--) {
5701            final Task task = tasks.get(i);
5702            hasUserTask = (task.mUserId == userId);
5703        }
5704        return hasUserTask;
5705    }
5706
5707    /* Called by WindowState */
5708    boolean isCurrentProfileLocked(int userId) {
5709        if (userId == mCurrentUserId) return true;
5710        for (int i = 0; i < mCurrentProfileIds.length; i++) {
5711            if (mCurrentProfileIds[i] == userId) return true;
5712        }
5713        return false;
5714    }
5715
5716    public void enableScreenAfterBoot() {
5717        synchronized(mWindowMap) {
5718            if (DEBUG_BOOT) {
5719                RuntimeException here = new RuntimeException("here");
5720                here.fillInStackTrace();
5721                Slog.i(TAG_WM, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
5722                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5723                        + " mShowingBootMessages=" + mShowingBootMessages
5724                        + " mSystemBooted=" + mSystemBooted, here);
5725            }
5726            if (mSystemBooted) {
5727                return;
5728            }
5729            mSystemBooted = true;
5730            hideBootMessagesLocked();
5731            // If the screen still doesn't come up after 30 seconds, give
5732            // up and turn it on.
5733            mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
5734        }
5735
5736        mPolicy.systemBooted();
5737
5738        performEnableScreen();
5739    }
5740
5741    @Override
5742    public void enableScreenIfNeeded() {
5743        synchronized (mWindowMap) {
5744            enableScreenIfNeededLocked();
5745        }
5746    }
5747
5748    void enableScreenIfNeededLocked() {
5749        if (DEBUG_BOOT) {
5750            RuntimeException here = new RuntimeException("here");
5751            here.fillInStackTrace();
5752            Slog.i(TAG_WM, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
5753                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5754                    + " mShowingBootMessages=" + mShowingBootMessages
5755                    + " mSystemBooted=" + mSystemBooted, here);
5756        }
5757        if (mDisplayEnabled) {
5758            return;
5759        }
5760        if (!mSystemBooted && !mShowingBootMessages) {
5761            return;
5762        }
5763        mH.sendEmptyMessage(H.ENABLE_SCREEN);
5764    }
5765
5766    public void performBootTimeout() {
5767        synchronized(mWindowMap) {
5768            if (mDisplayEnabled) {
5769                return;
5770            }
5771            Slog.w(TAG_WM, "***** BOOT TIMEOUT: forcing display enabled");
5772            mForceDisplayEnabled = true;
5773        }
5774        performEnableScreen();
5775    }
5776
5777    private boolean checkWaitingForWindowsLocked() {
5778
5779        boolean haveBootMsg = false;
5780        boolean haveApp = false;
5781        // if the wallpaper service is disabled on the device, we're never going to have
5782        // wallpaper, don't bother waiting for it
5783        boolean haveWallpaper = false;
5784        boolean wallpaperEnabled = mContext.getResources().getBoolean(
5785                com.android.internal.R.bool.config_enableWallpaperService)
5786                && !mOnlyCore;
5787        boolean haveKeyguard = true;
5788        // TODO(multidisplay): Expand to all displays?
5789        final WindowList windows = getDefaultWindowListLocked();
5790        final int N = windows.size();
5791        for (int i=0; i<N; i++) {
5792            WindowState w = windows.get(i);
5793            if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
5794                return true;
5795            }
5796            if (w.isDrawnLw()) {
5797                if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
5798                    haveBootMsg = true;
5799                } else if (w.mAttrs.type == TYPE_APPLICATION) {
5800                    haveApp = true;
5801                } else if (w.mAttrs.type == TYPE_WALLPAPER) {
5802                    haveWallpaper = true;
5803                } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
5804                    haveKeyguard = mPolicy.isKeyguardDrawnLw();
5805                }
5806            }
5807        }
5808
5809        if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
5810            Slog.i(TAG_WM, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
5811                    + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
5812                    + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
5813                    + " haveKeyguard=" + haveKeyguard);
5814        }
5815
5816        // If we are turning on the screen to show the boot message,
5817        // don't do it until the boot message is actually displayed.
5818        if (!mSystemBooted && !haveBootMsg) {
5819            return true;
5820        }
5821
5822        // If we are turning on the screen after the boot is completed
5823        // normally, don't do so until we have the application and
5824        // wallpaper.
5825        if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
5826                (wallpaperEnabled && !haveWallpaper))) {
5827            return true;
5828        }
5829
5830        return false;
5831    }
5832
5833    public void performEnableScreen() {
5834        synchronized(mWindowMap) {
5835            if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
5836                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5837                    + " mShowingBootMessages=" + mShowingBootMessages
5838                    + " mSystemBooted=" + mSystemBooted
5839                    + " mOnlyCore=" + mOnlyCore,
5840                    new RuntimeException("here").fillInStackTrace());
5841            if (mDisplayEnabled) {
5842                return;
5843            }
5844            if (!mSystemBooted && !mShowingBootMessages) {
5845                return;
5846            }
5847
5848            // Don't enable the screen until all existing windows have been drawn.
5849            if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) {
5850                return;
5851            }
5852
5853            if (!mBootAnimationStopped) {
5854                // Do this one time.
5855                Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
5856                try {
5857                    IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5858                    if (surfaceFlinger != null) {
5859                        //Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5860                        Parcel data = Parcel.obtain();
5861                        data.writeInterfaceToken("android.ui.ISurfaceComposer");
5862                        surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5863                                data, null, 0);
5864                        data.recycle();
5865                    }
5866                } catch (RemoteException ex) {
5867                    Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");
5868                }
5869                mBootAnimationStopped = true;
5870            }
5871
5872            if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
5873                if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: Waiting for anim complete");
5874                return;
5875            }
5876
5877            EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis());
5878            Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
5879            mDisplayEnabled = true;
5880            if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, "******************** ENABLING SCREEN!");
5881
5882            // Enable input dispatch.
5883            mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5884        }
5885
5886        try {
5887            mActivityManager.bootAnimationComplete();
5888        } catch (RemoteException e) {
5889        }
5890
5891        mPolicy.enableScreenAfterBoot();
5892
5893        // Make sure the last requested orientation has been applied.
5894        updateRotationUnchecked(false, false);
5895    }
5896
5897    private boolean checkBootAnimationCompleteLocked() {
5898        if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) {
5899            mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED);
5900            mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED,
5901                    BOOT_ANIMATION_POLL_INTERVAL);
5902            if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Waiting for anim complete");
5903            return false;
5904        }
5905        if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Animation complete!");
5906        return true;
5907    }
5908
5909    public void showBootMessage(final CharSequence msg, final boolean always) {
5910        boolean first = false;
5911        synchronized(mWindowMap) {
5912            if (DEBUG_BOOT) {
5913                RuntimeException here = new RuntimeException("here");
5914                here.fillInStackTrace();
5915                Slog.i(TAG_WM, "showBootMessage: msg=" + msg + " always=" + always
5916                        + " mAllowBootMessages=" + mAllowBootMessages
5917                        + " mShowingBootMessages=" + mShowingBootMessages
5918                        + " mSystemBooted=" + mSystemBooted, here);
5919            }
5920            if (!mAllowBootMessages) {
5921                return;
5922            }
5923            if (!mShowingBootMessages) {
5924                if (!always) {
5925                    return;
5926                }
5927                first = true;
5928            }
5929            if (mSystemBooted) {
5930                return;
5931            }
5932            mShowingBootMessages = true;
5933            mPolicy.showBootMessage(msg, always);
5934        }
5935        if (first) {
5936            performEnableScreen();
5937        }
5938    }
5939
5940    public void hideBootMessagesLocked() {
5941        if (DEBUG_BOOT) {
5942            RuntimeException here = new RuntimeException("here");
5943            here.fillInStackTrace();
5944            Slog.i(TAG_WM, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
5945                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5946                    + " mShowingBootMessages=" + mShowingBootMessages
5947                    + " mSystemBooted=" + mSystemBooted, here);
5948        }
5949        if (mShowingBootMessages) {
5950            mShowingBootMessages = false;
5951            mPolicy.hideBootMessages();
5952        }
5953    }
5954
5955    @Override
5956    public void setInTouchMode(boolean mode) {
5957        synchronized(mWindowMap) {
5958            mInTouchMode = mode;
5959        }
5960    }
5961
5962    private void updateCircularDisplayMaskIfNeeded() {
5963        // we're fullscreen and not hosted in an ActivityView
5964        if (mContext.getResources().getConfiguration().isScreenRound()
5965                && mContext.getResources().getBoolean(
5966                com.android.internal.R.bool.config_windowShowCircularMask)) {
5967            final int currentUserId;
5968            synchronized(mWindowMap) {
5969                currentUserId = mCurrentUserId;
5970            }
5971            // Device configuration calls for a circular display mask, but we only enable the mask
5972            // if the accessibility color inversion feature is disabled, as the inverted mask
5973            // causes artifacts.
5974            int inversionState = Settings.Secure.getIntForUser(mContext.getContentResolver(),
5975                    Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, currentUserId);
5976            int showMask = (inversionState == 1) ? 0 : 1;
5977            Message m = mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK);
5978            m.arg1 = showMask;
5979            mH.sendMessage(m);
5980        }
5981    }
5982
5983    public void showEmulatorDisplayOverlayIfNeeded() {
5984        if (mContext.getResources().getBoolean(
5985                com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay)
5986                && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false)
5987                && Build.IS_EMULATOR) {
5988            mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY));
5989        }
5990    }
5991
5992    public void showCircularMask(boolean visible) {
5993        synchronized(mWindowMap) {
5994
5995            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
5996                    ">>> OPEN TRANSACTION showCircularMask(visible=" + visible + ")");
5997            SurfaceControl.openTransaction();
5998            try {
5999                if (visible) {
6000                    // TODO(multi-display): support multiple displays
6001                    if (mCircularDisplayMask == null) {
6002                        int screenOffset = mContext.getResources().getInteger(
6003                                com.android.internal.R.integer.config_windowOutsetBottom);
6004                        int maskThickness = mContext.getResources().getDimensionPixelSize(
6005                                com.android.internal.R.dimen.circular_display_mask_thickness);
6006
6007                        mCircularDisplayMask = new CircularDisplayMask(
6008                                getDefaultDisplayContentLocked().getDisplay(),
6009                                mFxSession,
6010                                mPolicy.windowTypeToLayerLw(
6011                                        WindowManager.LayoutParams.TYPE_POINTER)
6012                                        * TYPE_LAYER_MULTIPLIER + 10, screenOffset, maskThickness);
6013                    }
6014                    mCircularDisplayMask.setVisibility(true);
6015                } else if (mCircularDisplayMask != null) {
6016                    mCircularDisplayMask.setVisibility(false);
6017                    mCircularDisplayMask = null;
6018                }
6019            } finally {
6020                SurfaceControl.closeTransaction();
6021                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
6022                        "<<< CLOSE TRANSACTION showCircularMask(visible=" + visible + ")");
6023            }
6024        }
6025    }
6026
6027    public void showEmulatorDisplayOverlay() {
6028        synchronized(mWindowMap) {
6029
6030            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
6031                    ">>> OPEN TRANSACTION showEmulatorDisplayOverlay");
6032            SurfaceControl.openTransaction();
6033            try {
6034                if (mEmulatorDisplayOverlay == null) {
6035                    mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
6036                            mContext,
6037                            getDefaultDisplayContentLocked().getDisplay(),
6038                            mFxSession,
6039                            mPolicy.windowTypeToLayerLw(
6040                                    WindowManager.LayoutParams.TYPE_POINTER)
6041                                    * TYPE_LAYER_MULTIPLIER + 10);
6042                }
6043                mEmulatorDisplayOverlay.setVisibility(true);
6044            } finally {
6045                SurfaceControl.closeTransaction();
6046                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
6047                        "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay");
6048            }
6049        }
6050    }
6051
6052    // TODO: more accounting of which pid(s) turned it on, keep count,
6053    // only allow disables from pids which have count on, etc.
6054    @Override
6055    public void showStrictModeViolation(boolean on) {
6056        int pid = Binder.getCallingPid();
6057        mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
6058    }
6059
6060    private void showStrictModeViolation(int arg, int pid) {
6061        final boolean on = arg != 0;
6062        synchronized(mWindowMap) {
6063            // Ignoring requests to enable the red border from clients
6064            // which aren't on screen.  (e.g. Broadcast Receivers in
6065            // the background..)
6066            if (on) {
6067                boolean isVisible = false;
6068                final int numDisplays = mDisplayContents.size();
6069                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6070                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
6071                    final int numWindows = windows.size();
6072                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
6073                        final WindowState ws = windows.get(winNdx);
6074                        if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
6075                            isVisible = true;
6076                            break;
6077                        }
6078                    }
6079                }
6080                if (!isVisible) {
6081                    return;
6082                }
6083            }
6084
6085            if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
6086                    ">>> OPEN TRANSACTION showStrictModeViolation");
6087            SurfaceControl.openTransaction();
6088            try {
6089                // TODO(multi-display): support multiple displays
6090                if (mStrictModeFlash == null) {
6091                    mStrictModeFlash = new StrictModeFlash(
6092                            getDefaultDisplayContentLocked().getDisplay(), mFxSession);
6093                }
6094                mStrictModeFlash.setVisibility(on);
6095            } finally {
6096                SurfaceControl.closeTransaction();
6097                if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
6098                        "<<< CLOSE TRANSACTION showStrictModeViolation");
6099            }
6100        }
6101    }
6102
6103    @Override
6104    public void setStrictModeVisualIndicatorPreference(String value) {
6105        SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
6106    }
6107
6108    private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
6109        if (rot == Surface.ROTATION_90) {
6110            final int tmp = crop.top;
6111            crop.top = dw - crop.right;
6112            crop.right = crop.bottom;
6113            crop.bottom = dw - crop.left;
6114            crop.left = tmp;
6115        } else if (rot == Surface.ROTATION_180) {
6116            int tmp = crop.top;
6117            crop.top = dh - crop.bottom;
6118            crop.bottom = dh - tmp;
6119            tmp = crop.right;
6120            crop.right = dw - crop.left;
6121            crop.left = dw - tmp;
6122        } else if (rot == Surface.ROTATION_270) {
6123            final int tmp = crop.top;
6124            crop.top = crop.left;
6125            crop.left = dh - crop.bottom;
6126            crop.bottom = crop.right;
6127            crop.right = dh - tmp;
6128        }
6129    }
6130
6131    /**
6132     * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
6133     * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
6134     * of the target image.
6135     */
6136    @Override
6137    public boolean requestAssistScreenshot(final IAssistScreenshotReceiver receiver) {
6138        if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
6139                "requestAssistScreenshot()")) {
6140            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
6141        }
6142
6143        FgThread.getHandler().post(new Runnable() {
6144            @Override
6145            public void run() {
6146                Bitmap bm = screenshotApplicationsInner(null, Display.DEFAULT_DISPLAY, -1, -1,
6147                        true, 1f, Bitmap.Config.ARGB_8888);
6148                try {
6149                    receiver.send(bm);
6150                } catch (RemoteException e) {
6151                }
6152            }
6153        });
6154
6155        return true;
6156    }
6157
6158    /**
6159     * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
6160     * In portrait mode, it grabs the full screenshot.
6161     *
6162     * @param displayId the Display to take a screenshot of.
6163     * @param width the width of the target bitmap
6164     * @param height the height of the target bitmap
6165     * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
6166     */
6167    @Override
6168    public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height,
6169            float frameScale) {
6170        if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
6171                "screenshotApplications()")) {
6172            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
6173        }
6174        try {
6175            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotApplications");
6176            return screenshotApplicationsInner(appToken, displayId, width, height, false,
6177                    frameScale, Bitmap.Config.RGB_565);
6178        } finally {
6179            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
6180        }
6181    }
6182
6183    Bitmap screenshotApplicationsInner(IBinder appToken, int displayId, int width, int height,
6184            boolean includeFullDisplay, float frameScale, Bitmap.Config config) {
6185        final DisplayContent displayContent;
6186        synchronized(mWindowMap) {
6187            displayContent = getDisplayContentLocked(displayId);
6188            if (displayContent == null) {
6189                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
6190                        + ": returning null. No Display for displayId=" + displayId);
6191                return null;
6192            }
6193        }
6194        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6195        int dw = displayInfo.logicalWidth;
6196        int dh = displayInfo.logicalHeight;
6197        if (dw == 0 || dh == 0) {
6198            if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
6199                    + ": returning null. logical widthxheight=" + dw + "x" + dh);
6200            return null;
6201        }
6202
6203        Bitmap bm = null;
6204
6205        int maxLayer = 0;
6206        final Rect frame = new Rect();
6207        final Rect stackBounds = new Rect();
6208
6209        boolean screenshotReady;
6210        int minLayer;
6211        if (appToken == null) {
6212            screenshotReady = true;
6213            minLayer = 0;
6214        } else {
6215            screenshotReady = false;
6216            minLayer = Integer.MAX_VALUE;
6217        }
6218
6219        WindowState appWin = null;
6220
6221        boolean includeImeInScreenshot;
6222        synchronized(mWindowMap) {
6223            final AppWindowToken imeTargetAppToken =
6224                    mInputMethodTarget != null ? mInputMethodTarget.mAppToken : null;
6225            // We only include the Ime in the screenshot if the app we are screenshoting is the IME
6226            // target and isn't in multi-window mode. We don't screenshot the IME in multi-window
6227            // mode because the frame of the IME might not overlap with that of the app.
6228            // E.g. IME target app at the top in split-screen mode and the IME at the bottom
6229            // overlapping with the bottom app.
6230            includeImeInScreenshot = imeTargetAppToken != null
6231                    && imeTargetAppToken.appToken != null
6232                    && imeTargetAppToken.appToken.asBinder() == appToken
6233                    && !mInputMethodTarget.isInMultiWindowMode();
6234        }
6235
6236        final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
6237                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
6238
6239        synchronized(mWindowMap) {
6240            // Figure out the part of the screen that is actually the app.
6241            appWin = null;
6242            final WindowList windows = displayContent.getWindowList();
6243            for (int i = windows.size() - 1; i >= 0; i--) {
6244                WindowState ws = windows.get(i);
6245                if (!ws.mHasSurface) {
6246                    continue;
6247                }
6248                if (ws.mLayer >= aboveAppLayer) {
6249                    continue;
6250                }
6251                if (ws.mIsImWindow) {
6252                    if (!includeImeInScreenshot) {
6253                        continue;
6254                    }
6255                } else if (ws.mIsWallpaper) {
6256                    if (appWin == null) {
6257                        // We have not ran across the target window yet, so it is probably
6258                        // behind the wallpaper. This can happen when the keyguard is up and
6259                        // all windows are moved behind the wallpaper. We don't want to
6260                        // include the wallpaper layer in the screenshot as it will coverup
6261                        // the layer of the target window.
6262                        continue;
6263                    }
6264                    // Fall through. The target window is in front of the wallpaper. For this
6265                    // case we want to include the wallpaper layer in the screenshot because
6266                    // the target window might have some transparent areas.
6267                } else if (appToken != null) {
6268                    if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
6269                        // This app window is of no interest if it is not associated with the
6270                        // screenshot app.
6271                        continue;
6272                    }
6273                    appWin = ws;
6274                }
6275
6276                // Include this window.
6277
6278                final WindowStateAnimator winAnim = ws.mWinAnimator;
6279                int layer = winAnim.mSurfaceController.getLayer();
6280                if (maxLayer < layer) {
6281                    maxLayer = layer;
6282                }
6283                if (minLayer > layer) {
6284                    minLayer = layer;
6285                }
6286
6287                // Don't include wallpaper in bounds calculation
6288                if (!includeFullDisplay && !ws.mIsWallpaper) {
6289                    final Rect wf = ws.mFrame;
6290                    final Rect cr = ws.mContentInsets;
6291                    int left = wf.left + cr.left;
6292                    int top = wf.top + cr.top;
6293                    int right = wf.right - cr.right;
6294                    int bottom = wf.bottom - cr.bottom;
6295                    frame.union(left, top, right, bottom);
6296                    ws.getVisibleBounds(stackBounds);
6297                    if (!Rect.intersects(frame, stackBounds)) {
6298                        // Set frame empty if there's no intersection.
6299                        frame.setEmpty();
6300                    }
6301                }
6302
6303                if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
6304                        ws.isDisplayedLw() && winAnim.getShown()) {
6305                    screenshotReady = true;
6306                }
6307
6308                if (ws.isObscuringFullscreen(displayInfo)){
6309                    break;
6310                }
6311            }
6312
6313            if (appToken != null && appWin == null) {
6314                // Can't find a window to snapshot.
6315                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM,
6316                        "Screenshot: Couldn't find a surface matching " + appToken);
6317                return null;
6318            }
6319
6320            if (!screenshotReady) {
6321                Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken +
6322                        " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
6323                        appWin.mWinAnimator.mDrawState)));
6324                return null;
6325            }
6326
6327            // Screenshot is ready to be taken. Everything from here below will continue
6328            // through the bottom of the loop and return a value. We only stay in the loop
6329            // because we don't want to release the mWindowMap lock until the screenshot is
6330            // taken.
6331
6332            if (maxLayer == 0) {
6333                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
6334                        + ": returning null maxLayer=" + maxLayer);
6335                return null;
6336            }
6337
6338            if (!includeFullDisplay) {
6339                // Constrain frame to the screen size.
6340                if (!frame.intersect(0, 0, dw, dh)) {
6341                    frame.setEmpty();
6342                }
6343            } else {
6344                // Caller just wants entire display.
6345                frame.set(0, 0, dw, dh);
6346            }
6347            if (frame.isEmpty()) {
6348                return null;
6349            }
6350
6351            if (width < 0) {
6352                width = (int) (frame.width() * frameScale);
6353            }
6354            if (height < 0) {
6355                height = (int) (frame.height() * frameScale);
6356            }
6357
6358            // Tell surface flinger what part of the image to crop. Take the top
6359            // right part of the application, and crop the larger dimension to fit.
6360            Rect crop = new Rect(frame);
6361            if (width / (float) frame.width() < height / (float) frame.height()) {
6362                int cropWidth = (int)((float)width / (float)height * frame.height());
6363                crop.right = crop.left + cropWidth;
6364            } else {
6365                int cropHeight = (int)((float)height / (float)width * frame.width());
6366                crop.bottom = crop.top + cropHeight;
6367            }
6368
6369            // The screenshot API does not apply the current screen rotation.
6370            int rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
6371
6372            if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
6373                rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
6374            }
6375
6376            // Surfaceflinger is not aware of orientation, so convert our logical
6377            // crop to surfaceflinger's portrait orientation.
6378            convertCropForSurfaceFlinger(crop, rot, dw, dh);
6379
6380            if (DEBUG_SCREENSHOT) {
6381                Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
6382                        + maxLayer + " appToken=" + appToken);
6383                for (int i = 0; i < windows.size(); i++) {
6384                    WindowState win = windows.get(i);
6385                    WindowSurfaceController controller = win.mWinAnimator.mSurfaceController;
6386                    Slog.i(TAG_WM, win + ": " + win.mLayer
6387                            + " animLayer=" + win.mWinAnimator.mAnimLayer
6388                            + " surfaceLayer=" + ((controller == null)
6389                                ? "null" : controller.getLayer()));
6390                }
6391            }
6392
6393            ScreenRotationAnimation screenRotationAnimation =
6394                    mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6395            final boolean inRotation = screenRotationAnimation != null &&
6396                    screenRotationAnimation.isAnimating();
6397            if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM,
6398                    "Taking screenshot while rotating");
6399
6400            // We force pending transactions to flush before taking
6401            // the screenshot by pushing an empty synchronous transaction.
6402            SurfaceControl.openTransaction();
6403            SurfaceControl.closeTransactionSync();
6404
6405            bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
6406                    inRotation, rot);
6407            if (bm == null) {
6408                Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh
6409                        + ") to layer " + maxLayer);
6410                return null;
6411            }
6412        }
6413
6414        if (DEBUG_SCREENSHOT) {
6415            // TEST IF IT's ALL BLACK
6416            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
6417            bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
6418            boolean allBlack = true;
6419            final int firstColor = buffer[0];
6420            for (int i = 0; i < buffer.length; i++) {
6421                if (buffer[i] != firstColor) {
6422                    allBlack = false;
6423                    break;
6424                }
6425            }
6426            if (allBlack) {
6427                Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" +
6428                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
6429                        (appWin != null ?
6430                                appWin.mWinAnimator.mSurfaceController.getLayer() : "null") +
6431                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
6432            }
6433        }
6434
6435        // Create a copy of the screenshot that is immutable and backed in ashmem.
6436        // This greatly reduces the overhead of passing the bitmap between processes.
6437        Bitmap ret = bm.createAshmemBitmap(config);
6438        bm.recycle();
6439        return ret;
6440    }
6441
6442    /**
6443     * Freeze rotation changes.  (Enable "rotation lock".)
6444     * Persists across reboots.
6445     * @param rotation The desired rotation to freeze to, or -1 to use the
6446     * current rotation.
6447     */
6448    @Override
6449    public void freezeRotation(int rotation) {
6450        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
6451                "freezeRotation()")) {
6452            throw new SecurityException("Requires SET_ORIENTATION permission");
6453        }
6454        if (rotation < -1 || rotation > Surface.ROTATION_270) {
6455            throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
6456                    + "rotation constant.");
6457        }
6458
6459        if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "freezeRotation: mRotation=" + mRotation);
6460
6461        long origId = Binder.clearCallingIdentity();
6462        try {
6463            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
6464                    rotation == -1 ? mRotation : rotation);
6465        } finally {
6466            Binder.restoreCallingIdentity(origId);
6467        }
6468
6469        updateRotationUnchecked(false, false);
6470    }
6471
6472    /**
6473     * Thaw rotation changes.  (Disable "rotation lock".)
6474     * Persists across reboots.
6475     */
6476    @Override
6477    public void thawRotation() {
6478        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
6479                "thawRotation()")) {
6480            throw new SecurityException("Requires SET_ORIENTATION permission");
6481        }
6482
6483        if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "thawRotation: mRotation=" + mRotation);
6484
6485        long origId = Binder.clearCallingIdentity();
6486        try {
6487            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
6488                    777); // rot not used
6489        } finally {
6490            Binder.restoreCallingIdentity(origId);
6491        }
6492
6493        updateRotationUnchecked(false, false);
6494    }
6495
6496    /**
6497     * Recalculate the current rotation.
6498     *
6499     * Called by the window manager policy whenever the state of the system changes
6500     * such that the current rotation might need to be updated, such as when the
6501     * device is docked or rotated into a new posture.
6502     */
6503    @Override
6504    public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
6505        updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
6506    }
6507
6508    /**
6509     * Temporarily pauses rotation changes until resumed.
6510     *
6511     * This can be used to prevent rotation changes from occurring while the user is
6512     * performing certain operations, such as drag and drop.
6513     *
6514     * This call nests and must be matched by an equal number of calls to
6515     * {@link #resumeRotationLocked}.
6516     */
6517    void pauseRotationLocked() {
6518        mDeferredRotationPauseCount += 1;
6519    }
6520
6521    /**
6522     * Resumes normal rotation changes after being paused.
6523     */
6524    void resumeRotationLocked() {
6525        if (mDeferredRotationPauseCount > 0) {
6526            mDeferredRotationPauseCount -= 1;
6527            if (mDeferredRotationPauseCount == 0) {
6528                boolean changed = updateRotationUncheckedLocked(false);
6529                if (changed) {
6530                    mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6531                }
6532            }
6533        }
6534    }
6535
6536    public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
6537        if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked("
6538                   + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
6539
6540        long origId = Binder.clearCallingIdentity();
6541        boolean changed;
6542        synchronized(mWindowMap) {
6543            changed = updateRotationUncheckedLocked(false);
6544            if (!changed || forceRelayout) {
6545                getDefaultDisplayContentLocked().layoutNeeded = true;
6546                mWindowPlacerLocked.performSurfacePlacement();
6547            }
6548        }
6549
6550        if (changed || alwaysSendConfiguration) {
6551            sendNewConfiguration();
6552        }
6553
6554        Binder.restoreCallingIdentity(origId);
6555    }
6556
6557    // TODO(multidisplay): Rotate any display?
6558    /**
6559     * Updates the current rotation.
6560     *
6561     * Returns true if the rotation has been changed.  In this case YOU
6562     * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
6563     */
6564    public boolean updateRotationUncheckedLocked(boolean inTransaction) {
6565        if (mDeferredRotationPauseCount > 0) {
6566            // Rotation updates have been paused temporarily.  Defer the update until
6567            // updates have been resumed.
6568            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");
6569            return false;
6570        }
6571
6572        ScreenRotationAnimation screenRotationAnimation =
6573                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6574        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
6575            // Rotation updates cannot be performed while the previous rotation change
6576            // animation is still in progress.  Skip this update.  We will try updating
6577            // again after the animation is finished and the display is unfrozen.
6578            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");
6579            return false;
6580        }
6581
6582        if (!mDisplayEnabled) {
6583            // No point choosing a rotation if the display is not enabled.
6584            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled.");
6585            return false;
6586        }
6587
6588        // TODO: Implement forced rotation changes.
6589        //       Set mAltOrientation to indicate that the application is receiving
6590        //       an orientation that has different metrics than it expected.
6591        //       eg. Portrait instead of Landscape.
6592
6593        int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
6594        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
6595                mForcedAppOrientation, rotation);
6596
6597        if (DEBUG_ORIENTATION) {
6598            Slog.v(TAG_WM, "Application requested orientation "
6599                    + mForcedAppOrientation + ", got rotation " + rotation
6600                    + " which has " + (altOrientation ? "incompatible" : "compatible")
6601                    + " metrics");
6602        }
6603
6604        if (mRotation == rotation && mAltOrientation == altOrientation) {
6605            // No change.
6606            return false;
6607        }
6608
6609        if (DEBUG_ORIENTATION) {
6610            Slog.v(TAG_WM,
6611                "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
6612                + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
6613                + ", forceApp=" + mForcedAppOrientation);
6614        }
6615
6616        mRotation = rotation;
6617        mAltOrientation = altOrientation;
6618        mPolicy.setRotationLw(mRotation);
6619
6620        mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
6621        mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
6622        mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
6623        mWaitingForConfig = true;
6624        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6625        displayContent.layoutNeeded = true;
6626        final int[] anim = new int[2];
6627        if (displayContent.isDimming()) {
6628            anim[0] = anim[1] = 0;
6629        } else {
6630            mPolicy.selectRotationAnimationLw(anim);
6631        }
6632        startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
6633        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
6634        screenRotationAnimation =
6635                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6636
6637        // We need to update our screen size information to match the new rotation. If the rotation
6638        // has actually changed then this method will return true and, according to the comment at
6639        // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
6640        // By updating the Display info here it will be available to
6641        // computeScreenConfigurationLocked later.
6642        updateDisplayAndOrientationLocked(mCurConfiguration.uiMode);
6643
6644        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6645        if (!inTransaction) {
6646            if (SHOW_TRANSACTIONS) {
6647                Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked");
6648            }
6649            SurfaceControl.openTransaction();
6650        }
6651        try {
6652            // NOTE: We disable the rotation in the emulator because
6653            //       it doesn't support hardware OpenGL emulation yet.
6654            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
6655                    && screenRotationAnimation.hasScreenshot()) {
6656                if (screenRotationAnimation.setRotationInTransaction(
6657                        rotation, mFxSession,
6658                        MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(),
6659                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
6660                    scheduleAnimationLocked();
6661                }
6662            }
6663
6664            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
6665        } finally {
6666            if (!inTransaction) {
6667                SurfaceControl.closeTransaction();
6668                if (SHOW_LIGHT_TRANSACTIONS) {
6669                    Slog.i(TAG_WM, "<<< CLOSE TRANSACTION setRotationUnchecked");
6670                }
6671            }
6672        }
6673
6674        final WindowList windows = displayContent.getWindowList();
6675        for (int i = windows.size() - 1; i >= 0; i--) {
6676            WindowState w = windows.get(i);
6677            // Discard surface after orientation change, these can't be reused.
6678            if (w.mAppToken != null) {
6679                w.mAppToken.destroySavedSurfaces();
6680            }
6681            if (w.mHasSurface) {
6682                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
6683                w.mOrientationChanging = true;
6684                mWindowPlacerLocked.mOrientationChangeComplete = false;
6685            }
6686            w.mLastFreezeDuration = 0;
6687        }
6688
6689        for (int i=mRotationWatchers.size()-1; i>=0; i--) {
6690            try {
6691                mRotationWatchers.get(i).watcher.onRotationChanged(rotation);
6692            } catch (RemoteException e) {
6693            }
6694        }
6695
6696        //TODO (multidisplay): Magnification is supported only for the default display.
6697        // Announce rotation only if we will not animate as we already have the
6698        // windows in final state. Otherwise, we make this call at the rotation end.
6699        if (screenRotationAnimation == null && mAccessibilityController != null
6700                && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
6701            mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(),
6702                    rotation);
6703        }
6704
6705        return true;
6706    }
6707
6708    @Override
6709    public int getRotation() {
6710        return mRotation;
6711    }
6712
6713    @Override
6714    public boolean isRotationFrozen() {
6715        return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6716    }
6717
6718    @Override
6719    public int watchRotation(IRotationWatcher watcher) {
6720        final IBinder watcherBinder = watcher.asBinder();
6721        IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6722            @Override
6723            public void binderDied() {
6724                synchronized (mWindowMap) {
6725                    for (int i=0; i<mRotationWatchers.size(); i++) {
6726                        if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) {
6727                            RotationWatcher removed = mRotationWatchers.remove(i);
6728                            IBinder binder = removed.watcher.asBinder();
6729                            if (binder != null) {
6730                                binder.unlinkToDeath(this, 0);
6731                            }
6732                            i--;
6733                        }
6734                    }
6735                }
6736            }
6737        };
6738
6739        synchronized (mWindowMap) {
6740            try {
6741                watcher.asBinder().linkToDeath(dr, 0);
6742                mRotationWatchers.add(new RotationWatcher(watcher, dr));
6743            } catch (RemoteException e) {
6744                // Client died, no cleanup needed.
6745            }
6746
6747            return mRotation;
6748        }
6749    }
6750
6751    @Override
6752    public void removeRotationWatcher(IRotationWatcher watcher) {
6753        final IBinder watcherBinder = watcher.asBinder();
6754        synchronized (mWindowMap) {
6755            for (int i=0; i<mRotationWatchers.size(); i++) {
6756                RotationWatcher rotationWatcher = mRotationWatchers.get(i);
6757                if (watcherBinder == rotationWatcher.watcher.asBinder()) {
6758                    RotationWatcher removed = mRotationWatchers.remove(i);
6759                    IBinder binder = removed.watcher.asBinder();
6760                    if (binder != null) {
6761                        binder.unlinkToDeath(removed.deathRecipient, 0);
6762                    }
6763                    i--;
6764                }
6765            }
6766        }
6767    }
6768
6769    /**
6770     * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6771     * theme attribute) on devices that feature a physical options menu key attempt to position
6772     * their menu panel window along the edge of the screen nearest the physical menu key.
6773     * This lowers the travel distance between invoking the menu panel and selecting
6774     * a menu option.
6775     *
6776     * This method helps control where that menu is placed. Its current implementation makes
6777     * assumptions about the menu key and its relationship to the screen based on whether
6778     * the device's natural orientation is portrait (width < height) or landscape.
6779     *
6780     * The menu key is assumed to be located along the bottom edge of natural-portrait
6781     * devices and along the right edge of natural-landscape devices. If these assumptions
6782     * do not hold for the target device, this method should be changed to reflect that.
6783     *
6784     * @return A {@link Gravity} value for placing the options menu window
6785     */
6786    @Override
6787    public int getPreferredOptionsPanelGravity() {
6788        synchronized (mWindowMap) {
6789            final int rotation = getRotation();
6790
6791            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6792            final DisplayContent displayContent = getDefaultDisplayContentLocked();
6793            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6794                // On devices with a natural orientation of portrait
6795                switch (rotation) {
6796                    default:
6797                    case Surface.ROTATION_0:
6798                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6799                    case Surface.ROTATION_90:
6800                        return Gravity.RIGHT | Gravity.BOTTOM;
6801                    case Surface.ROTATION_180:
6802                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6803                    case Surface.ROTATION_270:
6804                        return Gravity.START | Gravity.BOTTOM;
6805                }
6806            }
6807
6808            // On devices with a natural orientation of landscape
6809            switch (rotation) {
6810                default:
6811                case Surface.ROTATION_0:
6812                    return Gravity.RIGHT | Gravity.BOTTOM;
6813                case Surface.ROTATION_90:
6814                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6815                case Surface.ROTATION_180:
6816                    return Gravity.START | Gravity.BOTTOM;
6817                case Surface.ROTATION_270:
6818                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6819            }
6820        }
6821    }
6822
6823    /**
6824     * Starts the view server on the specified port.
6825     *
6826     * @param port The port to listener to.
6827     *
6828     * @return True if the server was successfully started, false otherwise.
6829     *
6830     * @see com.android.server.wm.ViewServer
6831     * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
6832     */
6833    @Override
6834    public boolean startViewServer(int port) {
6835        if (isSystemSecure()) {
6836            return false;
6837        }
6838
6839        if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
6840            return false;
6841        }
6842
6843        if (port < 1024) {
6844            return false;
6845        }
6846
6847        if (mViewServer != null) {
6848            if (!mViewServer.isRunning()) {
6849                try {
6850                    return mViewServer.start();
6851                } catch (IOException e) {
6852                    Slog.w(TAG_WM, "View server did not start");
6853                }
6854            }
6855            return false;
6856        }
6857
6858        try {
6859            mViewServer = new ViewServer(this, port);
6860            return mViewServer.start();
6861        } catch (IOException e) {
6862            Slog.w(TAG_WM, "View server did not start");
6863        }
6864        return false;
6865    }
6866
6867    private boolean isSystemSecure() {
6868        return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
6869                "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6870    }
6871
6872    /**
6873     * Stops the view server if it exists.
6874     *
6875     * @return True if the server stopped, false if it wasn't started or
6876     *         couldn't be stopped.
6877     *
6878     * @see com.android.server.wm.ViewServer
6879     */
6880    @Override
6881    public boolean stopViewServer() {
6882        if (isSystemSecure()) {
6883            return false;
6884        }
6885
6886        if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
6887            return false;
6888        }
6889
6890        if (mViewServer != null) {
6891            return mViewServer.stop();
6892        }
6893        return false;
6894    }
6895
6896    /**
6897     * Indicates whether the view server is running.
6898     *
6899     * @return True if the server is running, false otherwise.
6900     *
6901     * @see com.android.server.wm.ViewServer
6902     */
6903    @Override
6904    public boolean isViewServerRunning() {
6905        if (isSystemSecure()) {
6906            return false;
6907        }
6908
6909        if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
6910            return false;
6911        }
6912
6913        return mViewServer != null && mViewServer.isRunning();
6914    }
6915
6916    /**
6917     * Lists all availble windows in the system. The listing is written in the
6918     * specified Socket's output stream with the following syntax:
6919     * windowHashCodeInHexadecimal windowName
6920     * Each line of the ouput represents a different window.
6921     *
6922     * @param client The remote client to send the listing to.
6923     * @return False if an error occured, true otherwise.
6924     */
6925    boolean viewServerListWindows(Socket client) {
6926        if (isSystemSecure()) {
6927            return false;
6928        }
6929
6930        boolean result = true;
6931
6932        WindowList windows = new WindowList();
6933        synchronized (mWindowMap) {
6934            //noinspection unchecked
6935            final int numDisplays = mDisplayContents.size();
6936            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6937                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
6938                windows.addAll(displayContent.getWindowList());
6939            }
6940        }
6941
6942        BufferedWriter out = null;
6943
6944        // Any uncaught exception will crash the system process
6945        try {
6946            OutputStream clientStream = client.getOutputStream();
6947            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6948
6949            final int count = windows.size();
6950            for (int i = 0; i < count; i++) {
6951                final WindowState w = windows.get(i);
6952                out.write(Integer.toHexString(System.identityHashCode(w)));
6953                out.write(' ');
6954                out.append(w.mAttrs.getTitle());
6955                out.write('\n');
6956            }
6957
6958            out.write("DONE.\n");
6959            out.flush();
6960        } catch (Exception e) {
6961            result = false;
6962        } finally {
6963            if (out != null) {
6964                try {
6965                    out.close();
6966                } catch (IOException e) {
6967                    result = false;
6968                }
6969            }
6970        }
6971
6972        return result;
6973    }
6974
6975    // TODO(multidisplay): Extend to multiple displays.
6976    /**
6977     * Returns the focused window in the following format:
6978     * windowHashCodeInHexadecimal windowName
6979     *
6980     * @param client The remote client to send the listing to.
6981     * @return False if an error occurred, true otherwise.
6982     */
6983    boolean viewServerGetFocusedWindow(Socket client) {
6984        if (isSystemSecure()) {
6985            return false;
6986        }
6987
6988        boolean result = true;
6989
6990        WindowState focusedWindow = getFocusedWindow();
6991
6992        BufferedWriter out = null;
6993
6994        // Any uncaught exception will crash the system process
6995        try {
6996            OutputStream clientStream = client.getOutputStream();
6997            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6998
6999            if(focusedWindow != null) {
7000                out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
7001                out.write(' ');
7002                out.append(focusedWindow.mAttrs.getTitle());
7003            }
7004            out.write('\n');
7005            out.flush();
7006        } catch (Exception e) {
7007            result = false;
7008        } finally {
7009            if (out != null) {
7010                try {
7011                    out.close();
7012                } catch (IOException e) {
7013                    result = false;
7014                }
7015            }
7016        }
7017
7018        return result;
7019    }
7020
7021    /**
7022     * Sends a command to a target window. The result of the command, if any, will be
7023     * written in the output stream of the specified socket.
7024     *
7025     * The parameters must follow this syntax:
7026     * windowHashcode extra
7027     *
7028     * Where XX is the length in characeters of the windowTitle.
7029     *
7030     * The first parameter is the target window. The window with the specified hashcode
7031     * will be the target. If no target can be found, nothing happens. The extra parameters
7032     * will be delivered to the target window and as parameters to the command itself.
7033     *
7034     * @param client The remote client to sent the result, if any, to.
7035     * @param command The command to execute.
7036     * @param parameters The command parameters.
7037     *
7038     * @return True if the command was successfully delivered, false otherwise. This does
7039     *         not indicate whether the command itself was successful.
7040     */
7041    boolean viewServerWindowCommand(Socket client, String command, String parameters) {
7042        if (isSystemSecure()) {
7043            return false;
7044        }
7045
7046        boolean success = true;
7047        Parcel data = null;
7048        Parcel reply = null;
7049
7050        BufferedWriter out = null;
7051
7052        // Any uncaught exception will crash the system process
7053        try {
7054            // Find the hashcode of the window
7055            int index = parameters.indexOf(' ');
7056            if (index == -1) {
7057                index = parameters.length();
7058            }
7059            final String code = parameters.substring(0, index);
7060            int hashCode = (int) Long.parseLong(code, 16);
7061
7062            // Extract the command's parameter after the window description
7063            if (index < parameters.length()) {
7064                parameters = parameters.substring(index + 1);
7065            } else {
7066                parameters = "";
7067            }
7068
7069            final WindowState window = findWindow(hashCode);
7070            if (window == null) {
7071                return false;
7072            }
7073
7074            data = Parcel.obtain();
7075            data.writeInterfaceToken("android.view.IWindow");
7076            data.writeString(command);
7077            data.writeString(parameters);
7078            data.writeInt(1);
7079            ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
7080
7081            reply = Parcel.obtain();
7082
7083            final IBinder binder = window.mClient.asBinder();
7084            // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
7085            binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
7086
7087            reply.readException();
7088
7089            if (!client.isOutputShutdown()) {
7090                out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
7091                out.write("DONE\n");
7092                out.flush();
7093            }
7094
7095        } catch (Exception e) {
7096            Slog.w(TAG_WM, "Could not send command " + command + " with parameters " + parameters, e);
7097            success = false;
7098        } finally {
7099            if (data != null) {
7100                data.recycle();
7101            }
7102            if (reply != null) {
7103                reply.recycle();
7104            }
7105            if (out != null) {
7106                try {
7107                    out.close();
7108                } catch (IOException e) {
7109
7110                }
7111            }
7112        }
7113
7114        return success;
7115    }
7116
7117    public void addWindowChangeListener(WindowChangeListener listener) {
7118        synchronized(mWindowMap) {
7119            mWindowChangeListeners.add(listener);
7120        }
7121    }
7122
7123    public void removeWindowChangeListener(WindowChangeListener listener) {
7124        synchronized(mWindowMap) {
7125            mWindowChangeListeners.remove(listener);
7126        }
7127    }
7128
7129    private void notifyWindowsChanged() {
7130        WindowChangeListener[] windowChangeListeners;
7131        synchronized(mWindowMap) {
7132            if(mWindowChangeListeners.isEmpty()) {
7133                return;
7134            }
7135            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
7136            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
7137        }
7138        int N = windowChangeListeners.length;
7139        for(int i = 0; i < N; i++) {
7140            windowChangeListeners[i].windowsChanged();
7141        }
7142    }
7143
7144    private void notifyFocusChanged() {
7145        WindowChangeListener[] windowChangeListeners;
7146        synchronized(mWindowMap) {
7147            if(mWindowChangeListeners.isEmpty()) {
7148                return;
7149            }
7150            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
7151            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
7152        }
7153        int N = windowChangeListeners.length;
7154        for(int i = 0; i < N; i++) {
7155            windowChangeListeners[i].focusChanged();
7156        }
7157    }
7158
7159    private WindowState findWindow(int hashCode) {
7160        if (hashCode == -1) {
7161            // TODO(multidisplay): Extend to multiple displays.
7162            return getFocusedWindow();
7163        }
7164
7165        synchronized (mWindowMap) {
7166            final int numDisplays = mDisplayContents.size();
7167            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
7168                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
7169                final int numWindows = windows.size();
7170                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
7171                    final WindowState w = windows.get(winNdx);
7172                    if (System.identityHashCode(w) == hashCode) {
7173                        return w;
7174                    }
7175                }
7176            }
7177        }
7178
7179        return null;
7180    }
7181
7182    /*
7183     * Instruct the Activity Manager to fetch the current configuration and broadcast
7184     * that to config-changed listeners if appropriate.
7185     */
7186    void sendNewConfiguration() {
7187        try {
7188            mActivityManager.updateConfiguration(null);
7189        } catch (RemoteException e) {
7190        }
7191    }
7192
7193    public Configuration computeNewConfiguration() {
7194        synchronized (mWindowMap) {
7195            return computeNewConfigurationLocked();
7196        }
7197    }
7198
7199    private Configuration computeNewConfigurationLocked() {
7200        if (!mDisplayReady) {
7201            return null;
7202        }
7203        Configuration config = new Configuration();
7204        config.fontScale = 0;
7205        computeScreenConfigurationLocked(config);
7206        return config;
7207    }
7208
7209    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int uiMode,
7210            int dw, int dh) {
7211        // TODO: Multidisplay: for now only use with default display.
7212        final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode);
7213        if (width < displayInfo.smallestNominalAppWidth) {
7214            displayInfo.smallestNominalAppWidth = width;
7215        }
7216        if (width > displayInfo.largestNominalAppWidth) {
7217            displayInfo.largestNominalAppWidth = width;
7218        }
7219        final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode);
7220        if (height < displayInfo.smallestNominalAppHeight) {
7221            displayInfo.smallestNominalAppHeight = height;
7222        }
7223        if (height > displayInfo.largestNominalAppHeight) {
7224            displayInfo.largestNominalAppHeight = height;
7225        }
7226    }
7227
7228    private int reduceConfigLayout(int curLayout, int rotation, float density,
7229            int dw, int dh, int uiMode) {
7230        // TODO: Multidisplay: for now only use with default display.
7231        // Get the app screen size at this rotation.
7232        int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode);
7233        int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode);
7234
7235        // Compute the screen layout size class for this rotation.
7236        int longSize = w;
7237        int shortSize = h;
7238        if (longSize < shortSize) {
7239            int tmp = longSize;
7240            longSize = shortSize;
7241            shortSize = tmp;
7242        }
7243        longSize = (int)(longSize/density);
7244        shortSize = (int)(shortSize/density);
7245        return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
7246    }
7247
7248    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
7249                  int uiMode, int dw, int dh, float density, Configuration outConfig) {
7250        // TODO: Multidisplay: for now only use with default display.
7251
7252        // We need to determine the smallest width that will occur under normal
7253        // operation.  To this, start with the base screen size and compute the
7254        // width under the different possible rotations.  We need to un-rotate
7255        // the current screen dimensions before doing this.
7256        int unrotDw, unrotDh;
7257        if (rotated) {
7258            unrotDw = dh;
7259            unrotDh = dw;
7260        } else {
7261            unrotDw = dw;
7262            unrotDh = dh;
7263        }
7264        displayInfo.smallestNominalAppWidth = 1<<30;
7265        displayInfo.smallestNominalAppHeight = 1<<30;
7266        displayInfo.largestNominalAppWidth = 0;
7267        displayInfo.largestNominalAppHeight = 0;
7268        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, uiMode, unrotDw, unrotDh);
7269        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, uiMode, unrotDh, unrotDw);
7270        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, uiMode, unrotDw, unrotDh);
7271        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, uiMode, unrotDh, unrotDw);
7272        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
7273        sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode);
7274        sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode);
7275        sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode);
7276        sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode);
7277        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
7278        outConfig.screenLayout = sl;
7279    }
7280
7281    private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
7282            DisplayMetrics dm, int dw, int dh) {
7283        // TODO: Multidisplay: for now only use with default display.
7284        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode);
7285        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode);
7286        float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
7287        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
7288        if (curSize == 0 || size < curSize) {
7289            curSize = size;
7290        }
7291        return curSize;
7292    }
7293
7294    private int computeCompatSmallestWidth(boolean rotated, int uiMode, DisplayMetrics dm, int dw, int dh) {
7295        // TODO: Multidisplay: for now only use with default display.
7296        mTmpDisplayMetrics.setTo(dm);
7297        final DisplayMetrics tmpDm = mTmpDisplayMetrics;
7298        final int unrotDw, unrotDh;
7299        if (rotated) {
7300            unrotDw = dh;
7301            unrotDh = dw;
7302        } else {
7303            unrotDw = dw;
7304            unrotDh = dh;
7305        }
7306        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh);
7307        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw);
7308        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh);
7309        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw);
7310        return sw;
7311    }
7312
7313    /** Do not call if mDisplayReady == false */
7314    DisplayInfo updateDisplayAndOrientationLocked(int uiMode) {
7315        // TODO(multidisplay): For now, apply Configuration to main screen only.
7316        final DisplayContent displayContent = getDefaultDisplayContentLocked();
7317
7318        // Use the effective "visual" dimensions based on current rotation
7319        final boolean rotated = (mRotation == Surface.ROTATION_90
7320                || mRotation == Surface.ROTATION_270);
7321        final int realdw = rotated ?
7322                displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
7323        final int realdh = rotated ?
7324                displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
7325        int dw = realdw;
7326        int dh = realdh;
7327
7328        if (mAltOrientation) {
7329            if (realdw > realdh) {
7330                // Turn landscape into portrait.
7331                int maxw = (int)(realdh/1.3f);
7332                if (maxw < realdw) {
7333                    dw = maxw;
7334                }
7335            } else {
7336                // Turn portrait into landscape.
7337                int maxh = (int)(realdw/1.3f);
7338                if (maxh < realdh) {
7339                    dh = maxh;
7340                }
7341            }
7342        }
7343
7344        // Update application display metrics.
7345        final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode);
7346        final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode);
7347        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7348        displayInfo.rotation = mRotation;
7349        displayInfo.logicalWidth = dw;
7350        displayInfo.logicalHeight = dh;
7351        displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
7352        displayInfo.appWidth = appWidth;
7353        displayInfo.appHeight = appHeight;
7354        displayInfo.getLogicalMetrics(mRealDisplayMetrics,
7355                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
7356        displayInfo.getAppMetrics(mDisplayMetrics);
7357        if (displayContent.mDisplayScalingDisabled) {
7358            displayInfo.flags |= Display.FLAG_SCALING_DISABLED;
7359        } else {
7360            displayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
7361        }
7362
7363        mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
7364                displayContent.getDisplayId(), displayInfo);
7365
7366        displayContent.mBaseDisplayRect.set(0, 0, dw, dh);
7367        if (false) {
7368            Slog.i(TAG_WM, "Set app display size: " + appWidth + " x " + appHeight);
7369        }
7370
7371        mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
7372                mCompatDisplayMetrics);
7373        return displayInfo;
7374    }
7375
7376    /** Do not call if mDisplayReady == false */
7377    void computeScreenConfigurationLocked(Configuration config) {
7378        final DisplayInfo displayInfo = updateDisplayAndOrientationLocked(
7379                config.uiMode);
7380
7381        final int dw = displayInfo.logicalWidth;
7382        final int dh = displayInfo.logicalHeight;
7383        config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
7384                Configuration.ORIENTATION_LANDSCAPE;
7385        config.screenWidthDp =
7386                (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation, config.uiMode) /
7387                        mDisplayMetrics.density);
7388        config.screenHeightDp =
7389                (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation, config.uiMode) /
7390                        mDisplayMetrics.density);
7391        final boolean rotated = (mRotation == Surface.ROTATION_90
7392                || mRotation == Surface.ROTATION_270);
7393
7394        computeSizeRangesAndScreenLayout(displayInfo, rotated, config.uiMode, dw, dh,
7395                mDisplayMetrics.density, config);
7396
7397        config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK)
7398                | ((displayInfo.flags & Display.FLAG_ROUND) != 0
7399                        ? Configuration.SCREENLAYOUT_ROUND_YES
7400                        : Configuration.SCREENLAYOUT_ROUND_NO);
7401
7402        config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
7403        config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
7404        config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode,
7405                mDisplayMetrics, dw, dh);
7406        config.densityDpi = displayInfo.logicalDensityDpi;
7407
7408        // Update the configuration based on available input devices, lid switch,
7409        // and platform configuration.
7410        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
7411        config.keyboard = Configuration.KEYBOARD_NOKEYS;
7412        config.navigation = Configuration.NAVIGATION_NONAV;
7413
7414        int keyboardPresence = 0;
7415        int navigationPresence = 0;
7416        final InputDevice[] devices = mInputManager.getInputDevices();
7417        final int len = devices.length;
7418        for (int i = 0; i < len; i++) {
7419            InputDevice device = devices[i];
7420            if (!device.isVirtual()) {
7421                final int sources = device.getSources();
7422                final int presenceFlag = device.isExternal() ?
7423                        WindowManagerPolicy.PRESENCE_EXTERNAL :
7424                                WindowManagerPolicy.PRESENCE_INTERNAL;
7425
7426                if (mIsTouchDevice) {
7427                    if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
7428                            InputDevice.SOURCE_TOUCHSCREEN) {
7429                        config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
7430                    }
7431                } else {
7432                    config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
7433                }
7434
7435                if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
7436                    config.navigation = Configuration.NAVIGATION_TRACKBALL;
7437                    navigationPresence |= presenceFlag;
7438                } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
7439                        && config.navigation == Configuration.NAVIGATION_NONAV) {
7440                    config.navigation = Configuration.NAVIGATION_DPAD;
7441                    navigationPresence |= presenceFlag;
7442                }
7443
7444                if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
7445                    config.keyboard = Configuration.KEYBOARD_QWERTY;
7446                    keyboardPresence |= presenceFlag;
7447                }
7448            }
7449        }
7450
7451        if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) {
7452            config.navigation = Configuration.NAVIGATION_DPAD;
7453            navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
7454        }
7455
7456        // Determine whether a hard keyboard is available and enabled.
7457        boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
7458        if (hardKeyboardAvailable != mHardKeyboardAvailable) {
7459            mHardKeyboardAvailable = hardKeyboardAvailable;
7460            mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
7461            mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
7462        }
7463
7464        // Let the policy update hidden states.
7465        config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
7466        config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
7467        config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
7468        mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
7469    }
7470
7471    void notifyHardKeyboardStatusChange() {
7472        final boolean available;
7473        final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener;
7474        synchronized (mWindowMap) {
7475            listener = mHardKeyboardStatusChangeListener;
7476            available = mHardKeyboardAvailable;
7477        }
7478        if (listener != null) {
7479            listener.onHardKeyboardStatusChange(available);
7480        }
7481    }
7482
7483    boolean startMovingTask(IWindow window, float startX, float startY) {
7484        WindowState win = null;
7485        synchronized (mWindowMap) {
7486            win = windowForClientLocked(null, window, false);
7487            // win shouldn't be null here, pass it down to startPositioningLocked
7488            // to get warning if it's null.
7489            if (!startPositioningLocked(win, false /*resize*/, startX, startY)) {
7490                return false;
7491            }
7492        }
7493        try {
7494            mActivityManager.setFocusedTask(win.getTask().mTaskId);
7495        } catch(RemoteException e) {}
7496        return true;
7497    }
7498
7499    private void startScrollingTask(DisplayContent displayContent, int startX, int startY) {
7500        if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM,
7501                "startScrollingTask: " + "{" + startX + ", " + startY + "}");
7502
7503        Task task = null;
7504        synchronized (mWindowMap) {
7505            int taskId = displayContent.taskIdFromPoint(startX, startY);
7506            if (taskId >= 0) {
7507                task = mTaskIdToTask.get(taskId);
7508            }
7509            if (task == null || !task.isDockedInEffect() || !startPositioningLocked(
7510                    task.getTopVisibleAppMainWindow(), false /*resize*/, startX, startY)) {
7511                return;
7512            }
7513        }
7514        try {
7515            mActivityManager.setFocusedTask(task.mTaskId);
7516        } catch(RemoteException e) {}
7517    }
7518
7519    private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
7520        int taskId = -1;
7521        synchronized (mWindowMap) {
7522            final Task task = displayContent.findTaskForControlPoint(x, y);
7523            if (task != null) {
7524                if (!startPositioningLocked(
7525                        task.getTopVisibleAppMainWindow(), true /*resize*/, x, y)) {
7526                    return;
7527                }
7528                taskId = task.mTaskId;
7529            } else {
7530                taskId = displayContent.taskIdFromPoint(x, y);
7531            }
7532        }
7533        if (taskId >= 0) {
7534            try {
7535                mActivityManager.setFocusedTask(taskId);
7536            } catch(RemoteException e) {}
7537        }
7538    }
7539
7540    private boolean startPositioningLocked(
7541            WindowState win, boolean resize, float startX, float startY) {
7542        if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "startPositioningLocked: "
7543            + "win=" + win + ", resize=" + resize + ", {" + startX + ", " + startY + "}");
7544
7545        if (win == null || win.getAppToken() == null) {
7546            Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
7547            return false;
7548        }
7549        if (win.mInputChannel == null) {
7550            Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, "
7551                    + " probably being removed");
7552            return false;
7553        }
7554
7555        final DisplayContent displayContent = win.getDisplayContent();
7556        if (displayContent == null) {
7557            Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
7558            return false;
7559        }
7560
7561        Display display = displayContent.getDisplay();
7562        mTaskPositioner = new TaskPositioner(this);
7563        mTaskPositioner.register(display);
7564        mInputMonitor.updateInputWindowsLw(true /*force*/);
7565
7566        // We need to grab the touch focus so that the touch events during the
7567        // resizing/scrolling are not sent to the app. 'win' is the main window
7568        // of the app, it may not have focus since there might be other windows
7569        // on top (eg. a dialog window).
7570        WindowState transferFocusFromWin = win;
7571        if (mCurrentFocus != null && mCurrentFocus != win
7572                && mCurrentFocus.mAppToken == win.mAppToken) {
7573            transferFocusFromWin = mCurrentFocus;
7574        }
7575        if (!mInputManager.transferTouchFocus(
7576                transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) {
7577            Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
7578            mTaskPositioner.unregister();
7579            mTaskPositioner = null;
7580            mInputMonitor.updateInputWindowsLw(true /*force*/);
7581            return false;
7582        }
7583
7584        mTaskPositioner.startDragLocked(win, resize, startX, startY);
7585        return true;
7586    }
7587
7588    private void finishPositioning() {
7589        if (DEBUG_TASK_POSITIONING) {
7590            Slog.d(TAG_WM, "finishPositioning");
7591        }
7592        synchronized (mWindowMap) {
7593            if (mTaskPositioner != null) {
7594                mTaskPositioner.unregister();
7595                mTaskPositioner = null;
7596                mInputMonitor.updateInputWindowsLw(true /*force*/);
7597            }
7598        }
7599    }
7600
7601    void adjustForImeIfNeeded(final DisplayContent displayContent) {
7602        final WindowState imeWin = mInputMethodWindow;
7603        final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
7604                && !displayContent.mDividerControllerLocked.isImeHideRequested();
7605        final boolean dockVisible = isStackVisibleLocked(DOCKED_STACK_ID);
7606        final TaskStack imeTargetStack = getImeFocusStackLocked();
7607        final int imeDockSide = (dockVisible && imeTargetStack != null) ?
7608                imeTargetStack.getDockSide() : DOCKED_INVALID;
7609        final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
7610        final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
7611        final boolean dockMinimized = displayContent.mDividerControllerLocked.isMinimizedDock();
7612        final int imeHeight = mPolicy.getInputMethodWindowVisibleHeightLw();
7613        final boolean imeHeightChanged = imeVisible &&
7614                imeHeight != displayContent.mDividerControllerLocked.getImeHeightAdjustedFor();
7615
7616        // The divider could be adjusted for IME position, or be thinner than usual,
7617        // or both. There are three possible cases:
7618        // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
7619        // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
7620        // - If IME is not visible, divider is not moved and is normal width.
7621
7622        if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
7623            final ArrayList<TaskStack> stacks = displayContent.getStacks();
7624            for (int i = stacks.size() - 1; i >= 0; --i) {
7625                final TaskStack stack = stacks.get(i);
7626                final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
7627                if (stack.isVisibleLocked() && (imeOnBottom || isDockedOnBottom)) {
7628                    stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
7629                } else {
7630                    stack.resetAdjustedForIme(false);
7631                }
7632            }
7633            displayContent.mDividerControllerLocked.setAdjustedForIme(
7634                    imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
7635        } else {
7636            final ArrayList<TaskStack> stacks = displayContent.getStacks();
7637            for (int i = stacks.size() - 1; i >= 0; --i) {
7638                final TaskStack stack = stacks.get(i);
7639                stack.resetAdjustedForIme(!dockVisible);
7640            }
7641            displayContent.mDividerControllerLocked.setAdjustedForIme(
7642                    false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
7643        }
7644    }
7645
7646    // -------------------------------------------------------------
7647    // Drag and drop
7648    // -------------------------------------------------------------
7649
7650    IBinder prepareDragSurface(IWindow window, SurfaceSession session,
7651            int flags, int width, int height, Surface outSurface) {
7652        if (DEBUG_DRAG) {
7653            Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height
7654                    + " flags=" + Integer.toHexString(flags) + " win=" + window
7655                    + " asbinder=" + window.asBinder());
7656        }
7657
7658        final int callerPid = Binder.getCallingPid();
7659        final int callerUid = Binder.getCallingUid();
7660        final long origId = Binder.clearCallingIdentity();
7661        IBinder token = null;
7662
7663        try {
7664            synchronized (mWindowMap) {
7665                try {
7666                    if (mDragState == null) {
7667                        // TODO(multi-display): support other displays
7668                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
7669                        final Display display = displayContent.getDisplay();
7670
7671                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
7672                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
7673                        surface.setLayerStack(display.getLayerStack());
7674                        float alpha = 1;
7675                        if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
7676                            alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
7677                        }
7678                        surface.setAlpha(alpha);
7679
7680                        if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  DRAG "
7681                                + surface + ": CREATE");
7682                        outSurface.copyFrom(surface);
7683                        final IBinder winBinder = window.asBinder();
7684                        token = new Binder();
7685                        mDragState = new DragState(this, token, surface, flags, winBinder);
7686                        mDragState.mPid = callerPid;
7687                        mDragState.mUid = callerUid;
7688                        mDragState.mOriginalAlpha = alpha;
7689                        token = mDragState.mToken = new Binder();
7690
7691                        // 5 second timeout for this window to actually begin the drag
7692                        mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
7693                        Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
7694                        mH.sendMessageDelayed(msg, 5000);
7695                    } else {
7696                        Slog.w(TAG_WM, "Drag already in progress");
7697                    }
7698                } catch (OutOfResourcesException e) {
7699                    Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height, e);
7700                    if (mDragState != null) {
7701                        mDragState.reset();
7702                        mDragState = null;
7703                    }
7704                }
7705            }
7706        } finally {
7707            Binder.restoreCallingIdentity(origId);
7708        }
7709
7710        return token;
7711    }
7712
7713    // -------------------------------------------------------------
7714    // Input Events and Focus Management
7715    // -------------------------------------------------------------
7716
7717    final InputMonitor mInputMonitor = new InputMonitor(this);
7718    private boolean mEventDispatchingEnabled;
7719
7720    @Override
7721    public void pauseKeyDispatching(IBinder _token) {
7722        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7723                "pauseKeyDispatching()")) {
7724            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7725        }
7726
7727        synchronized (mWindowMap) {
7728            WindowToken token = mTokenMap.get(_token);
7729            if (token != null) {
7730                mInputMonitor.pauseDispatchingLw(token);
7731            }
7732        }
7733    }
7734
7735    @Override
7736    public void resumeKeyDispatching(IBinder _token) {
7737        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7738                "resumeKeyDispatching()")) {
7739            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7740        }
7741
7742        synchronized (mWindowMap) {
7743            WindowToken token = mTokenMap.get(_token);
7744            if (token != null) {
7745                mInputMonitor.resumeDispatchingLw(token);
7746            }
7747        }
7748    }
7749
7750    @Override
7751    public void setEventDispatching(boolean enabled) {
7752        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7753                "setEventDispatching()")) {
7754            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7755        }
7756
7757        synchronized (mWindowMap) {
7758            mEventDispatchingEnabled = enabled;
7759            if (mDisplayEnabled) {
7760                mInputMonitor.setEventDispatchingLw(enabled);
7761            }
7762        }
7763    }
7764
7765    private WindowState getFocusedWindow() {
7766        synchronized (mWindowMap) {
7767            return getFocusedWindowLocked();
7768        }
7769    }
7770
7771    private WindowState getFocusedWindowLocked() {
7772        return mCurrentFocus;
7773    }
7774
7775    TaskStack getImeFocusStackLocked() {
7776        // Don't use mCurrentFocus.getStack() because it returns home stack for system windows.
7777        // Also don't use mInputMethodTarget's stack, because some window with FLAG_NOT_FOCUSABLE
7778        // and FLAG_ALT_FOCUSABLE_IM flags both set might be set to IME target so they're moved
7779        // to make room for IME, but the window is not the focused window that's taking input.
7780        return (mFocusedApp != null && mFocusedApp.mTask != null) ?
7781                mFocusedApp.mTask.mStack : null;
7782    }
7783
7784    private void showAuditSafeModeNotification() {
7785        PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
7786                new Intent(Intent.ACTION_VIEW,
7787                           Uri.parse("https://support.google.com/nexus/answer/2852139")), 0);
7788
7789        String title = mContext.getString(R.string.audit_safemode_notification);
7790
7791        Notification notification = new Notification.Builder(mContext)
7792                .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning)
7793                .setWhen(0)
7794                .setOngoing(true)
7795                .setTicker(title)
7796                .setLocalOnly(true)
7797                .setPriority(Notification.PRIORITY_HIGH)
7798                .setVisibility(Notification.VISIBILITY_PUBLIC)
7799                .setColor(mContext.getColor(
7800                        com.android.internal.R.color.system_notification_accent_color))
7801                .setContentTitle(title)
7802                .setContentText(mContext.getString(R.string.audit_safemode_notification_details))
7803                .setContentIntent(pendingIntent)
7804                .build();
7805
7806        NotificationManager notificationManager = (NotificationManager) mContext
7807                .getSystemService(Context.NOTIFICATION_SERVICE);
7808
7809        notificationManager.notifyAsUser(null, R.string.audit_safemode_notification, notification,
7810                UserHandle.ALL);
7811    }
7812
7813    public boolean detectSafeMode() {
7814        if (!mInputMonitor.waitForInputDevicesReady(
7815                INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
7816            Slog.w(TAG_WM, "Devices still not ready after waiting "
7817                   + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
7818                   + " milliseconds before attempting to detect safe mode.");
7819        }
7820
7821        if (Settings.Global.getInt(
7822                mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) {
7823            return false;
7824        }
7825
7826        int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7827                KeyEvent.KEYCODE_MENU);
7828        int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
7829        int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
7830                KeyEvent.KEYCODE_DPAD_CENTER);
7831        int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
7832                InputManagerService.BTN_MOUSE);
7833        int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7834                KeyEvent.KEYCODE_VOLUME_DOWN);
7835        mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
7836                || volumeDownState > 0;
7837        try {
7838            if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0
7839                    || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) {
7840                int auditSafeMode = SystemProperties.getInt(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, 0);
7841
7842                if (auditSafeMode == 0) {
7843                    mSafeMode = true;
7844                    SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
7845                } else {
7846                    // stay in safe mode until we have updated to a newer build
7847                    int buildDate = SystemProperties.getInt(PROPERTY_BUILD_DATE_UTC, 0);
7848
7849                    if (auditSafeMode >= buildDate) {
7850                        mSafeMode = true;
7851                        showAuditSafeModeNotification();
7852                    } else {
7853                        SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
7854                        SystemProperties.set(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, "");
7855                    }
7856                }
7857            }
7858        } catch (IllegalArgumentException e) {
7859        }
7860        if (mSafeMode) {
7861            Log.i(TAG_WM, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
7862                    + " dpad=" + dpadState + " trackball=" + trackballState + ")");
7863            SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1");
7864        } else {
7865            Log.i(TAG_WM, "SAFE MODE not enabled");
7866        }
7867        mPolicy.setSafeMode(mSafeMode);
7868        return mSafeMode;
7869    }
7870
7871    public void displayReady() {
7872        for (Display display : mDisplays) {
7873            displayReady(display.getDisplayId());
7874        }
7875
7876        synchronized(mWindowMap) {
7877            final DisplayContent displayContent = getDefaultDisplayContentLocked();
7878            readForcedDisplayPropertiesLocked(displayContent);
7879            mDisplayReady = true;
7880        }
7881
7882        try {
7883            mActivityManager.updateConfiguration(null);
7884        } catch (RemoteException e) {
7885        }
7886
7887        synchronized(mWindowMap) {
7888            mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
7889                    PackageManager.FEATURE_TOUCHSCREEN);
7890            configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
7891        }
7892
7893        try {
7894            mActivityManager.updateConfiguration(null);
7895        } catch (RemoteException e) {
7896        }
7897
7898        updateCircularDisplayMaskIfNeeded();
7899    }
7900
7901    private void displayReady(int displayId) {
7902        synchronized(mWindowMap) {
7903            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7904            if (displayContent != null) {
7905                mAnimator.addDisplayLocked(displayId);
7906                displayContent.initializeDisplayBaseInfo();
7907                if (displayContent.mTapDetector != null) {
7908                    displayContent.mTapDetector.init();
7909                }
7910            }
7911        }
7912    }
7913
7914    public void systemReady() {
7915        mPolicy.systemReady();
7916    }
7917
7918    // -------------------------------------------------------------
7919    // Async Handler
7920    // -------------------------------------------------------------
7921
7922    final class H extends Handler {
7923        public static final int REPORT_FOCUS_CHANGE = 2;
7924        public static final int REPORT_LOSING_FOCUS = 3;
7925        public static final int DO_TRAVERSAL = 4;
7926        public static final int ADD_STARTING = 5;
7927        public static final int REMOVE_STARTING = 6;
7928        public static final int FINISHED_STARTING = 7;
7929        public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
7930        public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
7931        public static final int WINDOW_FREEZE_TIMEOUT = 11;
7932
7933        public static final int APP_TRANSITION_TIMEOUT = 13;
7934        public static final int PERSIST_ANIMATION_SCALE = 14;
7935        public static final int FORCE_GC = 15;
7936        public static final int ENABLE_SCREEN = 16;
7937        public static final int APP_FREEZE_TIMEOUT = 17;
7938        public static final int SEND_NEW_CONFIGURATION = 18;
7939        public static final int REPORT_WINDOWS_CHANGE = 19;
7940        public static final int DRAG_START_TIMEOUT = 20;
7941        public static final int DRAG_END_TIMEOUT = 21;
7942        public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
7943        public static final int BOOT_TIMEOUT = 23;
7944        public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
7945        public static final int SHOW_STRICT_MODE_VIOLATION = 25;
7946        public static final int DO_ANIMATION_CALLBACK = 26;
7947
7948        public static final int DO_DISPLAY_ADDED = 27;
7949        public static final int DO_DISPLAY_REMOVED = 28;
7950        public static final int DO_DISPLAY_CHANGED = 29;
7951
7952        public static final int CLIENT_FREEZE_TIMEOUT = 30;
7953        public static final int TAP_OUTSIDE_TASK = 31;
7954        public static final int NOTIFY_ACTIVITY_DRAWN = 32;
7955
7956        public static final int ALL_WINDOWS_DRAWN = 33;
7957
7958        public static final int NEW_ANIMATOR_SCALE = 34;
7959
7960        public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35;
7961        public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
7962
7963        public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37;
7964        public static final int RESET_ANR_MESSAGE = 38;
7965        public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39;
7966
7967        public static final int FINISH_TASK_POSITIONING = 40;
7968
7969        public static final int UPDATE_DOCKED_STACK_DIVIDER = 41;
7970
7971        public static final int RESIZE_STACK = 42;
7972        public static final int RESIZE_TASK = 43;
7973
7974        public static final int TWO_FINGER_SCROLL_START = 44;
7975
7976        public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
7977
7978        public static final int NOTIFY_APP_TRANSITION_STARTING = 47;
7979        public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48;
7980        public static final int NOTIFY_APP_TRANSITION_FINISHED = 49;
7981        public static final int NOTIFY_STARTING_WINDOW_DRAWN = 50;
7982        public static final int UPDATE_ANIMATION_SCALE = 51;
7983        public static final int WINDOW_REMOVE_TIMEOUT = 52;
7984
7985        public static final int NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED = 53;
7986
7987        /**
7988         * Used to denote that an integer field in a message will not be used.
7989         */
7990        public static final int UNUSED = 0;
7991
7992        @Override
7993        public void handleMessage(Message msg) {
7994            if (DEBUG_WINDOW_TRACE) {
7995                Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what);
7996            }
7997            switch (msg.what) {
7998                case REPORT_FOCUS_CHANGE: {
7999                    WindowState lastFocus;
8000                    WindowState newFocus;
8001
8002                    AccessibilityController accessibilityController = null;
8003
8004                    synchronized(mWindowMap) {
8005                        // TODO(multidisplay): Accessibility supported only of default desiplay.
8006                        if (mAccessibilityController != null && getDefaultDisplayContentLocked()
8007                                .getDisplayId() == Display.DEFAULT_DISPLAY) {
8008                            accessibilityController = mAccessibilityController;
8009                        }
8010
8011                        lastFocus = mLastFocus;
8012                        newFocus = mCurrentFocus;
8013                        if (lastFocus == newFocus) {
8014                            // Focus is not changing, so nothing to do.
8015                            return;
8016                        }
8017                        mLastFocus = newFocus;
8018                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Focus moving from " + lastFocus +
8019                                " to " + newFocus);
8020                        if (newFocus != null && lastFocus != null
8021                                && !newFocus.isDisplayedLw()) {
8022                            //Slog.i(TAG_WM, "Delaying loss of focus...");
8023                            mLosingFocus.add(lastFocus);
8024                            lastFocus = null;
8025                        }
8026                    }
8027
8028                    // First notify the accessibility manager for the change so it has
8029                    // the windows before the newly focused one starts firing eventgs.
8030                    if (accessibilityController != null) {
8031                        accessibilityController.onWindowFocusChangedNotLocked();
8032                    }
8033
8034                    //System.out.println("Changing focus from " + lastFocus
8035                    //                   + " to " + newFocus);
8036                    if (newFocus != null) {
8037                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus);
8038                        newFocus.reportFocusChangedSerialized(true, mInTouchMode);
8039                        notifyFocusChanged();
8040                    }
8041
8042                    if (lastFocus != null) {
8043                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus);
8044                        lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
8045                    }
8046                } break;
8047
8048                case REPORT_LOSING_FOCUS: {
8049                    ArrayList<WindowState> losers;
8050
8051                    synchronized(mWindowMap) {
8052                        losers = mLosingFocus;
8053                        mLosingFocus = new ArrayList<WindowState>();
8054                    }
8055
8056                    final int N = losers.size();
8057                    for (int i=0; i<N; i++) {
8058                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " +
8059                                losers.get(i));
8060                        losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
8061                    }
8062                } break;
8063
8064                case DO_TRAVERSAL: {
8065                    synchronized(mWindowMap) {
8066                        mWindowPlacerLocked.performSurfacePlacement();
8067                    }
8068                } break;
8069
8070                case ADD_STARTING: {
8071                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8072                    final StartingData sd = wtoken.startingData;
8073
8074                    if (sd == null) {
8075                        // Animation has been canceled... do nothing.
8076                        return;
8077                    }
8078
8079                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting "
8080                            + wtoken + ": pkg=" + sd.pkg);
8081
8082                    View view = null;
8083                    try {
8084                        final Configuration overrideConfig = wtoken != null && wtoken.mTask != null
8085                                ? wtoken.mTask.mOverrideConfig : null;
8086                        view = mPolicy.addStartingWindow(wtoken.token, sd.pkg, sd.theme,
8087                            sd.compatInfo, sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo,
8088                            sd.windowFlags, overrideConfig);
8089                    } catch (Exception e) {
8090                        Slog.w(TAG_WM, "Exception when adding starting window", e);
8091                    }
8092
8093                    if (view != null) {
8094                        boolean abort = false;
8095
8096                        synchronized(mWindowMap) {
8097                            if (wtoken.removed || wtoken.startingData == null) {
8098                                // If the window was successfully added, then
8099                                // we need to remove it.
8100                                if (wtoken.startingWindow != null) {
8101                                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
8102                                            "Aborted starting " + wtoken
8103                                            + ": removed=" + wtoken.removed
8104                                            + " startingData=" + wtoken.startingData);
8105                                    wtoken.startingWindow = null;
8106                                    wtoken.startingData = null;
8107                                    abort = true;
8108                                }
8109                            } else {
8110                                wtoken.startingView = view;
8111                            }
8112                            if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM,
8113                                    "Added starting " + wtoken
8114                                    + ": startingWindow="
8115                                    + wtoken.startingWindow + " startingView="
8116                                    + wtoken.startingView);
8117                        }
8118
8119                        if (abort) {
8120                            try {
8121                                mPolicy.removeStartingWindow(wtoken.token, view);
8122                            } catch (Exception e) {
8123                                Slog.w(TAG_WM, "Exception when removing starting window", e);
8124                            }
8125                        }
8126                    }
8127                } break;
8128
8129                case REMOVE_STARTING: {
8130                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8131                    IBinder token = null;
8132                    View view = null;
8133                    synchronized (mWindowMap) {
8134                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting "
8135                                + wtoken + ": startingWindow="
8136                                + wtoken.startingWindow + " startingView="
8137                                + wtoken.startingView);
8138                        if (wtoken.startingWindow != null) {
8139                            view = wtoken.startingView;
8140                            token = wtoken.token;
8141                            wtoken.startingData = null;
8142                            wtoken.startingView = null;
8143                            wtoken.startingWindow = null;
8144                            wtoken.startingDisplayed = false;
8145                        }
8146                    }
8147                    if (view != null) {
8148                        try {
8149                            mPolicy.removeStartingWindow(token, view);
8150                        } catch (Exception e) {
8151                            Slog.w(TAG_WM, "Exception when removing starting window", e);
8152                        }
8153                    }
8154                } break;
8155
8156                case FINISHED_STARTING: {
8157                    IBinder token = null;
8158                    View view = null;
8159                    while (true) {
8160                        synchronized (mWindowMap) {
8161                            final int N = mFinishedStarting.size();
8162                            if (N <= 0) {
8163                                break;
8164                            }
8165                            AppWindowToken wtoken = mFinishedStarting.remove(N-1);
8166
8167                            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
8168                                    "Finished starting " + wtoken
8169                                    + ": startingWindow=" + wtoken.startingWindow
8170                                    + " startingView=" + wtoken.startingView);
8171
8172                            if (wtoken.startingWindow == null) {
8173                                continue;
8174                            }
8175
8176                            view = wtoken.startingView;
8177                            token = wtoken.token;
8178                            wtoken.startingData = null;
8179                            wtoken.startingView = null;
8180                            wtoken.startingWindow = null;
8181                            wtoken.startingDisplayed = false;
8182                        }
8183
8184                        try {
8185                            mPolicy.removeStartingWindow(token, view);
8186                        } catch (Exception e) {
8187                            Slog.w(TAG_WM, "Exception when removing starting window", e);
8188                        }
8189                    }
8190                } break;
8191
8192                case REPORT_APPLICATION_TOKEN_DRAWN: {
8193                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8194
8195                    try {
8196                        if (DEBUG_VISIBILITY) Slog.v(
8197                                TAG_WM, "Reporting drawn in " + wtoken);
8198                        wtoken.appToken.windowsDrawn();
8199                    } catch (RemoteException ex) {
8200                    }
8201                } break;
8202
8203                case REPORT_APPLICATION_TOKEN_WINDOWS: {
8204                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8205
8206                    boolean nowVisible = msg.arg1 != 0;
8207                    boolean nowGone = msg.arg2 != 0;
8208
8209                    try {
8210                        if (DEBUG_VISIBILITY) Slog.v(
8211                                TAG_WM, "Reporting visible in " + wtoken
8212                                + " visible=" + nowVisible
8213                                + " gone=" + nowGone);
8214                        if (nowVisible) {
8215                            wtoken.appToken.windowsVisible();
8216                        } else {
8217                            wtoken.appToken.windowsGone();
8218                        }
8219                    } catch (RemoteException ex) {
8220                    }
8221                } break;
8222
8223                case WINDOW_FREEZE_TIMEOUT: {
8224                    // TODO(multidisplay): Can non-default displays rotate?
8225                    synchronized (mWindowMap) {
8226                        Slog.w(TAG_WM, "Window freeze timeout expired.");
8227                        mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
8228                        final WindowList windows = getDefaultWindowListLocked();
8229                        int i = windows.size();
8230                        while (i > 0) {
8231                            i--;
8232                            WindowState w = windows.get(i);
8233                            if (w.mOrientationChanging) {
8234                                w.mOrientationChanging = false;
8235                                w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
8236                                        - mDisplayFreezeTime);
8237                                Slog.w(TAG_WM, "Force clearing orientation change: " + w);
8238                            }
8239                        }
8240                        mWindowPlacerLocked.performSurfacePlacement();
8241                    }
8242                    break;
8243                }
8244
8245                case APP_TRANSITION_TIMEOUT: {
8246                    synchronized (mWindowMap) {
8247                        if (mAppTransition.isTransitionSet() || !mOpeningApps.isEmpty()
8248                                    || !mClosingApps.isEmpty()) {
8249                            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "*** APP TRANSITION TIMEOUT."
8250                                    + " isTransitionSet()=" + mAppTransition.isTransitionSet()
8251                                    + " mOpeningApps.size()=" + mOpeningApps.size()
8252                                    + " mClosingApps.size()=" + mClosingApps.size());
8253                            mAppTransition.setTimeout();
8254                            mWindowPlacerLocked.performSurfacePlacement();
8255                        }
8256                    }
8257                    break;
8258                }
8259
8260                case PERSIST_ANIMATION_SCALE: {
8261                    Settings.Global.putFloat(mContext.getContentResolver(),
8262                            Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
8263                    Settings.Global.putFloat(mContext.getContentResolver(),
8264                            Settings.Global.TRANSITION_ANIMATION_SCALE,
8265                            mTransitionAnimationScaleSetting);
8266                    Settings.Global.putFloat(mContext.getContentResolver(),
8267                            Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting);
8268                    break;
8269                }
8270
8271                case UPDATE_ANIMATION_SCALE: {
8272                    @UpdateAnimationScaleMode
8273                    final int mode = msg.arg1;
8274                    switch (mode) {
8275                        case WINDOW_ANIMATION_SCALE: {
8276                            mWindowAnimationScaleSetting = Settings.Global.getFloat(
8277                                    mContext.getContentResolver(),
8278                                    Settings.Global.WINDOW_ANIMATION_SCALE,
8279                                    mWindowAnimationScaleSetting);
8280                            break;
8281                        }
8282                        case TRANSITION_ANIMATION_SCALE: {
8283                            mTransitionAnimationScaleSetting = Settings.Global.getFloat(
8284                                    mContext.getContentResolver(),
8285                                    Settings.Global.TRANSITION_ANIMATION_SCALE,
8286                                    mTransitionAnimationScaleSetting);
8287                            break;
8288                        }
8289                        case ANIMATION_DURATION_SCALE: {
8290                            mAnimatorDurationScaleSetting = Settings.Global.getFloat(
8291                                    mContext.getContentResolver(),
8292                                    Settings.Global.ANIMATOR_DURATION_SCALE,
8293                                    mAnimatorDurationScaleSetting);
8294                            dispatchNewAnimatorScaleLocked(null);
8295                            break;
8296                        }
8297                    }
8298                    break;
8299                }
8300
8301                case FORCE_GC: {
8302                    synchronized (mWindowMap) {
8303                        // Since we're holding both mWindowMap and mAnimator we don't need to
8304                        // hold mAnimator.mLayoutToAnim.
8305                        if (mAnimator.isAnimating() || mAnimationScheduled) {
8306                            // If we are animating, don't do the gc now but
8307                            // delay a bit so we don't interrupt the animation.
8308                            sendEmptyMessageDelayed(H.FORCE_GC, 2000);
8309                            return;
8310                        }
8311                        // If we are currently rotating the display, it will
8312                        // schedule a new message when done.
8313                        if (mDisplayFrozen) {
8314                            return;
8315                        }
8316                    }
8317                    Runtime.getRuntime().gc();
8318                    break;
8319                }
8320
8321                case ENABLE_SCREEN: {
8322                    performEnableScreen();
8323                    break;
8324                }
8325
8326                case APP_FREEZE_TIMEOUT: {
8327                    synchronized (mWindowMap) {
8328                        Slog.w(TAG_WM, "App freeze timeout expired.");
8329                        mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
8330                        final int numStacks = mStackIdToStack.size();
8331                        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8332                            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
8333                            final ArrayList<Task> tasks = stack.getTasks();
8334                            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
8335                                AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8336                                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
8337                                    AppWindowToken tok = tokens.get(tokenNdx);
8338                                    if (tok.mAppAnimator.freezingScreen) {
8339                                        Slog.w(TAG_WM, "Force clearing freeze: " + tok);
8340                                        unsetAppFreezingScreenLocked(tok, true, true);
8341                                    }
8342                                }
8343                            }
8344                        }
8345                    }
8346                    break;
8347                }
8348
8349                case CLIENT_FREEZE_TIMEOUT: {
8350                    synchronized (mWindowMap) {
8351                        if (mClientFreezingScreen) {
8352                            mClientFreezingScreen = false;
8353                            mLastFinishedFreezeSource = "client-timeout";
8354                            stopFreezingDisplayLocked();
8355                        }
8356                    }
8357                    break;
8358                }
8359
8360                case SEND_NEW_CONFIGURATION: {
8361                    removeMessages(SEND_NEW_CONFIGURATION);
8362                    sendNewConfiguration();
8363                    break;
8364                }
8365
8366                case REPORT_WINDOWS_CHANGE: {
8367                    if (mWindowsChanged) {
8368                        synchronized (mWindowMap) {
8369                            mWindowsChanged = false;
8370                        }
8371                        notifyWindowsChanged();
8372                    }
8373                    break;
8374                }
8375
8376                case DRAG_START_TIMEOUT: {
8377                    IBinder win = (IBinder)msg.obj;
8378                    if (DEBUG_DRAG) {
8379                        Slog.w(TAG_WM, "Timeout starting drag by win " + win);
8380                    }
8381                    synchronized (mWindowMap) {
8382                        // !!! TODO: ANR the app that has failed to start the drag in time
8383                        if (mDragState != null) {
8384                            mDragState.unregister();
8385                            mInputMonitor.updateInputWindowsLw(true /*force*/);
8386                            mDragState.reset();
8387                            mDragState = null;
8388                        }
8389                    }
8390                    break;
8391                }
8392
8393                case DRAG_END_TIMEOUT: {
8394                    IBinder win = (IBinder)msg.obj;
8395                    if (DEBUG_DRAG) {
8396                        Slog.w(TAG_WM, "Timeout ending drag to win " + win);
8397                    }
8398                    synchronized (mWindowMap) {
8399                        // !!! TODO: ANR the drag-receiving app
8400                        if (mDragState != null) {
8401                            mDragState.mDragResult = false;
8402                            mDragState.endDragLw();
8403                        }
8404                    }
8405                    break;
8406                }
8407
8408                case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
8409                    notifyHardKeyboardStatusChange();
8410                    break;
8411                }
8412
8413                case BOOT_TIMEOUT: {
8414                    performBootTimeout();
8415                    break;
8416                }
8417
8418                case WAITING_FOR_DRAWN_TIMEOUT: {
8419                    Runnable callback = null;
8420                    synchronized (mWindowMap) {
8421                        Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
8422                        mWaitingForDrawn.clear();
8423                        callback = mWaitingForDrawnCallback;
8424                        mWaitingForDrawnCallback = null;
8425                    }
8426                    if (callback != null) {
8427                        callback.run();
8428                    }
8429                    break;
8430                }
8431
8432                case SHOW_STRICT_MODE_VIOLATION: {
8433                    showStrictModeViolation(msg.arg1, msg.arg2);
8434                    break;
8435                }
8436
8437                case SHOW_CIRCULAR_DISPLAY_MASK: {
8438                    showCircularMask(msg.arg1 == 1);
8439                    break;
8440                }
8441
8442                case SHOW_EMULATOR_DISPLAY_OVERLAY: {
8443                    showEmulatorDisplayOverlay();
8444                    break;
8445                }
8446
8447                case DO_ANIMATION_CALLBACK: {
8448                    try {
8449                        ((IRemoteCallback)msg.obj).sendResult(null);
8450                    } catch (RemoteException e) {
8451                    }
8452                    break;
8453                }
8454
8455                case DO_DISPLAY_ADDED:
8456                    handleDisplayAdded(msg.arg1);
8457                    break;
8458
8459                case DO_DISPLAY_REMOVED:
8460                    synchronized (mWindowMap) {
8461                        handleDisplayRemovedLocked(msg.arg1);
8462                    }
8463                    break;
8464
8465                case DO_DISPLAY_CHANGED:
8466                    synchronized (mWindowMap) {
8467                        handleDisplayChangedLocked(msg.arg1);
8468                    }
8469                    break;
8470
8471                case TWO_FINGER_SCROLL_START: {
8472                    startScrollingTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
8473                }
8474                break;
8475
8476                case TAP_OUTSIDE_TASK: {
8477                    handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
8478                }
8479                break;
8480
8481                case FINISH_TASK_POSITIONING: {
8482                    finishPositioning();
8483                }
8484                break;
8485
8486                case NOTIFY_ACTIVITY_DRAWN:
8487                    try {
8488                        mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
8489                    } catch (RemoteException e) {
8490                    }
8491                    break;
8492                case ALL_WINDOWS_DRAWN: {
8493                    Runnable callback;
8494                    synchronized (mWindowMap) {
8495                        callback = mWaitingForDrawnCallback;
8496                        mWaitingForDrawnCallback = null;
8497                    }
8498                    if (callback != null) {
8499                        callback.run();
8500                    }
8501                }
8502                case NEW_ANIMATOR_SCALE: {
8503                    float scale = getCurrentAnimatorScale();
8504                    ValueAnimator.setDurationScale(scale);
8505                    Session session = (Session)msg.obj;
8506                    if (session != null) {
8507                        try {
8508                            session.mCallback.onAnimatorScaleChanged(scale);
8509                        } catch (RemoteException e) {
8510                        }
8511                    } else {
8512                        ArrayList<IWindowSessionCallback> callbacks
8513                                = new ArrayList<IWindowSessionCallback>();
8514                        synchronized (mWindowMap) {
8515                            for (int i=0; i<mSessions.size(); i++) {
8516                                callbacks.add(mSessions.valueAt(i).mCallback);
8517                            }
8518
8519                        }
8520                        for (int i=0; i<callbacks.size(); i++) {
8521                            try {
8522                                callbacks.get(i).onAnimatorScaleChanged(scale);
8523                            } catch (RemoteException e) {
8524                            }
8525                        }
8526                    }
8527                }
8528                break;
8529                case CHECK_IF_BOOT_ANIMATION_FINISHED: {
8530                    final boolean bootAnimationComplete;
8531                    synchronized (mWindowMap) {
8532                        if (DEBUG_BOOT) Slog.i(TAG_WM, "CHECK_IF_BOOT_ANIMATION_FINISHED:");
8533                        bootAnimationComplete = checkBootAnimationCompleteLocked();
8534                    }
8535                    if (bootAnimationComplete) {
8536                        performEnableScreen();
8537                    }
8538                }
8539                break;
8540                case RESET_ANR_MESSAGE: {
8541                    synchronized (mWindowMap) {
8542                        mLastANRState = null;
8543                    }
8544                }
8545                break;
8546                case WALLPAPER_DRAW_PENDING_TIMEOUT: {
8547                    synchronized (mWindowMap) {
8548                        if (mWallpaperControllerLocked.processWallpaperDrawPendingTimeout()) {
8549                            mWindowPlacerLocked.performSurfacePlacement();
8550                        }
8551                    }
8552                }
8553                case UPDATE_DOCKED_STACK_DIVIDER: {
8554                    synchronized (mWindowMap) {
8555                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
8556                        displayContent.getDockedDividerController().reevaluateVisibility(false);
8557                        adjustForImeIfNeeded(displayContent);
8558                    }
8559                }
8560                break;
8561                case RESIZE_TASK: {
8562                    try {
8563                        mActivityManager.resizeTask(msg.arg1, (Rect) msg.obj, msg.arg2);
8564                    } catch (RemoteException e) {
8565                        // This will not happen since we are in the same process.
8566                    }
8567                }
8568                break;
8569                case RESIZE_STACK: {
8570                    try {
8571                        mActivityManager.resizeStack(
8572                                msg.arg1, (Rect) msg.obj, msg.arg2 == 1, false, false, -1);
8573                    } catch (RemoteException e) {
8574                        // This will not happen since we are in the same process.
8575                    }
8576                }
8577                break;
8578                case WINDOW_REPLACEMENT_TIMEOUT: {
8579                    synchronized (mWindowMap) {
8580                        for (int i = mReplacingWindowTimeouts.size() - 1; i >= 0; i--) {
8581                            final AppWindowToken token = mReplacingWindowTimeouts.get(i);
8582                            token.clearTimedoutReplacesLocked();
8583                        }
8584                        mReplacingWindowTimeouts.clear();
8585                    }
8586                }
8587                case NOTIFY_APP_TRANSITION_STARTING: {
8588                    mAmInternal.notifyAppTransitionStarting(msg.arg1);
8589                }
8590                break;
8591                case NOTIFY_APP_TRANSITION_CANCELLED: {
8592                    mAmInternal.notifyAppTransitionCancelled();
8593                }
8594                break;
8595                case NOTIFY_APP_TRANSITION_FINISHED: {
8596                    mAmInternal.notifyAppTransitionFinished();
8597                }
8598                break;
8599                case NOTIFY_STARTING_WINDOW_DRAWN: {
8600                    mAmInternal.notifyStartingWindowDrawn();
8601                }
8602                break;
8603                case WINDOW_REMOVE_TIMEOUT: {
8604                    final WindowState window = (WindowState) msg.obj;
8605                    synchronized(mWindowMap) {
8606                        // It's counterintuitive that we check that "mWindowRemovalAllowed"
8607                        // is false. But in fact if it's true, it means a remove has already
8608                        // been requested and we better just not do anything.
8609                        if (!window.mRemoved && !window.mWindowRemovalAllowed) {
8610                            removeWindowLocked(window);
8611                        }
8612                    }
8613                }
8614                break;
8615                case NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED: {
8616                    mAmInternal.notifyDockedStackMinimizedChanged(msg.arg1 == 1);
8617                }
8618                break;
8619            }
8620            if (DEBUG_WINDOW_TRACE) {
8621                Slog.v(TAG_WM, "handleMessage: exit");
8622            }
8623        }
8624    }
8625
8626    void destroyPreservedSurfaceLocked() {
8627        for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) {
8628            final WindowState w = mDestroyPreservedSurface.get(i);
8629            w.mWinAnimator.destroyPreservedSurfaceLocked();
8630        }
8631        mDestroyPreservedSurface.clear();
8632    }
8633
8634    void stopUsingSavedSurfaceLocked() {
8635        for (int i = mFinishedEarlyAnim.size() - 1; i >= 0 ; i--) {
8636            final AppWindowToken wtoken = mFinishedEarlyAnim.get(i);
8637            wtoken.stopUsingSavedSurfaceLocked();
8638        }
8639        mFinishedEarlyAnim.clear();
8640    }
8641
8642    // -------------------------------------------------------------
8643    // IWindowManager API
8644    // -------------------------------------------------------------
8645
8646    @Override
8647    public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
8648            IInputContext inputContext) {
8649        if (client == null) throw new IllegalArgumentException("null client");
8650        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
8651        Session session = new Session(this, callback, client, inputContext);
8652        return session;
8653    }
8654
8655    @Override
8656    public boolean inputMethodClientHasFocus(IInputMethodClient client) {
8657        synchronized (mWindowMap) {
8658            // The focus for the client is the window immediately below
8659            // where we would place the input method window.
8660            int idx = findDesiredInputMethodWindowIndexLocked(false);
8661            if (idx > 0) {
8662                // TODO(multidisplay): IMEs are only supported on the default display.
8663                WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
8664                if (DEBUG_INPUT_METHOD) {
8665                    Slog.i(TAG_WM, "Desired input method target: " + imFocus);
8666                    Slog.i(TAG_WM, "Current focus: " + mCurrentFocus);
8667                    Slog.i(TAG_WM, "Last focus: " + mLastFocus);
8668                }
8669                if (imFocus != null) {
8670                    // This may be a starting window, in which case we still want
8671                    // to count it as okay.
8672                    if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
8673                            && imFocus.mAppToken != null) {
8674                        // The client has definitely started, so it really should
8675                        // have a window in this app token.  Let's look for it.
8676                        for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
8677                            WindowState w = imFocus.mAppToken.windows.get(i);
8678                            if (w != imFocus) {
8679                                Log.i(TAG_WM, "Switching to real app window: " + w);
8680                                imFocus = w;
8681                                break;
8682                            }
8683                        }
8684                    }
8685                    if (DEBUG_INPUT_METHOD) {
8686                        Slog.i(TAG_WM, "IM target client: " + imFocus.mSession.mClient);
8687                        if (imFocus.mSession.mClient != null) {
8688                            Slog.i(TAG_WM, "IM target client binder: "
8689                                    + imFocus.mSession.mClient.asBinder());
8690                            Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder());
8691                        }
8692                    }
8693                    if (imFocus.mSession.mClient != null &&
8694                            imFocus.mSession.mClient.asBinder() == client.asBinder()) {
8695                        return true;
8696                    }
8697                }
8698            }
8699
8700            // Okay, how about this...  what is the current focus?
8701            // It seems in some cases we may not have moved the IM
8702            // target window, such as when it was in a pop-up window,
8703            // so let's also look at the current focus.  (An example:
8704            // go to Gmail, start searching so the keyboard goes up,
8705            // press home.  Sometimes the IME won't go down.)
8706            // Would be nice to fix this more correctly, but it's
8707            // way at the end of a release, and this should be good enough.
8708            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
8709                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
8710                return true;
8711            }
8712        }
8713        return false;
8714    }
8715
8716    @Override
8717    public void getInitialDisplaySize(int displayId, Point size) {
8718        synchronized (mWindowMap) {
8719            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8720            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8721                size.x = displayContent.mInitialDisplayWidth;
8722                size.y = displayContent.mInitialDisplayHeight;
8723            }
8724        }
8725    }
8726
8727    @Override
8728    public void getBaseDisplaySize(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.mBaseDisplayWidth;
8733                size.y = displayContent.mBaseDisplayHeight;
8734            }
8735        }
8736    }
8737
8738    @Override
8739    public void setForcedDisplaySize(int displayId, int width, int height) {
8740        if (mContext.checkCallingOrSelfPermission(
8741                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8742                PackageManager.PERMISSION_GRANTED) {
8743            throw new SecurityException("Must hold permission " +
8744                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8745        }
8746        if (displayId != Display.DEFAULT_DISPLAY) {
8747            throw new IllegalArgumentException("Can only set the default display");
8748        }
8749        final long ident = Binder.clearCallingIdentity();
8750        try {
8751            synchronized(mWindowMap) {
8752                // Set some sort of reasonable bounds on the size of the display that we
8753                // will try to emulate.
8754                final int MIN_WIDTH = 200;
8755                final int MIN_HEIGHT = 200;
8756                final int MAX_SCALE = 2;
8757                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8758                if (displayContent != null) {
8759                    width = Math.min(Math.max(width, MIN_WIDTH),
8760                            displayContent.mInitialDisplayWidth * MAX_SCALE);
8761                    height = Math.min(Math.max(height, MIN_HEIGHT),
8762                            displayContent.mInitialDisplayHeight * MAX_SCALE);
8763                    setForcedDisplaySizeLocked(displayContent, width, height);
8764                    Settings.Global.putString(mContext.getContentResolver(),
8765                            Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
8766                }
8767            }
8768        } finally {
8769            Binder.restoreCallingIdentity(ident);
8770        }
8771    }
8772
8773    @Override
8774    public void setForcedDisplayScalingMode(int displayId, int mode) {
8775        if (mContext.checkCallingOrSelfPermission(
8776                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8777                PackageManager.PERMISSION_GRANTED) {
8778            throw new SecurityException("Must hold permission " +
8779                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8780        }
8781        if (displayId != Display.DEFAULT_DISPLAY) {
8782            throw new IllegalArgumentException("Can only set the default display");
8783        }
8784        final long ident = Binder.clearCallingIdentity();
8785        try {
8786            synchronized(mWindowMap) {
8787                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8788                if (displayContent != null) {
8789                    if (mode < 0 || mode > 1) {
8790                        mode = 0;
8791                    }
8792                    setForcedDisplayScalingModeLocked(displayContent, mode);
8793                    Settings.Global.putInt(mContext.getContentResolver(),
8794                            Settings.Global.DISPLAY_SCALING_FORCE, mode);
8795                }
8796            }
8797        } finally {
8798            Binder.restoreCallingIdentity(ident);
8799        }
8800    }
8801
8802    private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode) {
8803        Slog.i(TAG_WM, "Using display scaling mode: " + (mode == 0 ? "auto" : "off"));
8804        displayContent.mDisplayScalingDisabled = (mode != 0);
8805        reconfigureDisplayLocked(displayContent);
8806    }
8807
8808    private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) {
8809        // Display size.
8810        String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
8811                Settings.Global.DISPLAY_SIZE_FORCED);
8812        if (sizeStr == null || sizeStr.length() == 0) {
8813            sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
8814        }
8815        if (sizeStr != null && sizeStr.length() > 0) {
8816            final int pos = sizeStr.indexOf(',');
8817            if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
8818                int width, height;
8819                try {
8820                    width = Integer.parseInt(sizeStr.substring(0, pos));
8821                    height = Integer.parseInt(sizeStr.substring(pos+1));
8822                    if (displayContent.mBaseDisplayWidth != width
8823                            || displayContent.mBaseDisplayHeight != height) {
8824                        Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
8825                        displayContent.mBaseDisplayWidth = width;
8826                        displayContent.mBaseDisplayHeight = height;
8827                    }
8828                } catch (NumberFormatException ex) {
8829                }
8830            }
8831        }
8832
8833        // Display density.
8834        final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId);
8835        if (density != 0) {
8836            displayContent.mBaseDisplayDensity = density;
8837        }
8838
8839        // Display scaling mode.
8840        int mode = Settings.Global.getInt(mContext.getContentResolver(),
8841                Settings.Global.DISPLAY_SCALING_FORCE, 0);
8842        if (mode != 0) {
8843            Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED");
8844            displayContent.mDisplayScalingDisabled = true;
8845        }
8846    }
8847
8848    // displayContent must not be null
8849    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
8850        Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
8851        displayContent.mBaseDisplayWidth = width;
8852        displayContent.mBaseDisplayHeight = height;
8853        reconfigureDisplayLocked(displayContent);
8854    }
8855
8856    @Override
8857    public void clearForcedDisplaySize(int displayId) {
8858        if (mContext.checkCallingOrSelfPermission(
8859                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8860                PackageManager.PERMISSION_GRANTED) {
8861            throw new SecurityException("Must hold permission " +
8862                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8863        }
8864        if (displayId != Display.DEFAULT_DISPLAY) {
8865            throw new IllegalArgumentException("Can only set the default display");
8866        }
8867        final long ident = Binder.clearCallingIdentity();
8868        try {
8869            synchronized(mWindowMap) {
8870                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8871                if (displayContent != null) {
8872                    setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
8873                            displayContent.mInitialDisplayHeight);
8874                    Settings.Global.putString(mContext.getContentResolver(),
8875                            Settings.Global.DISPLAY_SIZE_FORCED, "");
8876                }
8877            }
8878        } finally {
8879            Binder.restoreCallingIdentity(ident);
8880        }
8881    }
8882
8883    @Override
8884    public int getInitialDisplayDensity(int displayId) {
8885        synchronized (mWindowMap) {
8886            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8887            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8888                return displayContent.mInitialDisplayDensity;
8889            }
8890        }
8891        return -1;
8892    }
8893
8894    @Override
8895    public int getBaseDisplayDensity(int displayId) {
8896        synchronized (mWindowMap) {
8897            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8898            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8899                return displayContent.mBaseDisplayDensity;
8900            }
8901        }
8902        return -1;
8903    }
8904
8905    @Override
8906    public void setForcedDisplayDensity(int displayId, int density) {
8907        if (mContext.checkCallingOrSelfPermission(
8908                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8909                PackageManager.PERMISSION_GRANTED) {
8910            throw new SecurityException("Must hold permission " +
8911                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8912        }
8913        if (displayId != Display.DEFAULT_DISPLAY) {
8914            throw new IllegalArgumentException("Can only set the default display");
8915        }
8916        final long ident = Binder.clearCallingIdentity();
8917        try {
8918            synchronized(mWindowMap) {
8919                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8920                if (displayContent != null) {
8921                    setForcedDisplayDensityLocked(displayContent, density);
8922                    Settings.Secure.putStringForUser(mContext.getContentResolver(),
8923                            Settings.Secure.DISPLAY_DENSITY_FORCED,
8924                            Integer.toString(density), mCurrentUserId);
8925                }
8926            }
8927        } finally {
8928            Binder.restoreCallingIdentity(ident);
8929        }
8930    }
8931
8932    @Override
8933    public void clearForcedDisplayDensity(int displayId) {
8934        if (mContext.checkCallingOrSelfPermission(
8935                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8936                PackageManager.PERMISSION_GRANTED) {
8937            throw new SecurityException("Must hold permission " +
8938                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8939        }
8940        if (displayId != Display.DEFAULT_DISPLAY) {
8941            throw new IllegalArgumentException("Can only set the default display");
8942        }
8943        final long ident = Binder.clearCallingIdentity();
8944        try {
8945            synchronized(mWindowMap) {
8946                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8947                if (displayContent != null) {
8948                    setForcedDisplayDensityLocked(displayContent,
8949                            displayContent.mInitialDisplayDensity);
8950                    Settings.Secure.putStringForUser(mContext.getContentResolver(),
8951                            Settings.Secure.DISPLAY_DENSITY_FORCED, "", mCurrentUserId);
8952                }
8953            }
8954        } finally {
8955            Binder.restoreCallingIdentity(ident);
8956        }
8957    }
8958
8959    /**
8960     * @param userId the ID of the user
8961     * @return the forced display density for the specified user, if set, or
8962     *         {@code 0} if not set
8963     */
8964    private int getForcedDisplayDensityForUserLocked(int userId) {
8965        String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(),
8966                Settings.Secure.DISPLAY_DENSITY_FORCED, userId);
8967        if (densityStr == null || densityStr.length() == 0) {
8968            densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
8969        }
8970        if (densityStr != null && densityStr.length() > 0) {
8971            try {
8972                return Integer.parseInt(densityStr);
8973            } catch (NumberFormatException ex) {
8974            }
8975        }
8976        return 0;
8977    }
8978
8979    /**
8980     * Forces the given display to the use the specified density.
8981     *
8982     * @param displayContent the display to modify
8983     * @param density the density in DPI to use
8984     */
8985    private void setForcedDisplayDensityLocked(@NonNull DisplayContent displayContent,
8986            int density) {
8987        displayContent.mBaseDisplayDensity = density;
8988        reconfigureDisplayLocked(displayContent);
8989    }
8990
8991    // displayContent must not be null
8992    private void reconfigureDisplayLocked(DisplayContent displayContent) {
8993        // TODO: Multidisplay: for now only use with default display.
8994        if (!mDisplayReady) {
8995            return;
8996        }
8997        configureDisplayPolicyLocked(displayContent);
8998        displayContent.layoutNeeded = true;
8999
9000        boolean configChanged = updateOrientationFromAppTokensLocked(false);
9001        mTempConfiguration.setToDefaults();
9002        mTempConfiguration.updateFrom(mCurConfiguration);
9003        computeScreenConfigurationLocked(mTempConfiguration);
9004        configChanged |= mCurConfiguration.diff(mTempConfiguration) != 0;
9005
9006        if (configChanged) {
9007            mWaitingForConfig = true;
9008            startFreezingDisplayLocked(false, 0, 0);
9009            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9010            if (!mReconfigureOnConfigurationChanged.contains(displayContent)) {
9011                mReconfigureOnConfigurationChanged.add(displayContent);
9012            }
9013        }
9014
9015        mWindowPlacerLocked.performSurfacePlacement();
9016    }
9017
9018    private void configureDisplayPolicyLocked(DisplayContent displayContent) {
9019        mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
9020                displayContent.mBaseDisplayWidth,
9021                displayContent.mBaseDisplayHeight,
9022                displayContent.mBaseDisplayDensity);
9023
9024        DisplayInfo displayInfo = displayContent.getDisplayInfo();
9025        mPolicy.setDisplayOverscan(displayContent.getDisplay(),
9026                displayInfo.overscanLeft, displayInfo.overscanTop,
9027                displayInfo.overscanRight, displayInfo.overscanBottom);
9028    }
9029
9030    @Override
9031    public void setOverscan(int displayId, int left, int top, int right, int bottom) {
9032        if (mContext.checkCallingOrSelfPermission(
9033                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
9034                PackageManager.PERMISSION_GRANTED) {
9035            throw new SecurityException("Must hold permission " +
9036                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
9037        }
9038        final long ident = Binder.clearCallingIdentity();
9039        try {
9040            synchronized(mWindowMap) {
9041                DisplayContent displayContent = getDisplayContentLocked(displayId);
9042                if (displayContent != null) {
9043                    setOverscanLocked(displayContent, left, top, right, bottom);
9044                }
9045            }
9046        } finally {
9047            Binder.restoreCallingIdentity(ident);
9048        }
9049    }
9050
9051    private void setOverscanLocked(DisplayContent displayContent,
9052            int left, int top, int right, int bottom) {
9053        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
9054        displayInfo.overscanLeft = left;
9055        displayInfo.overscanTop = top;
9056        displayInfo.overscanRight = right;
9057        displayInfo.overscanBottom = bottom;
9058
9059        mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top,
9060                right, bottom);
9061        mDisplaySettings.writeSettingsLocked();
9062
9063        reconfigureDisplayLocked(displayContent);
9064    }
9065
9066    // -------------------------------------------------------------
9067    // Internals
9068    // -------------------------------------------------------------
9069
9070    final WindowState windowForClientLocked(Session session, IWindow client,
9071            boolean throwOnError) {
9072        return windowForClientLocked(session, client.asBinder(), throwOnError);
9073    }
9074
9075    final WindowState windowForClientLocked(Session session, IBinder client,
9076            boolean throwOnError) {
9077        WindowState win = mWindowMap.get(client);
9078        if (localLOGV) Slog.v(
9079            TAG_WM, "Looking up client " + client + ": " + win);
9080        if (win == null) {
9081            RuntimeException ex = new IllegalArgumentException(
9082                    "Requested window " + client + " does not exist");
9083            if (throwOnError) {
9084                throw ex;
9085            }
9086            Slog.w(TAG_WM, "Failed looking up window", ex);
9087            return null;
9088        }
9089        if (session != null && win.mSession != session) {
9090            RuntimeException ex = new IllegalArgumentException(
9091                    "Requested window " + client + " is in session " +
9092                    win.mSession + ", not " + session);
9093            if (throwOnError) {
9094                throw ex;
9095            }
9096            Slog.w(TAG_WM, "Failed looking up window", ex);
9097            return null;
9098        }
9099
9100        return win;
9101    }
9102
9103    final void rebuildAppWindowListLocked() {
9104        rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
9105    }
9106
9107    private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
9108        final WindowList windows = displayContent.getWindowList();
9109        int NW = windows.size();
9110        int i;
9111        int lastBelow = -1;
9112        int numRemoved = 0;
9113
9114        if (mRebuildTmp.length < NW) {
9115            mRebuildTmp = new WindowState[NW+10];
9116        }
9117
9118        // First remove all existing app windows.
9119        i=0;
9120        while (i < NW) {
9121            WindowState w = windows.get(i);
9122            if (w.mAppToken != null) {
9123                WindowState win = windows.remove(i);
9124                win.mRebuilding = true;
9125                mRebuildTmp[numRemoved] = win;
9126                mWindowsChanged = true;
9127                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win);
9128                NW--;
9129                numRemoved++;
9130                continue;
9131            } else if (lastBelow == i-1) {
9132                if (w.mAttrs.type == TYPE_WALLPAPER) {
9133                    lastBelow = i;
9134                }
9135            }
9136            i++;
9137        }
9138
9139        // Keep whatever windows were below the app windows still below,
9140        // by skipping them.
9141        lastBelow++;
9142        i = lastBelow;
9143
9144        // First add all of the exiting app tokens...  these are no longer
9145        // in the main app list, but still have windows shown.  We put them
9146        // in the back because now that the animation is over we no longer
9147        // will care about them.
9148        final ArrayList<TaskStack> stacks = displayContent.getStacks();
9149        final int numStacks = stacks.size();
9150        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
9151            AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens;
9152            int NT = exitingAppTokens.size();
9153            for (int j = 0; j < NT; j++) {
9154                i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
9155            }
9156        }
9157
9158        // And add in the still active app tokens in Z order.
9159        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
9160            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9161            final int numTasks = tasks.size();
9162            for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
9163                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9164                final int numTokens = tokens.size();
9165                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
9166                    final AppWindowToken wtoken = tokens.get(tokenNdx);
9167                    if (wtoken.mIsExiting && !wtoken.waitingForReplacement()) {
9168                        continue;
9169                    }
9170                    i = reAddAppWindowsLocked(displayContent, i, wtoken);
9171                }
9172            }
9173        }
9174
9175        i -= lastBelow;
9176        if (i != numRemoved) {
9177            displayContent.layoutNeeded = true;
9178            Slog.w(TAG_WM, "On display=" + displayContent.getDisplayId() + " Rebuild removed "
9179                    + numRemoved + " windows but added " + i + " rebuildAppWindowListLocked() "
9180                    + " callers=" + Debug.getCallers(10));
9181            for (i = 0; i < numRemoved; i++) {
9182                WindowState ws = mRebuildTmp[i];
9183                if (ws.mRebuilding) {
9184                    StringWriter sw = new StringWriter();
9185                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
9186                    ws.dump(pw, "", true);
9187                    pw.flush();
9188                    Slog.w(TAG_WM, "This window was lost: " + ws);
9189                    Slog.w(TAG_WM, sw.toString());
9190                    ws.mWinAnimator.destroySurfaceLocked();
9191                }
9192            }
9193            Slog.w(TAG_WM, "Current app token list:");
9194            dumpAppTokensLocked();
9195            Slog.w(TAG_WM, "Final window list:");
9196            dumpWindowsLocked();
9197        }
9198        Arrays.fill(mRebuildTmp, null);
9199    }
9200
9201    void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
9202        // If the screen is currently frozen or off, then keep
9203        // it frozen/off until this window draws at its new
9204        // orientation.
9205        if (!okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
9206            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w);
9207            w.mOrientationChanging = true;
9208            w.mLastFreezeDuration = 0;
9209            mWindowPlacerLocked.mOrientationChangeComplete = false;
9210            if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) {
9211                mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
9212                // XXX should probably keep timeout from
9213                // when we first froze the display.
9214                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9215                mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
9216                        WINDOW_FREEZE_TIMEOUT_DURATION);
9217            }
9218        }
9219    }
9220
9221    /**
9222     * @return bitmap indicating if another pass through layout must be made.
9223     */
9224    int handleAnimatingStoppedAndTransitionLocked() {
9225        int changes = 0;
9226
9227        mAppTransition.setIdle();
9228
9229        for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) {
9230            final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i);
9231            mAppTransition.notifyAppTransitionFinishedLocked(token);
9232        }
9233        mNoAnimationNotifyOnTransitionFinished.clear();
9234
9235        mWallpaperControllerLocked.hideDeferredWallpapersIfNeeded();
9236
9237        // Restore window app tokens to the ActivityManager views
9238        ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks();
9239        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
9240            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9241            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9242                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9243                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9244                    tokens.get(tokenNdx).sendingToBottom = false;
9245                }
9246            }
9247        }
9248        rebuildAppWindowListLocked();
9249
9250        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
9251        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
9252                "Wallpaper layer changed: assigning layers + relayout");
9253        moveInputMethodWindowsIfNeededLocked(true);
9254        mWindowPlacerLocked.mWallpaperMayChange = true;
9255        // Since the window list has been rebuilt, focus might
9256        // have to be recomputed since the actual order of windows
9257        // might have changed again.
9258        mFocusMayChange = true;
9259
9260        return changes;
9261    }
9262
9263    void updateResizingWindows(final WindowState w) {
9264        final WindowStateAnimator winAnimator = w.mWinAnimator;
9265        if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq && !w.isGoneForLayoutLw()) {
9266            final Task task = w.getTask();
9267            // In the case of stack bound animations, the window frames
9268            // will update (unlike other animations which just modifiy
9269            // various transformation properties). We don't want to
9270            // notify the client of frame changes in this case. Not only
9271            // is it a lot of churn, but the frame may not correspond
9272            // to the surface size or the onscreen area at various
9273            // phases in the animation, and the client will become
9274            // sad and confused.
9275            if (task != null && task.mStack.getBoundsAnimating()) {
9276                return;
9277            }
9278            w.setInsetsChanged();
9279            boolean configChanged = w.isConfigChanged();
9280            if (DEBUG_CONFIGURATION && configChanged) {
9281                Slog.v(TAG_WM, "Win " + w + " config changed: "
9282                        + mCurConfiguration);
9283            }
9284            final boolean dragResizingChanged = w.isDragResizeChanged()
9285                    && !w.isDragResizingChangeReported();
9286            if (localLOGV) Slog.v(TAG_WM, "Resizing " + w
9287                    + ": configChanged=" + configChanged
9288                    + " dragResizingChanged=" + dragResizingChanged
9289                    + " last=" + w.mLastFrame + " frame=" + w.mFrame);
9290            w.mLastFrame.set(w.mFrame);
9291            if (w.mContentInsetsChanged
9292                    || w.mVisibleInsetsChanged
9293                    || winAnimator.mSurfaceResized
9294                    || w.mOutsetsChanged
9295                    || configChanged
9296                    || dragResizingChanged
9297                    || !w.isResizedWhileNotDragResizingReported()) {
9298                if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
9299                    Slog.v(TAG_WM, "Resize reasons for w=" + w + ": "
9300                            + " contentInsetsChanged=" + w.mContentInsetsChanged
9301                            + " " + w.mContentInsets.toShortString()
9302                            + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
9303                            + " " + w.mVisibleInsets.toShortString()
9304                            + " stableInsetsChanged=" + w.mStableInsetsChanged
9305                            + " " + w.mStableInsets.toShortString()
9306                            + " outsetsChanged=" + w.mOutsetsChanged
9307                            + " " + w.mOutsets.toShortString()
9308                            + " surfaceResized=" + winAnimator.mSurfaceResized
9309                            + " configChanged=" + configChanged
9310                            + " dragResizingChanged=" + dragResizingChanged
9311                            + " resizedWhileNotDragResizingReported="
9312                            + w.isResizedWhileNotDragResizingReported());
9313                }
9314
9315                // If it's a dead window left on screen, and the configuration changed,
9316                // there is nothing we can do about it. Remove the window now.
9317                if (w.mAppToken != null && w.mAppDied) {
9318                    w.mAppToken.removeAllDeadWindows();
9319                    return;
9320                }
9321
9322                w.mLastOverscanInsets.set(w.mOverscanInsets);
9323                w.mLastContentInsets.set(w.mContentInsets);
9324                w.mLastVisibleInsets.set(w.mVisibleInsets);
9325                w.mLastStableInsets.set(w.mStableInsets);
9326                w.mLastOutsets.set(w.mOutsets);
9327                makeWindowFreezingScreenIfNeededLocked(w);
9328                // If the orientation is changing, or we're starting or ending
9329                // a drag resizing action, then we need to hold off on unfreezing
9330                // the display until this window has been redrawn; to do that,
9331                // we need to go through the process of getting informed by the
9332                // application when it has finished drawing.
9333                if (w.mOrientationChanging || dragResizingChanged
9334                        || w.isResizedWhileNotDragResizing()) {
9335                    if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
9336                        Slog.v(TAG_WM, "Orientation or resize start waiting for draw"
9337                                + ", mDrawState=DRAW_PENDING in " + w
9338                                + ", surfaceController " + winAnimator.mSurfaceController);
9339                    }
9340                    winAnimator.mDrawState = DRAW_PENDING;
9341                    if (w.mAppToken != null) {
9342                        w.mAppToken.clearAllDrawn();
9343                    }
9344                }
9345                if (!mResizingWindows.contains(w)) {
9346                    if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG_WM,
9347                            "Resizing window " + w);
9348                    mResizingWindows.add(w);
9349                }
9350            } else if (w.mOrientationChanging) {
9351                if (w.isDrawnLw()) {
9352                    if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
9353                            "Orientation not waiting for draw in "
9354                            + w + ", surfaceController " + winAnimator.mSurfaceController);
9355                    w.mOrientationChanging = false;
9356                    w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
9357                            - mDisplayFreezeTime);
9358                }
9359            }
9360        }
9361    }
9362
9363    void checkDrawnWindowsLocked() {
9364        if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
9365            return;
9366        }
9367        for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
9368            WindowState win = mWaitingForDrawn.get(j);
9369            if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win +
9370                    ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
9371                    " mHasSurface=" + win.mHasSurface +
9372                    " drawState=" + win.mWinAnimator.mDrawState);
9373            if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) {
9374                // Window has been removed or hidden; no draw will now happen, so stop waiting.
9375                if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win);
9376                mWaitingForDrawn.remove(win);
9377            } else if (win.hasDrawnLw()) {
9378                // Window is now drawn (and shown).
9379                if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win);
9380                mWaitingForDrawn.remove(win);
9381            }
9382        }
9383        if (mWaitingForDrawn.isEmpty()) {
9384            if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!");
9385            mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
9386            mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
9387        }
9388    }
9389
9390    void setHoldScreenLocked(final Session newHoldScreen) {
9391        final boolean hold = newHoldScreen != null;
9392
9393        if (hold && mHoldingScreenOn != newHoldScreen) {
9394            mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
9395        }
9396        mHoldingScreenOn = newHoldScreen;
9397
9398        final boolean state = mHoldingScreenWakeLock.isHeld();
9399        if (hold != state) {
9400            if (hold) {
9401                if (DEBUG_KEEP_SCREEN_ON) {
9402                    Slog.d(TAG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to " +
9403                            mWindowPlacerLocked.mHoldScreenWindow);
9404                }
9405                mLastWakeLockHoldingWindow = mWindowPlacerLocked.mHoldScreenWindow;
9406                mLastWakeLockObscuringWindow = null;
9407                mHoldingScreenWakeLock.acquire();
9408                mPolicy.keepScreenOnStartedLw();
9409            } else {
9410                if (DEBUG_KEEP_SCREEN_ON) {
9411                    Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by " +
9412                            mWindowPlacerLocked.mObsuringWindow);
9413                }
9414                mLastWakeLockHoldingWindow = null;
9415                mLastWakeLockObscuringWindow = mWindowPlacerLocked.mObsuringWindow;
9416                mPolicy.keepScreenOnStoppedLw();
9417                mHoldingScreenWakeLock.release();
9418            }
9419        }
9420    }
9421
9422    void requestTraversal() {
9423        synchronized (mWindowMap) {
9424            mWindowPlacerLocked.requestTraversal();
9425        }
9426    }
9427
9428    /** Note that Locked in this case is on mLayoutToAnim */
9429    void scheduleAnimationLocked() {
9430        if (!mAnimationScheduled) {
9431            mAnimationScheduled = true;
9432            mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback);
9433        }
9434    }
9435
9436    boolean needsLayout() {
9437        final int numDisplays = mDisplayContents.size();
9438        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9439            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9440            if (displayContent.layoutNeeded) {
9441                return true;
9442            }
9443        }
9444        return false;
9445    }
9446
9447    /** If a window that has an animation specifying a colored background and the current wallpaper
9448     * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
9449     * suddenly disappear. */
9450    int adjustAnimationBackground(WindowStateAnimator winAnimator) {
9451        WindowList windows = winAnimator.mWin.getWindowList();
9452        for (int i = windows.size() - 1; i >= 0; --i) {
9453            WindowState testWin = windows.get(i);
9454            if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
9455                return testWin.mWinAnimator.mAnimLayer;
9456            }
9457        }
9458        return winAnimator.mAnimLayer;
9459    }
9460
9461    boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
9462                                           boolean secure) {
9463        final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
9464        boolean leakedSurface = false;
9465        boolean killedApps = false;
9466
9467        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
9468                winAnimator.mSession.mPid, operation);
9469
9470        final long callingIdentity = Binder.clearCallingIdentity();
9471        try {
9472            // There was some problem...   first, do a sanity check of the window list to make sure
9473            // we haven't left any dangling surfaces around.
9474
9475            Slog.i(TAG_WM, "Out of memory for surface!  Looking for leaks...");
9476            final int numDisplays = mDisplayContents.size();
9477            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9478                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9479                final int numWindows = windows.size();
9480                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9481                    final WindowState ws = windows.get(winNdx);
9482                    final WindowStateAnimator wsa = ws.mWinAnimator;
9483                    if (wsa.mSurfaceController == null) {
9484                        continue;
9485                    }
9486                    if (!mSessions.contains(wsa.mSession)) {
9487                        Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
9488                                + ws + " surface=" + wsa.mSurfaceController
9489                                + " token=" + ws.mToken
9490                                + " pid=" + ws.mSession.mPid
9491                                + " uid=" + ws.mSession.mUid);
9492                        wsa.destroySurface();
9493                        mForceRemoves.add(ws);
9494                        leakedSurface = true;
9495                    } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
9496                        Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
9497                                + ws + " surface=" + wsa.mSurfaceController
9498                                + " token=" + ws.mAppToken
9499                                + " saved=" + ws.hasSavedSurface());
9500                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
9501                        wsa.destroySurface();
9502                        leakedSurface = true;
9503                    }
9504                }
9505            }
9506
9507            if (!leakedSurface) {
9508                Slog.w(TAG_WM, "No leaked surfaces; killing applicatons!");
9509                SparseIntArray pidCandidates = new SparseIntArray();
9510                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9511                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9512                    final int numWindows = windows.size();
9513                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9514                        final WindowState ws = windows.get(winNdx);
9515                        if (mForceRemoves.contains(ws)) {
9516                            continue;
9517                        }
9518                        WindowStateAnimator wsa = ws.mWinAnimator;
9519                        if (wsa.mSurfaceController != null) {
9520                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
9521                        }
9522                    }
9523                    if (pidCandidates.size() > 0) {
9524                        int[] pids = new int[pidCandidates.size()];
9525                        for (int i=0; i<pids.length; i++) {
9526                            pids[i] = pidCandidates.keyAt(i);
9527                        }
9528                        try {
9529                            if (mActivityManager.killPids(pids, "Free memory", secure)) {
9530                                killedApps = true;
9531                            }
9532                        } catch (RemoteException e) {
9533                        }
9534                    }
9535                }
9536            }
9537
9538            if (leakedSurface || killedApps) {
9539                // We managed to reclaim some memory, so get rid of the trouble
9540                // surface and ask the app to request another one.
9541                Slog.w(TAG_WM, "Looks like we have reclaimed some memory, clearing surface for retry.");
9542                if (surfaceController != null) {
9543                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
9544                            "RECOVER DESTROY", false);
9545                    winAnimator.destroySurface();
9546                    scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken);
9547                }
9548
9549                try {
9550                    winAnimator.mWin.mClient.dispatchGetNewSurface();
9551                } catch (RemoteException e) {
9552                }
9553            }
9554        } finally {
9555            Binder.restoreCallingIdentity(callingIdentity);
9556        }
9557
9558        return leakedSurface || killedApps;
9559    }
9560
9561    boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
9562        WindowState newFocus = computeFocusedWindowLocked();
9563        if (mCurrentFocus != newFocus) {
9564            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
9565            // This check makes sure that we don't already have the focus
9566            // change message pending.
9567            mH.removeMessages(H.REPORT_FOCUS_CHANGE);
9568            mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
9569            // TODO(multidisplay): Focused windows on default display only.
9570            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9571            final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
9572                    mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
9573                            && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
9574            if (imWindowChanged) {
9575                displayContent.layoutNeeded = true;
9576                newFocus = computeFocusedWindowLocked();
9577            }
9578
9579            if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG_WM, "Changing focus from " +
9580                    mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
9581            final WindowState oldFocus = mCurrentFocus;
9582            mCurrentFocus = newFocus;
9583            mLosingFocus.remove(newFocus);
9584
9585            int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
9586
9587            if (imWindowChanged && oldFocus != mInputMethodWindow) {
9588                // Focus of the input method window changed. Perform layout if needed.
9589                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9590                    mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
9591                            updateInputWindows);
9592                    focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9593                } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
9594                    // Client will do the layout, but we need to assign layers
9595                    // for handleNewWindowLocked() below.
9596                    mLayersController.assignLayersLocked(displayContent.getWindowList());
9597                }
9598            }
9599
9600            if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9601                // The change in focus caused us to need to do a layout.  Okay.
9602                displayContent.layoutNeeded = true;
9603                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9604                    mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
9605                            updateInputWindows);
9606                }
9607            }
9608
9609            if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
9610                // If we defer assigning layers, then the caller is responsible for
9611                // doing this part.
9612                mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
9613            }
9614
9615            adjustForImeIfNeeded(displayContent);
9616
9617            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
9618            return true;
9619        }
9620        return false;
9621    }
9622
9623    private WindowState computeFocusedWindowLocked() {
9624        final int displayCount = mDisplayContents.size();
9625        for (int i = 0; i < displayCount; i++) {
9626            final DisplayContent displayContent = mDisplayContents.valueAt(i);
9627            WindowState win = findFocusedWindowLocked(displayContent);
9628            if (win != null) {
9629                return win;
9630            }
9631        }
9632        return null;
9633    }
9634
9635    WindowState findFocusedWindowLocked(DisplayContent displayContent) {
9636        final WindowList windows = displayContent.getWindowList();
9637        for (int i = windows.size() - 1; i >= 0; i--) {
9638            final WindowState win = windows.get(i);
9639
9640            if (localLOGV || DEBUG_FOCUS) Slog.v(
9641                TAG_WM, "Looking for focus: " + i
9642                + " = " + win
9643                + ", flags=" + win.mAttrs.flags
9644                + ", canReceive=" + win.canReceiveKeys());
9645
9646            if (!win.canReceiveKeys()) {
9647                continue;
9648            }
9649
9650            AppWindowToken wtoken = win.mAppToken;
9651
9652            // If this window's application has been removed, just skip it.
9653            if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
9654                if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
9655                        + (wtoken.removed ? "removed" : "sendingToBottom"));
9656                continue;
9657            }
9658
9659            // Descend through all of the app tokens and find the first that either matches
9660            // win.mAppToken (return win) or mFocusedApp (return null).
9661            if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
9662                    mFocusedApp != null) {
9663                ArrayList<Task> tasks = displayContent.getTasks();
9664                for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9665                    AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9666                    int tokenNdx = tokens.size() - 1;
9667                    for ( ; tokenNdx >= 0; --tokenNdx) {
9668                        final AppWindowToken token = tokens.get(tokenNdx);
9669                        if (wtoken == token) {
9670                            break;
9671                        }
9672                        if (mFocusedApp == token && token.windowsAreFocusable()) {
9673                            // Whoops, we are below the focused app whose windows are focusable...
9674                            // No focus for you!!!
9675                            if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
9676                                    "findFocusedWindow: Reached focused app=" + mFocusedApp);
9677                            return null;
9678                        }
9679                    }
9680                    if (tokenNdx >= 0) {
9681                        // Early exit from loop, must have found the matching token.
9682                        break;
9683                    }
9684                }
9685            }
9686
9687            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + i +
9688                        " = " + win);
9689            return win;
9690        }
9691
9692        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
9693        return null;
9694    }
9695
9696    private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
9697        if (mDisplayFrozen) {
9698            return;
9699        }
9700
9701        if (!mDisplayReady || !mPolicy.isScreenOn()) {
9702            // No need to freeze the screen before the system is ready or if
9703            // the screen is off.
9704            return;
9705        }
9706
9707        if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
9708                "startFreezingDisplayLocked: inTransaction=" + inTransaction
9709                + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim
9710                + " called by " + Debug.getCallers(8));
9711        mScreenFrozenLock.acquire();
9712
9713        mDisplayFrozen = true;
9714        mDisplayFreezeTime = SystemClock.elapsedRealtime();
9715        mLastFinishedFreezeSource = null;
9716
9717        mInputMonitor.freezeInputDispatchingLw();
9718
9719        // Clear the last input window -- that is just used for
9720        // clean transitions between IMEs, and if we are freezing
9721        // the screen then the whole world is changing behind the scenes.
9722        mPolicy.setLastInputMethodWindowLw(null, null);
9723
9724        if (mAppTransition.isTransitionSet()) {
9725            mAppTransition.freeze();
9726        }
9727
9728        if (PROFILE_ORIENTATION) {
9729            File file = new File("/data/system/frozen");
9730            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
9731        }
9732
9733        if (CUSTOM_SCREEN_ROTATION) {
9734            mExitAnimId = exitAnim;
9735            mEnterAnimId = enterAnim;
9736            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9737            final int displayId = displayContent.getDisplayId();
9738            ScreenRotationAnimation screenRotationAnimation =
9739                    mAnimator.getScreenRotationAnimationLocked(displayId);
9740            if (screenRotationAnimation != null) {
9741                screenRotationAnimation.kill();
9742            }
9743
9744            // Check whether the current screen contains any secure content.
9745            boolean isSecure = false;
9746            final WindowList windows = getDefaultWindowListLocked();
9747            final int N = windows.size();
9748            for (int i = 0; i < N; i++) {
9749                WindowState ws = windows.get(i);
9750                if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
9751                    isSecure = true;
9752                    break;
9753                }
9754            }
9755
9756            // TODO(multidisplay): rotation on main screen only.
9757            displayContent.updateDisplayInfo();
9758            screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
9759                    mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure);
9760            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9761        }
9762    }
9763
9764    void stopFreezingDisplayLocked() {
9765        if (!mDisplayFrozen) {
9766            return;
9767        }
9768
9769        if (mWaitingForConfig || mAppsFreezingScreen > 0
9770                || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE
9771                || mClientFreezingScreen || !mOpeningApps.isEmpty()) {
9772            if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
9773                "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
9774                + ", mAppsFreezingScreen=" + mAppsFreezingScreen
9775                + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
9776                + ", mClientFreezingScreen=" + mClientFreezingScreen
9777                + ", mOpeningApps.size()=" + mOpeningApps.size());
9778            return;
9779        }
9780
9781        if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
9782                "stopFreezingDisplayLocked: Unfreezing now");
9783
9784        mDisplayFrozen = false;
9785        mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
9786        StringBuilder sb = new StringBuilder(128);
9787        sb.append("Screen frozen for ");
9788        TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
9789        if (mLastFinishedFreezeSource != null) {
9790            sb.append(" due to ");
9791            sb.append(mLastFinishedFreezeSource);
9792        }
9793        Slog.i(TAG_WM, sb.toString());
9794        mH.removeMessages(H.APP_FREEZE_TIMEOUT);
9795        mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
9796        if (PROFILE_ORIENTATION) {
9797            Debug.stopMethodTracing();
9798        }
9799
9800        boolean updateRotation = false;
9801
9802        final DisplayContent displayContent = getDefaultDisplayContentLocked();
9803        final int displayId = displayContent.getDisplayId();
9804        ScreenRotationAnimation screenRotationAnimation =
9805                mAnimator.getScreenRotationAnimationLocked(displayId);
9806        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
9807                && screenRotationAnimation.hasScreenshot()) {
9808            if (DEBUG_ORIENTATION) Slog.i(TAG_WM, "**** Dismissing screen rotation animation");
9809            // TODO(multidisplay): rotation on main screen only.
9810            DisplayInfo displayInfo = displayContent.getDisplayInfo();
9811            // Get rotation animation again, with new top window
9812            boolean isDimming = displayContent.isDimming();
9813            if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
9814                mExitAnimId = mEnterAnimId = 0;
9815            }
9816            if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
9817                    getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
9818                        displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
9819                scheduleAnimationLocked();
9820            } else {
9821                screenRotationAnimation.kill();
9822                mAnimator.setScreenRotationAnimationLocked(displayId, null);
9823                updateRotation = true;
9824            }
9825        } else {
9826            if (screenRotationAnimation != null) {
9827                screenRotationAnimation.kill();
9828                mAnimator.setScreenRotationAnimationLocked(displayId, null);
9829            }
9830            updateRotation = true;
9831        }
9832
9833        mInputMonitor.thawInputDispatchingLw();
9834
9835        boolean configChanged;
9836
9837        // While the display is frozen we don't re-compute the orientation
9838        // to avoid inconsistent states.  However, something interesting
9839        // could have actually changed during that time so re-evaluate it
9840        // now to catch that.
9841        configChanged = updateOrientationFromAppTokensLocked(false);
9842
9843        // A little kludge: a lot could have happened while the
9844        // display was frozen, so now that we are coming back we
9845        // do a gc so that any remote references the system
9846        // processes holds on others can be released if they are
9847        // no longer needed.
9848        mH.removeMessages(H.FORCE_GC);
9849        mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
9850
9851        mScreenFrozenLock.release();
9852
9853        if (updateRotation) {
9854            if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation");
9855            configChanged |= updateRotationUncheckedLocked(false);
9856        }
9857
9858        if (configChanged) {
9859            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9860        }
9861    }
9862
9863    static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
9864            DisplayMetrics dm) {
9865        if (index < tokens.length) {
9866            String str = tokens[index];
9867            if (str != null && str.length() > 0) {
9868                try {
9869                    int val = Integer.parseInt(str);
9870                    return val;
9871                } catch (Exception e) {
9872                }
9873            }
9874        }
9875        if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
9876            return defDps;
9877        }
9878        int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
9879        return val;
9880    }
9881
9882    void createWatermarkInTransaction() {
9883        if (mWatermark != null) {
9884            return;
9885        }
9886
9887        File file = new File("/system/etc/setup.conf");
9888        FileInputStream in = null;
9889        DataInputStream ind = null;
9890        try {
9891            in = new FileInputStream(file);
9892            ind = new DataInputStream(in);
9893            String line = ind.readLine();
9894            if (line != null) {
9895                String[] toks = line.split("%");
9896                if (toks != null && toks.length > 0) {
9897                    mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
9898                            mRealDisplayMetrics, mFxSession, toks);
9899                }
9900            }
9901        } catch (FileNotFoundException e) {
9902        } catch (IOException e) {
9903        } finally {
9904            if (ind != null) {
9905                try {
9906                    ind.close();
9907                } catch (IOException e) {
9908                }
9909            } else if (in != null) {
9910                try {
9911                    in.close();
9912                } catch (IOException e) {
9913                }
9914            }
9915        }
9916    }
9917
9918    @Override
9919    public void statusBarVisibilityChanged(int visibility) {
9920        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
9921                != PackageManager.PERMISSION_GRANTED) {
9922            throw new SecurityException("Caller does not hold permission "
9923                    + android.Manifest.permission.STATUS_BAR);
9924        }
9925
9926        synchronized (mWindowMap) {
9927            mLastStatusBarVisibility = visibility;
9928            visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
9929            updateStatusBarVisibilityLocked(visibility);
9930        }
9931    }
9932
9933    // TOOD(multidisplay): StatusBar on multiple screens?
9934    boolean updateStatusBarVisibilityLocked(int visibility) {
9935        if (mLastDispatchedSystemUiVisibility == visibility) {
9936            return false;
9937        }
9938        final int globalDiff = (visibility ^ mLastDispatchedSystemUiVisibility)
9939                // We are only interested in differences of one of the
9940                // clearable flags...
9941                & View.SYSTEM_UI_CLEARABLE_FLAGS
9942                // ...if it has actually been cleared.
9943                & ~visibility;
9944
9945        mLastDispatchedSystemUiVisibility = visibility;
9946        mInputManager.setSystemUiVisibility(visibility);
9947        final WindowList windows = getDefaultWindowListLocked();
9948        final int N = windows.size();
9949        for (int i = 0; i < N; i++) {
9950            WindowState ws = windows.get(i);
9951            try {
9952                int curValue = ws.mSystemUiVisibility;
9953                int diff = (curValue ^ visibility) & globalDiff;
9954                int newValue = (curValue&~diff) | (visibility&diff);
9955                if (newValue != curValue) {
9956                    ws.mSeq++;
9957                    ws.mSystemUiVisibility = newValue;
9958                }
9959                if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
9960                    ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
9961                            visibility, newValue, diff);
9962                }
9963            } catch (RemoteException e) {
9964                // so sorry
9965            }
9966        }
9967        return true;
9968    }
9969
9970    @Override
9971    public void reevaluateStatusBarVisibility() {
9972        synchronized (mWindowMap) {
9973            int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
9974            if (updateStatusBarVisibilityLocked(visibility)) {
9975                mWindowPlacerLocked.requestTraversal();
9976            }
9977        }
9978    }
9979
9980    private static final class HideNavInputConsumer extends InputConsumerImpl
9981            implements WindowManagerPolicy.InputConsumer {
9982        private final InputEventReceiver mInputEventReceiver;
9983
9984        HideNavInputConsumer(WindowManagerService service, Looper looper,
9985                             InputEventReceiver.Factory inputEventReceiverFactory) {
9986            super(service, "input consumer", null);
9987            mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver(
9988                    mClientChannel, looper);
9989        }
9990
9991        @Override
9992        public void dismiss() {
9993            if (mService.removeInputConsumer()) {
9994                synchronized (mService.mWindowMap) {
9995                    mInputEventReceiver.dispose();
9996                    disposeChannelsLw();
9997                }
9998            }
9999        }
10000    }
10001
10002    @Override
10003    public WindowManagerPolicy.InputConsumer addInputConsumer(Looper looper,
10004            InputEventReceiver.Factory inputEventReceiverFactory) {
10005        synchronized (mWindowMap) {
10006            HideNavInputConsumer inputConsumerImpl = new HideNavInputConsumer(
10007                    this, looper, inputEventReceiverFactory);
10008            mInputConsumer = inputConsumerImpl;
10009            mInputMonitor.updateInputWindowsLw(true);
10010            return inputConsumerImpl;
10011        }
10012    }
10013
10014    boolean removeInputConsumer() {
10015        synchronized (mWindowMap) {
10016            if (mInputConsumer != null) {
10017                mInputConsumer = null;
10018                mInputMonitor.updateInputWindowsLw(true);
10019                return true;
10020            }
10021            return false;
10022        }
10023    }
10024
10025    public void createWallpaperInputConsumer(InputChannel inputChannel) {
10026        synchronized (mWindowMap) {
10027            mWallpaperInputConsumer = new InputConsumerImpl(this, "wallpaper input", inputChannel);
10028            mWallpaperInputConsumer.mWindowHandle.hasWallpaper = true;
10029            mInputMonitor.updateInputWindowsLw(true);
10030        }
10031    }
10032
10033    public void removeWallpaperInputConsumer() {
10034        synchronized (mWindowMap) {
10035            if (mWallpaperInputConsumer != null) {
10036                mWallpaperInputConsumer.disposeChannelsLw();
10037                mWallpaperInputConsumer = null;
10038                mInputMonitor.updateInputWindowsLw(true);
10039            }
10040        }
10041    }
10042
10043    @Override
10044    public boolean hasNavigationBar() {
10045        return mPolicy.hasNavigationBar();
10046    }
10047
10048    @Override
10049    public void lockNow(Bundle options) {
10050        mPolicy.lockNow(options);
10051    }
10052
10053    public void showRecentApps(boolean fromHome) {
10054        mPolicy.showRecentApps(fromHome);
10055    }
10056
10057    @Override
10058    public boolean isSafeModeEnabled() {
10059        return mSafeMode;
10060    }
10061
10062    @Override
10063    public boolean clearWindowContentFrameStats(IBinder token) {
10064        if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10065                "clearWindowContentFrameStats()")) {
10066            throw new SecurityException("Requires FRAME_STATS permission");
10067        }
10068        synchronized (mWindowMap) {
10069            WindowState windowState = mWindowMap.get(token);
10070            if (windowState == null) {
10071                return false;
10072            }
10073            WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
10074            if (surfaceController == null) {
10075                return false;
10076            }
10077            return surfaceController.clearWindowContentFrameStats();
10078        }
10079    }
10080
10081    @Override
10082    public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
10083        if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10084                "getWindowContentFrameStats()")) {
10085            throw new SecurityException("Requires FRAME_STATS permission");
10086        }
10087        synchronized (mWindowMap) {
10088            WindowState windowState = mWindowMap.get(token);
10089            if (windowState == null) {
10090                return null;
10091            }
10092            WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
10093            if (surfaceController == null) {
10094                return null;
10095            }
10096            if (mTempWindowRenderStats == null) {
10097                mTempWindowRenderStats = new WindowContentFrameStats();
10098            }
10099            WindowContentFrameStats stats = mTempWindowRenderStats;
10100            if (!surfaceController.getWindowContentFrameStats(stats)) {
10101                return null;
10102            }
10103            return stats;
10104        }
10105    }
10106
10107    public void notifyAppRelaunching(IBinder token) {
10108        synchronized (mWindowMap) {
10109            AppWindowToken appWindow = findAppWindowToken(token);
10110            if (appWindow != null) {
10111                appWindow.startRelaunching();
10112            }
10113        }
10114    }
10115
10116    public void notifyAppRelaunchingFinished(IBinder token) {
10117        synchronized (mWindowMap) {
10118            AppWindowToken appWindow = findAppWindowToken(token);
10119            if (appWindow != null) {
10120                appWindow.finishRelaunching();
10121            }
10122        }
10123    }
10124
10125    @Override
10126    public int getDockedDividerInsetsLw() {
10127        return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets();
10128    }
10129
10130    void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10131        pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
10132        mPolicy.dump("    ", pw, args);
10133    }
10134
10135    void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10136        pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
10137        mAnimator.dumpLocked(pw, "    ", dumpAll);
10138    }
10139
10140    void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
10141        pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
10142        if (!mTokenMap.isEmpty()) {
10143            pw.println("  All tokens:");
10144            Iterator<WindowToken> it = mTokenMap.values().iterator();
10145            while (it.hasNext()) {
10146                WindowToken token = it.next();
10147                pw.print("  "); pw.print(token);
10148                if (dumpAll) {
10149                    pw.println(':');
10150                    token.dump(pw, "    ");
10151                } else {
10152                    pw.println();
10153                }
10154            }
10155        }
10156        mWallpaperControllerLocked.dumpTokens(pw, "  ", dumpAll);
10157        if (!mFinishedStarting.isEmpty()) {
10158            pw.println();
10159            pw.println("  Finishing start of application tokens:");
10160            for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10161                WindowToken token = mFinishedStarting.get(i);
10162                pw.print("  Finished Starting #"); pw.print(i);
10163                        pw.print(' '); pw.print(token);
10164                if (dumpAll) {
10165                    pw.println(':');
10166                    token.dump(pw, "    ");
10167                } else {
10168                    pw.println();
10169                }
10170            }
10171        }
10172        if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) {
10173            pw.println();
10174            if (mOpeningApps.size() > 0) {
10175                pw.print("  mOpeningApps="); pw.println(mOpeningApps);
10176            }
10177            if (mClosingApps.size() > 0) {
10178                pw.print("  mClosingApps="); pw.println(mClosingApps);
10179            }
10180        }
10181    }
10182
10183    void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
10184        pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
10185        for (int i=0; i<mSessions.size(); i++) {
10186            Session s = mSessions.valueAt(i);
10187            pw.print("  Session "); pw.print(s); pw.println(':');
10188            s.dump(pw, "    ");
10189        }
10190    }
10191
10192    void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
10193        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
10194        if (mDisplayReady) {
10195            final int numDisplays = mDisplayContents.size();
10196            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10197                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10198                displayContent.dump("  ", pw);
10199            }
10200        } else {
10201            pw.println("  NO DISPLAY");
10202        }
10203    }
10204
10205    void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
10206            ArrayList<WindowState> windows) {
10207        pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
10208        dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
10209    }
10210
10211    void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
10212            ArrayList<WindowState> windows) {
10213        final int numDisplays = mDisplayContents.size();
10214        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10215            final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
10216            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10217                final WindowState w = windowList.get(winNdx);
10218                if (windows == null || windows.contains(w)) {
10219                    pw.print("  Window #"); pw.print(winNdx); pw.print(' ');
10220                            pw.print(w); pw.println(":");
10221                    w.dump(pw, "    ", dumpAll || windows != null);
10222                }
10223            }
10224        }
10225        if (mInputMethodDialogs.size() > 0) {
10226            pw.println();
10227            pw.println("  Input method dialogs:");
10228            for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10229                WindowState w = mInputMethodDialogs.get(i);
10230                if (windows == null || windows.contains(w)) {
10231                    pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
10232                }
10233            }
10234        }
10235        if (mPendingRemove.size() > 0) {
10236            pw.println();
10237            pw.println("  Remove pending for:");
10238            for (int i=mPendingRemove.size()-1; i>=0; i--) {
10239                WindowState w = mPendingRemove.get(i);
10240                if (windows == null || windows.contains(w)) {
10241                    pw.print("  Remove #"); pw.print(i); pw.print(' ');
10242                            pw.print(w);
10243                    if (dumpAll) {
10244                        pw.println(":");
10245                        w.dump(pw, "    ", true);
10246                    } else {
10247                        pw.println();
10248                    }
10249                }
10250            }
10251        }
10252        if (mForceRemoves != null && mForceRemoves.size() > 0) {
10253            pw.println();
10254            pw.println("  Windows force removing:");
10255            for (int i=mForceRemoves.size()-1; i>=0; i--) {
10256                WindowState w = mForceRemoves.get(i);
10257                pw.print("  Removing #"); pw.print(i); pw.print(' ');
10258                        pw.print(w);
10259                if (dumpAll) {
10260                    pw.println(":");
10261                    w.dump(pw, "    ", true);
10262                } else {
10263                    pw.println();
10264                }
10265            }
10266        }
10267        if (mDestroySurface.size() > 0) {
10268            pw.println();
10269            pw.println("  Windows waiting to destroy their surface:");
10270            for (int i=mDestroySurface.size()-1; i>=0; i--) {
10271                WindowState w = mDestroySurface.get(i);
10272                if (windows == null || windows.contains(w)) {
10273                    pw.print("  Destroy #"); pw.print(i); pw.print(' ');
10274                            pw.print(w);
10275                    if (dumpAll) {
10276                        pw.println(":");
10277                        w.dump(pw, "    ", true);
10278                    } else {
10279                        pw.println();
10280                    }
10281                }
10282            }
10283        }
10284        if (mLosingFocus.size() > 0) {
10285            pw.println();
10286            pw.println("  Windows losing focus:");
10287            for (int i=mLosingFocus.size()-1; i>=0; i--) {
10288                WindowState w = mLosingFocus.get(i);
10289                if (windows == null || windows.contains(w)) {
10290                    pw.print("  Losing #"); pw.print(i); pw.print(' ');
10291                            pw.print(w);
10292                    if (dumpAll) {
10293                        pw.println(":");
10294                        w.dump(pw, "    ", true);
10295                    } else {
10296                        pw.println();
10297                    }
10298                }
10299            }
10300        }
10301        if (mResizingWindows.size() > 0) {
10302            pw.println();
10303            pw.println("  Windows waiting to resize:");
10304            for (int i=mResizingWindows.size()-1; i>=0; i--) {
10305                WindowState w = mResizingWindows.get(i);
10306                if (windows == null || windows.contains(w)) {
10307                    pw.print("  Resizing #"); pw.print(i); pw.print(' ');
10308                            pw.print(w);
10309                    if (dumpAll) {
10310                        pw.println(":");
10311                        w.dump(pw, "    ", true);
10312                    } else {
10313                        pw.println();
10314                    }
10315                }
10316            }
10317        }
10318        if (mWaitingForDrawn.size() > 0) {
10319            pw.println();
10320            pw.println("  Clients waiting for these windows to be drawn:");
10321            for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
10322                WindowState win = mWaitingForDrawn.get(i);
10323                pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
10324            }
10325        }
10326        pw.println();
10327        pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
10328        pw.print("  mHasPermanentDpad="); pw.println(mHasPermanentDpad);
10329        pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
10330        if (mLastFocus != mCurrentFocus) {
10331            pw.print("  mLastFocus="); pw.println(mLastFocus);
10332        }
10333        pw.print("  mFocusedApp="); pw.println(mFocusedApp);
10334        if (mInputMethodTarget != null) {
10335            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
10336        }
10337        pw.print("  mInTouchMode="); pw.print(mInTouchMode);
10338                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
10339        pw.print("  mLastDisplayFreezeDuration=");
10340                TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
10341                if ( mLastFinishedFreezeSource != null) {
10342                    pw.print(" due to ");
10343                    pw.print(mLastFinishedFreezeSource);
10344                }
10345                pw.println();
10346        pw.print("  mLastWakeLockHoldingWindow=");pw.print(mLastWakeLockHoldingWindow);
10347                pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow);
10348                pw.println();
10349
10350        mInputMonitor.dump(pw, "  ");
10351
10352        if (dumpAll) {
10353            pw.print("  mSystemDecorLayer="); pw.print(mSystemDecorLayer);
10354                    pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
10355            if (mLastStatusBarVisibility != 0) {
10356                pw.print("  mLastStatusBarVisibility=0x");
10357                        pw.println(Integer.toHexString(mLastStatusBarVisibility));
10358            }
10359            if (mInputMethodWindow != null) {
10360                pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
10361            }
10362            mWindowPlacerLocked.dump(pw, "  ");
10363            mWallpaperControllerLocked.dump(pw, "  ");
10364            mLayersController.dump(pw, "  ");
10365            pw.print("  mSystemBooted="); pw.print(mSystemBooted);
10366                    pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10367            if (needsLayout()) {
10368                pw.print("  layoutNeeded on displays=");
10369                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10370                    final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10371                    if (displayContent.layoutNeeded) {
10372                        pw.print(displayContent.getDisplayId());
10373                    }
10374                }
10375                pw.println();
10376            }
10377            pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
10378            pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
10379                    pw.print(" windows="); pw.print(mWindowsFreezingScreen);
10380                    pw.print(" client="); pw.print(mClientFreezingScreen);
10381                    pw.print(" apps="); pw.print(mAppsFreezingScreen);
10382                    pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
10383            pw.print("  mRotation="); pw.print(mRotation);
10384                    pw.print(" mAltOrientation="); pw.println(mAltOrientation);
10385            pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
10386                    pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
10387            pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
10388            pw.print("  Animation settings: disabled="); pw.print(mAnimationsDisabled);
10389                    pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
10390                    pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
10391                    pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
10392            pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation);
10393            pw.println("  mLayoutToAnim:");
10394            mAppTransition.dump(pw, "    ");
10395        }
10396    }
10397
10398    boolean dumpWindows(PrintWriter pw, String name, String[] args,
10399            int opti, boolean dumpAll) {
10400        WindowList windows = new WindowList();
10401        if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
10402            final boolean appsOnly = name.contains("apps");
10403            final boolean visibleOnly = name.contains("visible");
10404            synchronized(mWindowMap) {
10405                if (appsOnly) {
10406                    dumpDisplayContentsLocked(pw, true);
10407                }
10408
10409                final int numDisplays = mDisplayContents.size();
10410                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10411                    final WindowList windowList =
10412                            mDisplayContents.valueAt(displayNdx).getWindowList();
10413                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10414                        final WindowState w = windowList.get(winNdx);
10415                        if ((!visibleOnly || w.mWinAnimator.getShown())
10416                                && (!appsOnly || w.mAppToken != null)) {
10417                            windows.add(w);
10418                        }
10419                    }
10420                }
10421            }
10422        } else {
10423            int objectId = 0;
10424            // See if this is an object ID.
10425            try {
10426                objectId = Integer.parseInt(name, 16);
10427                name = null;
10428            } catch (RuntimeException e) {
10429            }
10430            synchronized(mWindowMap) {
10431                final int numDisplays = mDisplayContents.size();
10432                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10433                    final WindowList windowList =
10434                            mDisplayContents.valueAt(displayNdx).getWindowList();
10435                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10436                        final WindowState w = windowList.get(winNdx);
10437                        if (name != null) {
10438                            if (w.mAttrs.getTitle().toString().contains(name)) {
10439                                windows.add(w);
10440                            }
10441                        } else if (System.identityHashCode(w) == objectId) {
10442                            windows.add(w);
10443                        }
10444                    }
10445                }
10446            }
10447        }
10448
10449        if (windows.size() <= 0) {
10450            return false;
10451        }
10452
10453        synchronized(mWindowMap) {
10454            dumpWindowsLocked(pw, dumpAll, windows);
10455        }
10456        return true;
10457    }
10458
10459    void dumpLastANRLocked(PrintWriter pw) {
10460        pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
10461        if (mLastANRState == null) {
10462            pw.println("  <no ANR has occurred since boot>");
10463        } else {
10464            pw.println(mLastANRState);
10465        }
10466    }
10467
10468    /**
10469     * Saves information about the state of the window manager at
10470     * the time an ANR occurred before anything else in the system changes
10471     * in response.
10472     *
10473     * @param appWindowToken The application that ANR'd, may be null.
10474     * @param windowState The window that ANR'd, may be null.
10475     * @param reason The reason for the ANR, may be null.
10476     */
10477    public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
10478            String reason) {
10479        StringWriter sw = new StringWriter();
10480        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
10481        pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
10482        if (appWindowToken != null) {
10483            pw.println("  Application at fault: " + appWindowToken.stringName);
10484        }
10485        if (windowState != null) {
10486            pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
10487        }
10488        if (reason != null) {
10489            pw.println("  Reason: " + reason);
10490        }
10491        pw.println();
10492        dumpWindowsNoHeaderLocked(pw, true, null);
10493        pw.println();
10494        pw.println("Last ANR continued");
10495        dumpDisplayContentsLocked(pw, true);
10496        pw.close();
10497        mLastANRState = sw.toString();
10498
10499        mH.removeMessages(H.RESET_ANR_MESSAGE);
10500        mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS);
10501    }
10502
10503    @Override
10504    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10505        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
10506                != PackageManager.PERMISSION_GRANTED) {
10507            pw.println("Permission Denial: can't dump WindowManager from from pid="
10508                    + Binder.getCallingPid()
10509                    + ", uid=" + Binder.getCallingUid());
10510            return;
10511        }
10512
10513        boolean dumpAll = false;
10514
10515        int opti = 0;
10516        while (opti < args.length) {
10517            String opt = args[opti];
10518            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10519                break;
10520            }
10521            opti++;
10522            if ("-a".equals(opt)) {
10523                dumpAll = true;
10524            } else if ("-h".equals(opt)) {
10525                pw.println("Window manager dump options:");
10526                pw.println("  [-a] [-h] [cmd] ...");
10527                pw.println("  cmd may be one of:");
10528                pw.println("    l[astanr]: last ANR information");
10529                pw.println("    p[policy]: policy state");
10530                pw.println("    a[animator]: animator state");
10531                pw.println("    s[essions]: active sessions");
10532                pw.println("    surfaces: active surfaces (debugging enabled only)");
10533                pw.println("    d[isplays]: active display contents");
10534                pw.println("    t[okens]: token list");
10535                pw.println("    w[indows]: window list");
10536                pw.println("  cmd may also be a NAME to dump windows.  NAME may");
10537                pw.println("    be a partial substring in a window name, a");
10538                pw.println("    Window hex object identifier, or");
10539                pw.println("    \"all\" for all windows, or");
10540                pw.println("    \"visible\" for the visible windows.");
10541                pw.println("    \"visible-apps\" for the visible app windows.");
10542                pw.println("  -a: include all available server state.");
10543                return;
10544            } else {
10545                pw.println("Unknown argument: " + opt + "; use -h for help");
10546            }
10547        }
10548
10549        // Is the caller requesting to dump a particular piece of data?
10550        if (opti < args.length) {
10551            String cmd = args[opti];
10552            opti++;
10553            if ("lastanr".equals(cmd) || "l".equals(cmd)) {
10554                synchronized(mWindowMap) {
10555                    dumpLastANRLocked(pw);
10556                }
10557                return;
10558            } else if ("policy".equals(cmd) || "p".equals(cmd)) {
10559                synchronized(mWindowMap) {
10560                    dumpPolicyLocked(pw, args, true);
10561                }
10562                return;
10563            } else if ("animator".equals(cmd) || "a".equals(cmd)) {
10564                synchronized(mWindowMap) {
10565                    dumpAnimatorLocked(pw, args, true);
10566                }
10567                return;
10568            } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
10569                synchronized(mWindowMap) {
10570                    dumpSessionsLocked(pw, true);
10571                }
10572                return;
10573            } else if ("surfaces".equals(cmd)) {
10574                synchronized(mWindowMap) {
10575                    WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, null);
10576                }
10577                return;
10578            } else if ("displays".equals(cmd) || "d".equals(cmd)) {
10579                synchronized(mWindowMap) {
10580                    dumpDisplayContentsLocked(pw, true);
10581                }
10582                return;
10583            } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
10584                synchronized(mWindowMap) {
10585                    dumpTokensLocked(pw, true);
10586                }
10587                return;
10588            } else if ("windows".equals(cmd) || "w".equals(cmd)) {
10589                synchronized(mWindowMap) {
10590                    dumpWindowsLocked(pw, true, null);
10591                }
10592                return;
10593            } else if ("all".equals(cmd) || "a".equals(cmd)) {
10594                synchronized(mWindowMap) {
10595                    dumpWindowsLocked(pw, true, null);
10596                }
10597                return;
10598            } else {
10599                // Dumping a single name?
10600                if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
10601                    pw.println("Bad window command, or no windows match: " + cmd);
10602                    pw.println("Use -h for help.");
10603                }
10604                return;
10605            }
10606        }
10607
10608        synchronized(mWindowMap) {
10609            pw.println();
10610            if (dumpAll) {
10611                pw.println("-------------------------------------------------------------------------------");
10612            }
10613            dumpLastANRLocked(pw);
10614            pw.println();
10615            if (dumpAll) {
10616                pw.println("-------------------------------------------------------------------------------");
10617            }
10618            dumpPolicyLocked(pw, args, dumpAll);
10619            pw.println();
10620            if (dumpAll) {
10621                pw.println("-------------------------------------------------------------------------------");
10622            }
10623            dumpAnimatorLocked(pw, args, dumpAll);
10624            pw.println();
10625            if (dumpAll) {
10626                pw.println("-------------------------------------------------------------------------------");
10627            }
10628            dumpSessionsLocked(pw, dumpAll);
10629            pw.println();
10630            if (dumpAll) {
10631                pw.println("-------------------------------------------------------------------------------");
10632            }
10633            WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ?
10634                    "-------------------------------------------------------------------------------"
10635                    : null);
10636            pw.println();
10637            if (dumpAll) {
10638                pw.println("-------------------------------------------------------------------------------");
10639            }
10640            dumpDisplayContentsLocked(pw, dumpAll);
10641            pw.println();
10642            if (dumpAll) {
10643                pw.println("-------------------------------------------------------------------------------");
10644            }
10645            dumpTokensLocked(pw, dumpAll);
10646            pw.println();
10647            if (dumpAll) {
10648                pw.println("-------------------------------------------------------------------------------");
10649            }
10650            dumpWindowsLocked(pw, dumpAll, null);
10651        }
10652    }
10653
10654    // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
10655    @Override
10656    public void monitor() {
10657        synchronized (mWindowMap) { }
10658    }
10659
10660    private DisplayContent newDisplayContentLocked(final Display display) {
10661        DisplayContent displayContent = new DisplayContent(display, this);
10662        final int displayId = display.getDisplayId();
10663        if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
10664        mDisplayContents.put(displayId, displayContent);
10665
10666        DisplayInfo displayInfo = displayContent.getDisplayInfo();
10667        final Rect rect = new Rect();
10668        mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
10669        displayInfo.overscanLeft = rect.left;
10670        displayInfo.overscanTop = rect.top;
10671        displayInfo.overscanRight = rect.right;
10672        displayInfo.overscanBottom = rect.bottom;
10673        mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId, displayInfo);
10674        configureDisplayPolicyLocked(displayContent);
10675
10676        // TODO: Create an input channel for each display with touch capability.
10677        if (displayId == Display.DEFAULT_DISPLAY) {
10678            displayContent.mTapDetector = new TaskTapPointerEventListener(this, displayContent);
10679            registerPointerEventListener(displayContent.mTapDetector);
10680            registerPointerEventListener(mMousePositionTracker);
10681        }
10682
10683        return displayContent;
10684    }
10685
10686    public void createDisplayContentLocked(final Display display) {
10687        if (display == null) {
10688            throw new IllegalArgumentException("getDisplayContent: display must not be null");
10689        }
10690        getDisplayContentLocked(display.getDisplayId());
10691    }
10692
10693    /**
10694     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
10695     * there is a Display for the displayId.
10696     * @param displayId The display the caller is interested in.
10697     * @return The DisplayContent associated with displayId or null if there is no Display for it.
10698     */
10699    public DisplayContent getDisplayContentLocked(final int displayId) {
10700        DisplayContent displayContent = mDisplayContents.get(displayId);
10701        if (displayContent == null) {
10702            final Display display = mDisplayManager.getDisplay(displayId);
10703            if (display != null) {
10704                displayContent = newDisplayContentLocked(display);
10705            }
10706        }
10707        return displayContent;
10708    }
10709
10710    // There is an inherent assumption that this will never return null.
10711    public DisplayContent getDefaultDisplayContentLocked() {
10712        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
10713    }
10714
10715    public WindowList getDefaultWindowListLocked() {
10716        return getDefaultDisplayContentLocked().getWindowList();
10717    }
10718
10719    public DisplayInfo getDefaultDisplayInfoLocked() {
10720        return getDefaultDisplayContentLocked().getDisplayInfo();
10721    }
10722
10723    /**
10724     * Return the list of WindowStates associated on the passed display.
10725     * @param display The screen to return windows from.
10726     * @return The list of WindowStates on the screen, or null if the there is no screen.
10727     */
10728    public WindowList getWindowListLocked(final Display display) {
10729        return getWindowListLocked(display.getDisplayId());
10730    }
10731
10732    /**
10733     * Return the list of WindowStates associated on the passed display.
10734     * @param displayId The screen to return windows from.
10735     * @return The list of WindowStates on the screen, or null if the there is no screen.
10736     */
10737    public WindowList getWindowListLocked(final int displayId) {
10738        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10739        return displayContent != null ? displayContent.getWindowList() : null;
10740    }
10741
10742    public void onDisplayAdded(int displayId) {
10743        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
10744    }
10745
10746    public void handleDisplayAdded(int displayId) {
10747        synchronized (mWindowMap) {
10748            final Display display = mDisplayManager.getDisplay(displayId);
10749            if (display != null) {
10750                createDisplayContentLocked(display);
10751                displayReady(displayId);
10752            }
10753            mWindowPlacerLocked.requestTraversal();
10754        }
10755    }
10756
10757    public void onDisplayRemoved(int displayId) {
10758        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
10759    }
10760
10761    private void handleDisplayRemovedLocked(int displayId) {
10762        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10763        if (displayContent != null) {
10764            if (displayContent.isAnimating()) {
10765                displayContent.mDeferredRemoval = true;
10766                return;
10767            }
10768            if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + displayContent);
10769            mDisplayContents.delete(displayId);
10770            displayContent.close();
10771            if (displayId == Display.DEFAULT_DISPLAY) {
10772                unregisterPointerEventListener(displayContent.mTapDetector);
10773                unregisterPointerEventListener(mMousePositionTracker);
10774            }
10775        }
10776        mAnimator.removeDisplayLocked(displayId);
10777        mWindowPlacerLocked.requestTraversal();
10778    }
10779
10780    public void onDisplayChanged(int displayId) {
10781        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
10782    }
10783
10784    private void handleDisplayChangedLocked(int displayId) {
10785        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10786        if (displayContent != null) {
10787            displayContent.updateDisplayInfo();
10788        }
10789        mWindowPlacerLocked.requestTraversal();
10790    }
10791
10792    @Override
10793    public Object getWindowManagerLock() {
10794        return mWindowMap;
10795    }
10796
10797    /**
10798     * Hint to a token that its activity will relaunch, which will trigger removal and addition of
10799     * a window.
10800     * @param token Application token for which the activity will be relaunched.
10801     */
10802    public void setReplacingWindow(IBinder token, boolean animate) {
10803        AppWindowToken appWindowToken = null;
10804        synchronized (mWindowMap) {
10805            appWindowToken = findAppWindowToken(token);
10806            if (appWindowToken == null || !appWindowToken.isVisible()) {
10807                Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
10808                        + token);
10809                return;
10810            }
10811            appWindowToken.setReplacingWindows(animate);
10812        }
10813    }
10814
10815    /**
10816     * Hint to a token that its windows will be replaced across activity relaunch.
10817     * The windows would otherwise be removed  shortly following this as the
10818     * activity is torn down.
10819     * @param token Application token for which the activity will be relaunched.
10820     * @param childrenOnly Whether to mark only child windows for replacement
10821     *                     (for the case where main windows are being preserved/
10822     *                     reused rather than replaced).
10823     *
10824     */
10825    public void setReplacingWindows(IBinder token, boolean childrenOnly) {
10826        AppWindowToken appWindowToken = null;
10827        synchronized (mWindowMap) {
10828            appWindowToken = findAppWindowToken(token);
10829            if (appWindowToken == null || !appWindowToken.isVisible()) {
10830                Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
10831                        + token);
10832                return;
10833            }
10834
10835            if (childrenOnly) {
10836                appWindowToken.setReplacingChildren();
10837            } else {
10838                appWindowToken.setReplacingWindows(false /* animate */);
10839            }
10840
10841            scheduleClearReplacingWindowIfNeeded(token, true /* replacing */);
10842        }
10843    }
10844
10845    /**
10846     * If we're replacing the window, schedule a timer to clear the replaced window
10847     * after a timeout, in case the replacing window is not coming.
10848     *
10849     * If we're not replacing the window, clear the replace window settings of the app.
10850     *
10851     * @param token Application token for the activity whose window might be replaced.
10852     * @param replacing Whether the window is being replaced or not.
10853     */
10854    public void scheduleClearReplacingWindowIfNeeded(IBinder token, boolean replacing) {
10855        AppWindowToken appWindowToken = null;
10856        synchronized (mWindowMap) {
10857            appWindowToken = findAppWindowToken(token);
10858            if (appWindowToken == null) {
10859                Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token "
10860                        + token);
10861                return;
10862            }
10863            if (replacing) {
10864                scheduleReplacingWindowTimeouts(appWindowToken);
10865            } else {
10866                appWindowToken.resetReplacingWindows();
10867            }
10868        }
10869    }
10870
10871    void scheduleReplacingWindowTimeouts(AppWindowToken appWindowToken) {
10872        if (!mReplacingWindowTimeouts.contains(appWindowToken)) {
10873            mReplacingWindowTimeouts.add(appWindowToken);
10874        }
10875        mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
10876        mH.sendEmptyMessageDelayed(
10877                H.WINDOW_REPLACEMENT_TIMEOUT, WINDOW_REPLACEMENT_TIMEOUT_DURATION);
10878    }
10879
10880    @Override
10881    public int getDockedStackSide() {
10882        synchronized (mWindowMap) {
10883            final TaskStack dockedStack = getDefaultDisplayContentLocked()
10884                    .getDockedStackVisibleForUserLocked();
10885            return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide();
10886        }
10887    }
10888
10889    @Override
10890    public void setDockedStackResizing(boolean resizing) {
10891        synchronized (mWindowMap) {
10892            getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing);
10893            requestTraversal();
10894        }
10895    }
10896
10897    @Override
10898    public void setDockedStackDividerTouchRegion(Rect touchRegion) {
10899        synchronized (mWindowMap) {
10900            getDefaultDisplayContentLocked().getDockedDividerController()
10901                    .setTouchRegion(touchRegion);
10902            setFocusTaskRegionLocked();
10903        }
10904    }
10905
10906    @Override
10907    public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
10908        synchronized (mWindowMap) {
10909            getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer(
10910                    visible, targetStackId, alpha);
10911        }
10912    }
10913
10914    public void animateResizePinnedStack(final Rect bounds, final int animationDuration) {
10915        synchronized (mWindowMap) {
10916            final TaskStack stack = mStackIdToStack.get(PINNED_STACK_ID);
10917            if (stack == null) {
10918                Slog.w(TAG, "animateResizePinnedStack: stackId " + PINNED_STACK_ID + " not found.");
10919                return;
10920            }
10921            final Rect originalBounds = new Rect();
10922            stack.getBounds(originalBounds);
10923            UiThread.getHandler().post(new Runnable() {
10924                @Override
10925                public void run() {
10926                    mBoundsAnimationController.animateBounds(
10927                            stack, originalBounds, bounds, animationDuration);
10928                }
10929            });
10930        }
10931    }
10932
10933    public void setTaskResizeable(int taskId, int resizeMode) {
10934        synchronized (mWindowMap) {
10935            final Task task = mTaskIdToTask.get(taskId);
10936            if (task != null) {
10937                task.setResizeable(resizeMode);
10938            }
10939        }
10940    }
10941
10942    public void setForceResizableTasks(boolean forceResizableTasks) {
10943        synchronized (mWindowMap) {
10944            mForceResizableTasks = forceResizableTasks;
10945        }
10946    }
10947
10948    static int dipToPixel(int dip, DisplayMetrics displayMetrics) {
10949        return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
10950    }
10951
10952    @Override
10953    public void registerDockedStackListener(IDockedStackListener listener) {
10954        if (!checkCallingPermission(android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS,
10955                "registerDockedStackListener()")) {
10956            return;
10957        }
10958        // TODO(multi-display): The listener is registered on the default display only.
10959        getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener(
10960                listener);
10961    }
10962
10963    @Override
10964    public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
10965        try {
10966            WindowState focusedWindow = getFocusedWindow();
10967            if (focusedWindow != null && focusedWindow.mClient != null) {
10968                getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId);
10969            }
10970        } catch (RemoteException e) {
10971        }
10972    }
10973
10974    @Override
10975    public void getStableInsets(Rect outInsets) throws RemoteException {
10976        synchronized (mWindowMap) {
10977            getStableInsetsLocked(outInsets);
10978        }
10979    }
10980
10981    void getStableInsetsLocked(Rect outInsets) {
10982        final DisplayInfo di = getDefaultDisplayInfoLocked();
10983        mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
10984    }
10985
10986    private void getNonDecorInsetsLocked(Rect outInsets) {
10987        final DisplayInfo di = getDefaultDisplayInfoLocked();
10988        mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
10989    }
10990
10991    /**
10992     * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
10993     * inset areas.
10994     *
10995     * @param inOutBounds The inOutBounds to subtract the stable inset areas from.
10996     */
10997    public void subtractStableInsets(Rect inOutBounds) {
10998        synchronized (mWindowMap) {
10999            getStableInsetsLocked(mTmpRect2);
11000            final DisplayInfo di = getDefaultDisplayInfoLocked();
11001            mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
11002            subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
11003        }
11004    }
11005
11006    /**
11007     * Intersects the specified {@code inOutBounds} with the display frame that excludes
11008     * areas that could never be removed in Honeycomb. See
11009     * {@link WindowManagerPolicy#getNonDecorInsetsLw}.
11010     *
11011     * @param inOutBounds The inOutBounds to subtract the inset areas from.
11012     */
11013    public void subtractNonDecorInsets(Rect inOutBounds) {
11014        synchronized (mWindowMap) {
11015            getNonDecorInsetsLocked(mTmpRect2);
11016            final DisplayInfo di = getDefaultDisplayInfoLocked();
11017            mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
11018            subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
11019        }
11020    }
11021
11022    void subtractInsets(Rect display, Rect insets, Rect inOutBounds) {
11023        mTmpRect3.set(display);
11024        mTmpRect3.inset(insets);
11025        inOutBounds.intersect(mTmpRect3);
11026    }
11027
11028    /**
11029     * Calculates the smallest width for a task given the {@param bounds}. It does that by iterating
11030     * across all screen orientations, and returns the minimum of the task width taking into account
11031     * that the bounds might change because the snap algorithm snaps to a different value.
11032     *
11033     * @return the smallest width to be used in the Configuration, in dips
11034     */
11035    public int getSmallestWidthForTaskBounds(Rect bounds) {
11036        synchronized (mWindowMap) {
11037            return getDefaultDisplayContentLocked().getDockedDividerController()
11038                    .getSmallestWidthDpForBounds(bounds);
11039        }
11040    }
11041
11042    private MousePositionTracker mMousePositionTracker = new MousePositionTracker();
11043
11044    private static class MousePositionTracker implements PointerEventListener {
11045        private boolean mLatestEventWasMouse;
11046        private float mLatestMouseX;
11047        private float mLatestMouseY;
11048
11049        void updatePosition(float x, float y) {
11050            synchronized (this) {
11051                mLatestEventWasMouse = true;
11052                mLatestMouseX = x;
11053                mLatestMouseY = y;
11054            }
11055        }
11056
11057        @Override
11058        public void onPointerEvent(MotionEvent motionEvent) {
11059            if (motionEvent.isFromSource(InputDevice.SOURCE_MOUSE)) {
11060                updatePosition(motionEvent.getRawX(), motionEvent.getRawY());
11061            } else {
11062                synchronized (this) {
11063                    mLatestEventWasMouse = false;
11064                }
11065            }
11066        }
11067    };
11068
11069    void updatePointerIcon(IWindow client) {
11070        float mouseX, mouseY;
11071
11072        synchronized(mMousePositionTracker) {
11073            if (!mMousePositionTracker.mLatestEventWasMouse) {
11074                return;
11075            }
11076            mouseX = mMousePositionTracker.mLatestMouseX;
11077            mouseY = mMousePositionTracker.mLatestMouseY;
11078        }
11079
11080        synchronized (mWindowMap) {
11081            if (mDragState != null) {
11082                // Drag cursor overrides the app cursor.
11083                return;
11084            }
11085            WindowState callingWin = windowForClientLocked(null, client, false);
11086            if (callingWin == null) {
11087                Slog.w(TAG_WM, "Bad requesting window " + client);
11088                return;
11089            }
11090            final DisplayContent displayContent = callingWin.getDisplayContent();
11091            if (displayContent == null) {
11092                return;
11093            }
11094            WindowState windowUnderPointer =
11095                    displayContent.getTouchableWinAtPointLocked(mouseX, mouseY);
11096            if (windowUnderPointer != callingWin) {
11097                return;
11098            }
11099            try {
11100                windowUnderPointer.mClient.updatePointerIcon(
11101                        windowUnderPointer.translateToWindowX(mouseX),
11102                        windowUnderPointer.translateToWindowY(mouseY));
11103            } catch (RemoteException e) {
11104                Slog.w(TAG_WM, "unable to update pointer icon");
11105            }
11106        }
11107    }
11108
11109    void restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY) {
11110        // Mouse position tracker has not been getting updates while dragging, update it now.
11111        mMousePositionTracker.updatePosition(latestX, latestY);
11112
11113        WindowState windowUnderPointer =
11114                displayContent.getTouchableWinAtPointLocked(latestX, latestY);
11115        if (windowUnderPointer != null) {
11116            try {
11117                windowUnderPointer.mClient.updatePointerIcon(
11118                        windowUnderPointer.translateToWindowX(latestX),
11119                        windowUnderPointer.translateToWindowY(latestY));
11120            } catch (RemoteException e) {
11121                Slog.w(TAG_WM, "unable to restore pointer icon");
11122            }
11123        } else {
11124            InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_DEFAULT);
11125        }
11126    }
11127
11128    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
11129            throws RemoteException {
11130        if (!checkCallingPermission(Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS,
11131                "registerShortcutKey")) {
11132            throw new SecurityException(
11133                    "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission");
11134        }
11135        mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
11136    }
11137
11138    private final class LocalService extends WindowManagerInternal {
11139        @Override
11140        public void requestTraversalFromDisplayManager() {
11141            requestTraversal();
11142        }
11143
11144        @Override
11145        public void setMagnificationSpec(MagnificationSpec spec) {
11146            synchronized (mWindowMap) {
11147                if (mAccessibilityController != null) {
11148                    mAccessibilityController.setMagnificationSpecLocked(spec);
11149                } else {
11150                    throw new IllegalStateException("Magnification callbacks not set!");
11151                }
11152            }
11153            if (Binder.getCallingPid() != android.os.Process.myPid()) {
11154                spec.recycle();
11155            }
11156        }
11157
11158        @Override
11159        public void getMagnificationRegion(@NonNull Region magnificationRegion) {
11160            synchronized (mWindowMap) {
11161                if (mAccessibilityController != null) {
11162                    mAccessibilityController.getMagnificationRegionLocked(magnificationRegion);
11163                } else {
11164                    throw new IllegalStateException("Magnification callbacks not set!");
11165                }
11166            }
11167        }
11168
11169        @Override
11170        public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
11171            synchronized (mWindowMap) {
11172                WindowState windowState = mWindowMap.get(windowToken);
11173                if (windowState == null) {
11174                    return null;
11175                }
11176                MagnificationSpec spec = null;
11177                if (mAccessibilityController != null) {
11178                    spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState);
11179                }
11180                if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
11181                    return null;
11182                }
11183                spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
11184                spec.scale *= windowState.mGlobalScale;
11185                return spec;
11186            }
11187        }
11188
11189        @Override
11190        public void setMagnificationCallbacks(@Nullable MagnificationCallbacks callbacks) {
11191            synchronized (mWindowMap) {
11192                if (mAccessibilityController == null) {
11193                    mAccessibilityController = new AccessibilityController(
11194                            WindowManagerService.this);
11195                }
11196                mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
11197                if (!mAccessibilityController.hasCallbacksLocked()) {
11198                    mAccessibilityController = null;
11199                }
11200            }
11201        }
11202
11203        @Override
11204        public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
11205            synchronized (mWindowMap) {
11206                if (mAccessibilityController == null) {
11207                    mAccessibilityController = new AccessibilityController(
11208                            WindowManagerService.this);
11209                }
11210                mAccessibilityController.setWindowsForAccessibilityCallback(callback);
11211                if (!mAccessibilityController.hasCallbacksLocked()) {
11212                    mAccessibilityController = null;
11213                }
11214            }
11215        }
11216
11217        @Override
11218        public void setInputFilter(IInputFilter filter) {
11219            mInputManager.setInputFilter(filter);
11220        }
11221
11222        @Override
11223        public IBinder getFocusedWindowToken() {
11224            synchronized (mWindowMap) {
11225                WindowState windowState = getFocusedWindowLocked();
11226                if (windowState != null) {
11227                    return windowState.mClient.asBinder();
11228                }
11229                return null;
11230            }
11231        }
11232
11233        @Override
11234        public boolean isKeyguardLocked() {
11235            return WindowManagerService.this.isKeyguardLocked();
11236        }
11237
11238        @Override
11239        public void showGlobalActions() {
11240            WindowManagerService.this.showGlobalActions();
11241        }
11242
11243        @Override
11244        public void getWindowFrame(IBinder token, Rect outBounds) {
11245            synchronized (mWindowMap) {
11246                WindowState windowState = mWindowMap.get(token);
11247                if (windowState != null) {
11248                    outBounds.set(windowState.mFrame);
11249                } else {
11250                    outBounds.setEmpty();
11251                }
11252            }
11253        }
11254
11255        @Override
11256        public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
11257            boolean allWindowsDrawn = false;
11258            synchronized (mWindowMap) {
11259                mWaitingForDrawnCallback = callback;
11260                final WindowList windows = getDefaultWindowListLocked();
11261                for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
11262                    final WindowState win = windows.get(winNdx);
11263                    final boolean isForceHiding = mPolicy.isForceHiding(win.mAttrs);
11264                    if (win.isVisibleLw()
11265                            && (win.mAppToken != null || isForceHiding)) {
11266                        win.mWinAnimator.mDrawState = DRAW_PENDING;
11267                        // Force add to mResizingWindows.
11268                        win.mLastContentInsets.set(-1, -1, -1, -1);
11269                        mWaitingForDrawn.add(win);
11270
11271                        // No need to wait for the windows below Keyguard.
11272                        if (isForceHiding) {
11273                            break;
11274                        }
11275                    }
11276                }
11277                mWindowPlacerLocked.requestTraversal();
11278                mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
11279                if (mWaitingForDrawn.isEmpty()) {
11280                    allWindowsDrawn = true;
11281                } else {
11282                    mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
11283                    checkDrawnWindowsLocked();
11284                }
11285            }
11286            if (allWindowsDrawn) {
11287                callback.run();
11288            }
11289        }
11290
11291        @Override
11292        public void addWindowToken(IBinder token, int type) {
11293            WindowManagerService.this.addWindowToken(token, type);
11294        }
11295
11296        @Override
11297        public void removeWindowToken(IBinder token, boolean removeWindows) {
11298            synchronized(mWindowMap) {
11299                if (removeWindows) {
11300                    WindowToken wtoken = mTokenMap.remove(token);
11301                    if (wtoken != null) {
11302                        wtoken.removeAllWindows();
11303                    }
11304                }
11305                WindowManagerService.this.removeWindowToken(token);
11306            }
11307        }
11308
11309        @Override
11310        public void registerAppTransitionListener(AppTransitionListener listener) {
11311            synchronized (mWindowMap) {
11312                mAppTransition.registerListenerLocked(listener);
11313            }
11314        }
11315
11316        @Override
11317        public int getInputMethodWindowVisibleHeight() {
11318            synchronized (mWindowMap) {
11319                return mPolicy.getInputMethodWindowVisibleHeightLw();
11320            }
11321        }
11322
11323        @Override
11324        public void saveLastInputMethodWindowForTransition() {
11325            synchronized (mWindowMap) {
11326                if (mInputMethodWindow != null) {
11327                    mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
11328                }
11329            }
11330        }
11331
11332        @Override
11333        public void clearLastInputMethodWindowForTransition() {
11334            synchronized (mWindowMap) {
11335                mPolicy.setLastInputMethodWindowLw(null, null);
11336            }
11337        }
11338
11339        @Override
11340        public boolean isHardKeyboardAvailable() {
11341            synchronized (mWindowMap) {
11342                return mHardKeyboardAvailable;
11343            }
11344        }
11345
11346        @Override
11347        public void setOnHardKeyboardStatusChangeListener(
11348                OnHardKeyboardStatusChangeListener listener) {
11349            synchronized (mWindowMap) {
11350                mHardKeyboardStatusChangeListener = listener;
11351            }
11352        }
11353
11354        @Override
11355        public boolean isStackVisible(int stackId) {
11356            synchronized (mWindowMap) {
11357                return WindowManagerService.this.isStackVisibleLocked(stackId);
11358            }
11359        }
11360
11361        @Override
11362        public boolean isDockedDividerResizing() {
11363            synchronized (mWindowMap) {
11364                return getDefaultDisplayContentLocked().getDockedDividerController().isResizing();
11365            }
11366        }
11367    }
11368}
11369