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