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