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