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