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