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