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