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