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