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