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