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