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