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