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