WindowManagerService.java revision adf85cac3acc6f132c15b0f05d902a12f5777e38
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);
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 upper region of the screen based on the vertical dimension
6010     * of the target image.
6011     *
6012     * @param displayId the Display to take a screenshot of.
6013     * @param width the width of the target bitmap
6014     * @param height the height of the target bitmap
6015     * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
6016     */
6017    @Override
6018    public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height,
6019            float frameScale) {
6020        if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
6021                "screenshotApplications()")) {
6022            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
6023        }
6024        try {
6025            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotApplications");
6026            return screenshotApplicationsInner(appToken, displayId, width, height, false,
6027                    frameScale);
6028        } finally {
6029            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
6030        }
6031    }
6032
6033    Bitmap screenshotApplicationsInner(IBinder appToken, int displayId, int width, int height,
6034            boolean includeFullDisplay, float frameScale) {
6035        final DisplayContent displayContent;
6036        synchronized(mWindowMap) {
6037            displayContent = getDisplayContentLocked(displayId);
6038            if (displayContent == null) {
6039                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
6040                        + ": returning null. No Display for displayId=" + displayId);
6041                return null;
6042            }
6043        }
6044        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6045        int dw = displayInfo.logicalWidth;
6046        int dh = displayInfo.logicalHeight;
6047        if (dw == 0 || dh == 0) {
6048            if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
6049                    + ": returning null. logical widthxheight=" + dw + "x" + dh);
6050            return null;
6051        }
6052
6053        Bitmap bm = null;
6054
6055        int maxLayer = 0;
6056        final Rect frame = new Rect();
6057        final Rect stackBounds = new Rect();
6058
6059        boolean screenshotReady;
6060        int minLayer;
6061        if (appToken == null) {
6062            screenshotReady = true;
6063            minLayer = 0;
6064        } else {
6065            screenshotReady = false;
6066            minLayer = Integer.MAX_VALUE;
6067        }
6068
6069        WindowState appWin = null;
6070
6071        boolean appIsImTarget;
6072        synchronized(mWindowMap) {
6073            appIsImTarget = mInputMethodTarget != null
6074                    && mInputMethodTarget.mAppToken != null
6075                    && mInputMethodTarget.mAppToken.appToken != null
6076                    && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
6077        }
6078
6079        final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
6080                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
6081
6082        synchronized(mWindowMap) {
6083            // Figure out the part of the screen that is actually the app.
6084            appWin = null;
6085            final WindowList windows = displayContent.getWindowList();
6086            for (int i = windows.size() - 1; i >= 0; i--) {
6087                WindowState ws = windows.get(i);
6088                if (!ws.mHasSurface) {
6089                    continue;
6090                }
6091                if (ws.mLayer >= aboveAppLayer) {
6092                    continue;
6093                }
6094                if (ws.mIsImWindow) {
6095                    if (!appIsImTarget) {
6096                        continue;
6097                    }
6098                } else if (ws.mIsWallpaper) {
6099                    if (appWin == null) {
6100                        // We have not ran across the target window yet, so it is probably
6101                        // behind the wallpaper. This can happen when the keyguard is up and
6102                        // all windows are moved behind the wallpaper. We don't want to
6103                        // include the wallpaper layer in the screenshot as it will coverup
6104                        // the layer of the target window.
6105                        continue;
6106                    }
6107                    // Fall through. The target window is in front of the wallpaper. For this
6108                    // case we want to include the wallpaper layer in the screenshot because
6109                    // the target window might have some transparent areas.
6110                } else if (appToken != null) {
6111                    if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
6112                        // This app window is of no interest if it is not associated with the
6113                        // screenshot app.
6114                        continue;
6115                    }
6116                    appWin = ws;
6117                }
6118
6119                // Include this window.
6120
6121                final WindowStateAnimator winAnim = ws.mWinAnimator;
6122                int layer = winAnim.mSurfaceController.getLayer();
6123                if (maxLayer < layer) {
6124                    maxLayer = layer;
6125                }
6126                if (minLayer > layer) {
6127                    minLayer = layer;
6128                }
6129
6130                // Don't include wallpaper in bounds calculation
6131                if (!includeFullDisplay && !ws.mIsWallpaper) {
6132                    final Rect wf = ws.mFrame;
6133                    final Rect cr = ws.mContentInsets;
6134                    int left = wf.left + cr.left;
6135                    int top = wf.top + cr.top;
6136                    int right = wf.right - cr.right;
6137                    int bottom = wf.bottom - cr.bottom;
6138                    frame.union(left, top, right, bottom);
6139                    ws.getVisibleBounds(stackBounds);
6140                    if (!Rect.intersects(frame, stackBounds)) {
6141                        // Set frame empty if there's no intersection.
6142                        frame.setEmpty();
6143                    }
6144                }
6145
6146                if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
6147                        ws.isDisplayedLw() && winAnim.getShown()) {
6148                    screenshotReady = true;
6149                }
6150
6151                if (ws.isObscuringFullscreen(displayInfo)){
6152                    break;
6153                }
6154            }
6155
6156            if (appToken != null && appWin == null) {
6157                // Can't find a window to snapshot.
6158                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM,
6159                        "Screenshot: Couldn't find a surface matching " + appToken);
6160                return null;
6161            }
6162
6163            if (!screenshotReady) {
6164                Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken +
6165                        " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
6166                        appWin.mWinAnimator.mDrawState)));
6167                return null;
6168            }
6169
6170            // Screenshot is ready to be taken. Everything from here below will continue
6171            // through the bottom of the loop and return a value. We only stay in the loop
6172            // because we don't want to release the mWindowMap lock until the screenshot is
6173            // taken.
6174
6175            if (maxLayer == 0) {
6176                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
6177                        + ": returning null maxLayer=" + maxLayer);
6178                return null;
6179            }
6180
6181            if (!includeFullDisplay) {
6182                // Constrain frame to the screen size.
6183                if (!frame.intersect(0, 0, dw, dh)) {
6184                    frame.setEmpty();
6185                }
6186            } else {
6187                // Caller just wants entire display.
6188                frame.set(0, 0, dw, dh);
6189            }
6190            if (frame.isEmpty()) {
6191                return null;
6192            }
6193
6194            if (width < 0) {
6195                width = (int) (frame.width() * frameScale);
6196            }
6197            if (height < 0) {
6198                height = (int) (frame.height() * frameScale);
6199            }
6200
6201            // Tell surface flinger what part of the image to crop. Take the top
6202            // right part of the application, and crop the larger dimension to fit.
6203            Rect crop = new Rect(frame);
6204            if (width / (float) frame.width() < height / (float) frame.height()) {
6205                int cropWidth = (int)((float)width / (float)height * frame.height());
6206                crop.right = crop.left + cropWidth;
6207            } else {
6208                int cropHeight = (int)((float)height / (float)width * frame.width());
6209                crop.bottom = crop.top + cropHeight;
6210            }
6211
6212            // The screenshot API does not apply the current screen rotation.
6213            int rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
6214
6215            if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
6216                rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
6217            }
6218
6219            // Surfaceflinger is not aware of orientation, so convert our logical
6220            // crop to surfaceflinger's portrait orientation.
6221            convertCropForSurfaceFlinger(crop, rot, dw, dh);
6222
6223            if (DEBUG_SCREENSHOT) {
6224                Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
6225                        + maxLayer + " appToken=" + appToken);
6226                for (int i = 0; i < windows.size(); i++) {
6227                    WindowState win = windows.get(i);
6228                    Slog.i(TAG_WM, win + ": " + win.mLayer
6229                            + " animLayer=" + win.mWinAnimator.mAnimLayer
6230                            + " surfaceLayer=" + win.mWinAnimator.mSurfaceController.getLayer());
6231                }
6232            }
6233
6234            ScreenRotationAnimation screenRotationAnimation =
6235                    mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6236            final boolean inRotation = screenRotationAnimation != null &&
6237                    screenRotationAnimation.isAnimating();
6238            if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM,
6239                    "Taking screenshot while rotating");
6240
6241            bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
6242                    inRotation, rot);
6243            if (bm == null) {
6244                Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh
6245                        + ") to layer " + maxLayer);
6246                return null;
6247            }
6248        }
6249
6250        if (DEBUG_SCREENSHOT) {
6251            // TEST IF IT's ALL BLACK
6252            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
6253            bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
6254            boolean allBlack = true;
6255            final int firstColor = buffer[0];
6256            for (int i = 0; i < buffer.length; i++) {
6257                if (buffer[i] != firstColor) {
6258                    allBlack = false;
6259                    break;
6260                }
6261            }
6262            if (allBlack) {
6263                Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" +
6264                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
6265                        (appWin != null ?
6266                                appWin.mWinAnimator.mSurfaceController.getLayer() : "null") +
6267                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
6268            }
6269        }
6270
6271        // Create a copy of the screenshot that is immutable and backed in ashmem.
6272        // This greatly reduces the overhead of passing the bitmap between processes.
6273        Bitmap ret = bm.createAshmemBitmap();
6274        bm.recycle();
6275        return ret;
6276    }
6277
6278    /**
6279     * Freeze rotation changes.  (Enable "rotation lock".)
6280     * Persists across reboots.
6281     * @param rotation The desired rotation to freeze to, or -1 to use the
6282     * current rotation.
6283     */
6284    @Override
6285    public void freezeRotation(int rotation) {
6286        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
6287                "freezeRotation()")) {
6288            throw new SecurityException("Requires SET_ORIENTATION permission");
6289        }
6290        if (rotation < -1 || rotation > Surface.ROTATION_270) {
6291            throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
6292                    + "rotation constant.");
6293        }
6294
6295        if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "freezeRotation: mRotation=" + mRotation);
6296
6297        long origId = Binder.clearCallingIdentity();
6298        try {
6299            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
6300                    rotation == -1 ? mRotation : rotation);
6301        } finally {
6302            Binder.restoreCallingIdentity(origId);
6303        }
6304
6305        updateRotationUnchecked(false, false);
6306    }
6307
6308    /**
6309     * Thaw rotation changes.  (Disable "rotation lock".)
6310     * Persists across reboots.
6311     */
6312    @Override
6313    public void thawRotation() {
6314        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
6315                "thawRotation()")) {
6316            throw new SecurityException("Requires SET_ORIENTATION permission");
6317        }
6318
6319        if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "thawRotation: mRotation=" + mRotation);
6320
6321        long origId = Binder.clearCallingIdentity();
6322        try {
6323            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
6324                    777); // rot not used
6325        } finally {
6326            Binder.restoreCallingIdentity(origId);
6327        }
6328
6329        updateRotationUnchecked(false, false);
6330    }
6331
6332    /**
6333     * Recalculate the current rotation.
6334     *
6335     * Called by the window manager policy whenever the state of the system changes
6336     * such that the current rotation might need to be updated, such as when the
6337     * device is docked or rotated into a new posture.
6338     */
6339    @Override
6340    public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
6341        updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
6342    }
6343
6344    /**
6345     * Temporarily pauses rotation changes until resumed.
6346     *
6347     * This can be used to prevent rotation changes from occurring while the user is
6348     * performing certain operations, such as drag and drop.
6349     *
6350     * This call nests and must be matched by an equal number of calls to
6351     * {@link #resumeRotationLocked}.
6352     */
6353    void pauseRotationLocked() {
6354        mDeferredRotationPauseCount += 1;
6355    }
6356
6357    /**
6358     * Resumes normal rotation changes after being paused.
6359     */
6360    void resumeRotationLocked() {
6361        if (mDeferredRotationPauseCount > 0) {
6362            mDeferredRotationPauseCount -= 1;
6363            if (mDeferredRotationPauseCount == 0) {
6364                boolean changed = updateRotationUncheckedLocked(false);
6365                if (changed) {
6366                    mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6367                }
6368            }
6369        }
6370    }
6371
6372    public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
6373        if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked("
6374                   + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
6375
6376        long origId = Binder.clearCallingIdentity();
6377        boolean changed;
6378        synchronized(mWindowMap) {
6379            changed = updateRotationUncheckedLocked(false);
6380            if (!changed || forceRelayout) {
6381                getDefaultDisplayContentLocked().layoutNeeded = true;
6382                mWindowPlacerLocked.performSurfacePlacement();
6383            }
6384        }
6385
6386        if (changed || alwaysSendConfiguration) {
6387            sendNewConfiguration();
6388        }
6389
6390        Binder.restoreCallingIdentity(origId);
6391    }
6392
6393    // TODO(multidisplay): Rotate any display?
6394    /**
6395     * Updates the current rotation.
6396     *
6397     * Returns true if the rotation has been changed.  In this case YOU
6398     * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
6399     */
6400    public boolean updateRotationUncheckedLocked(boolean inTransaction) {
6401        if (mDeferredRotationPauseCount > 0) {
6402            // Rotation updates have been paused temporarily.  Defer the update until
6403            // updates have been resumed.
6404            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");
6405            return false;
6406        }
6407
6408        ScreenRotationAnimation screenRotationAnimation =
6409                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6410        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
6411            // Rotation updates cannot be performed while the previous rotation change
6412            // animation is still in progress.  Skip this update.  We will try updating
6413            // again after the animation is finished and the display is unfrozen.
6414            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");
6415            return false;
6416        }
6417
6418        if (!mDisplayEnabled) {
6419            // No point choosing a rotation if the display is not enabled.
6420            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled.");
6421            return false;
6422        }
6423
6424        // TODO: Implement forced rotation changes.
6425        //       Set mAltOrientation to indicate that the application is receiving
6426        //       an orientation that has different metrics than it expected.
6427        //       eg. Portrait instead of Landscape.
6428
6429        int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
6430        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
6431                mForcedAppOrientation, rotation);
6432
6433        if (DEBUG_ORIENTATION) {
6434            Slog.v(TAG_WM, "Application requested orientation "
6435                    + mForcedAppOrientation + ", got rotation " + rotation
6436                    + " which has " + (altOrientation ? "incompatible" : "compatible")
6437                    + " metrics");
6438        }
6439
6440        if (mRotation == rotation && mAltOrientation == altOrientation) {
6441            // No change.
6442            return false;
6443        }
6444
6445        if (DEBUG_ORIENTATION) {
6446            Slog.v(TAG_WM,
6447                "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
6448                + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
6449                + ", forceApp=" + mForcedAppOrientation);
6450        }
6451
6452        mRotation = rotation;
6453        mAltOrientation = altOrientation;
6454        mPolicy.setRotationLw(mRotation);
6455
6456        mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
6457        mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
6458        mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
6459        mWaitingForConfig = true;
6460        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6461        displayContent.layoutNeeded = true;
6462        final int[] anim = new int[2];
6463        if (displayContent.isDimming()) {
6464            anim[0] = anim[1] = 0;
6465        } else {
6466            mPolicy.selectRotationAnimationLw(anim);
6467        }
6468        startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
6469        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
6470        screenRotationAnimation =
6471                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6472
6473        // We need to update our screen size information to match the new rotation. If the rotation
6474        // has actually changed then this method will return true and, according to the comment at
6475        // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
6476        // By updating the Display info here it will be available to
6477        // computeScreenConfigurationLocked later.
6478        updateDisplayAndOrientationLocked(mCurConfiguration.uiMode);
6479
6480        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6481        if (!inTransaction) {
6482            if (SHOW_TRANSACTIONS) {
6483                Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked");
6484            }
6485            SurfaceControl.openTransaction();
6486        }
6487        try {
6488            // NOTE: We disable the rotation in the emulator because
6489            //       it doesn't support hardware OpenGL emulation yet.
6490            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
6491                    && screenRotationAnimation.hasScreenshot()) {
6492                if (screenRotationAnimation.setRotationInTransaction(
6493                        rotation, mFxSession,
6494                        MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(),
6495                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
6496                    scheduleAnimationLocked();
6497                }
6498            }
6499
6500            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
6501        } finally {
6502            if (!inTransaction) {
6503                SurfaceControl.closeTransaction();
6504                if (SHOW_LIGHT_TRANSACTIONS) {
6505                    Slog.i(TAG_WM, "<<< CLOSE TRANSACTION setRotationUnchecked");
6506                }
6507            }
6508        }
6509
6510        final WindowList windows = displayContent.getWindowList();
6511        for (int i = windows.size() - 1; i >= 0; i--) {
6512            WindowState w = windows.get(i);
6513            // Discard surface after orientation change, these can't be reused.
6514            if (w.mAppToken != null) {
6515                w.mAppToken.destroySavedSurfaces();
6516            }
6517            if (w.mHasSurface) {
6518                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
6519                w.mOrientationChanging = true;
6520                mWindowPlacerLocked.mOrientationChangeComplete = false;
6521            }
6522            w.mLastFreezeDuration = 0;
6523        }
6524
6525        for (int i=mRotationWatchers.size()-1; i>=0; i--) {
6526            try {
6527                mRotationWatchers.get(i).watcher.onRotationChanged(rotation);
6528            } catch (RemoteException e) {
6529            }
6530        }
6531
6532        //TODO (multidisplay): Magnification is supported only for the default display.
6533        // Announce rotation only if we will not animate as we already have the
6534        // windows in final state. Otherwise, we make this call at the rotation end.
6535        if (screenRotationAnimation == null && mAccessibilityController != null
6536                && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
6537            mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(),
6538                    rotation);
6539        }
6540
6541        return true;
6542    }
6543
6544    @Override
6545    public int getRotation() {
6546        return mRotation;
6547    }
6548
6549    @Override
6550    public boolean isRotationFrozen() {
6551        return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6552    }
6553
6554    @Override
6555    public int watchRotation(IRotationWatcher watcher) {
6556        final IBinder watcherBinder = watcher.asBinder();
6557        IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6558            @Override
6559            public void binderDied() {
6560                synchronized (mWindowMap) {
6561                    for (int i=0; i<mRotationWatchers.size(); i++) {
6562                        if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) {
6563                            RotationWatcher removed = mRotationWatchers.remove(i);
6564                            IBinder binder = removed.watcher.asBinder();
6565                            if (binder != null) {
6566                                binder.unlinkToDeath(this, 0);
6567                            }
6568                            i--;
6569                        }
6570                    }
6571                }
6572            }
6573        };
6574
6575        synchronized (mWindowMap) {
6576            try {
6577                watcher.asBinder().linkToDeath(dr, 0);
6578                mRotationWatchers.add(new RotationWatcher(watcher, dr));
6579            } catch (RemoteException e) {
6580                // Client died, no cleanup needed.
6581            }
6582
6583            return mRotation;
6584        }
6585    }
6586
6587    @Override
6588    public void removeRotationWatcher(IRotationWatcher watcher) {
6589        final IBinder watcherBinder = watcher.asBinder();
6590        synchronized (mWindowMap) {
6591            for (int i=0; i<mRotationWatchers.size(); i++) {
6592                RotationWatcher rotationWatcher = mRotationWatchers.get(i);
6593                if (watcherBinder == rotationWatcher.watcher.asBinder()) {
6594                    RotationWatcher removed = mRotationWatchers.remove(i);
6595                    IBinder binder = removed.watcher.asBinder();
6596                    if (binder != null) {
6597                        binder.unlinkToDeath(removed.deathRecipient, 0);
6598                    }
6599                    i--;
6600                }
6601            }
6602        }
6603    }
6604
6605    /**
6606     * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6607     * theme attribute) on devices that feature a physical options menu key attempt to position
6608     * their menu panel window along the edge of the screen nearest the physical menu key.
6609     * This lowers the travel distance between invoking the menu panel and selecting
6610     * a menu option.
6611     *
6612     * This method helps control where that menu is placed. Its current implementation makes
6613     * assumptions about the menu key and its relationship to the screen based on whether
6614     * the device's natural orientation is portrait (width < height) or landscape.
6615     *
6616     * The menu key is assumed to be located along the bottom edge of natural-portrait
6617     * devices and along the right edge of natural-landscape devices. If these assumptions
6618     * do not hold for the target device, this method should be changed to reflect that.
6619     *
6620     * @return A {@link Gravity} value for placing the options menu window
6621     */
6622    @Override
6623    public int getPreferredOptionsPanelGravity() {
6624        synchronized (mWindowMap) {
6625            final int rotation = getRotation();
6626
6627            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6628            final DisplayContent displayContent = getDefaultDisplayContentLocked();
6629            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6630                // On devices with a natural orientation of portrait
6631                switch (rotation) {
6632                    default:
6633                    case Surface.ROTATION_0:
6634                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6635                    case Surface.ROTATION_90:
6636                        return Gravity.RIGHT | Gravity.BOTTOM;
6637                    case Surface.ROTATION_180:
6638                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6639                    case Surface.ROTATION_270:
6640                        return Gravity.START | Gravity.BOTTOM;
6641                }
6642            }
6643
6644            // On devices with a natural orientation of landscape
6645            switch (rotation) {
6646                default:
6647                case Surface.ROTATION_0:
6648                    return Gravity.RIGHT | Gravity.BOTTOM;
6649                case Surface.ROTATION_90:
6650                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6651                case Surface.ROTATION_180:
6652                    return Gravity.START | Gravity.BOTTOM;
6653                case Surface.ROTATION_270:
6654                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6655            }
6656        }
6657    }
6658
6659    /**
6660     * Starts the view server on the specified port.
6661     *
6662     * @param port The port to listener to.
6663     *
6664     * @return True if the server was successfully started, false otherwise.
6665     *
6666     * @see com.android.server.wm.ViewServer
6667     * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
6668     */
6669    @Override
6670    public boolean startViewServer(int port) {
6671        if (isSystemSecure()) {
6672            return false;
6673        }
6674
6675        if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
6676            return false;
6677        }
6678
6679        if (port < 1024) {
6680            return false;
6681        }
6682
6683        if (mViewServer != null) {
6684            if (!mViewServer.isRunning()) {
6685                try {
6686                    return mViewServer.start();
6687                } catch (IOException e) {
6688                    Slog.w(TAG_WM, "View server did not start");
6689                }
6690            }
6691            return false;
6692        }
6693
6694        try {
6695            mViewServer = new ViewServer(this, port);
6696            return mViewServer.start();
6697        } catch (IOException e) {
6698            Slog.w(TAG_WM, "View server did not start");
6699        }
6700        return false;
6701    }
6702
6703    private boolean isSystemSecure() {
6704        return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
6705                "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6706    }
6707
6708    /**
6709     * Stops the view server if it exists.
6710     *
6711     * @return True if the server stopped, false if it wasn't started or
6712     *         couldn't be stopped.
6713     *
6714     * @see com.android.server.wm.ViewServer
6715     */
6716    @Override
6717    public boolean stopViewServer() {
6718        if (isSystemSecure()) {
6719            return false;
6720        }
6721
6722        if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
6723            return false;
6724        }
6725
6726        if (mViewServer != null) {
6727            return mViewServer.stop();
6728        }
6729        return false;
6730    }
6731
6732    /**
6733     * Indicates whether the view server is running.
6734     *
6735     * @return True if the server is running, false otherwise.
6736     *
6737     * @see com.android.server.wm.ViewServer
6738     */
6739    @Override
6740    public boolean isViewServerRunning() {
6741        if (isSystemSecure()) {
6742            return false;
6743        }
6744
6745        if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
6746            return false;
6747        }
6748
6749        return mViewServer != null && mViewServer.isRunning();
6750    }
6751
6752    /**
6753     * Lists all availble windows in the system. The listing is written in the
6754     * specified Socket's output stream with the following syntax:
6755     * windowHashCodeInHexadecimal windowName
6756     * Each line of the ouput represents a different window.
6757     *
6758     * @param client The remote client to send the listing to.
6759     * @return False if an error occured, true otherwise.
6760     */
6761    boolean viewServerListWindows(Socket client) {
6762        if (isSystemSecure()) {
6763            return false;
6764        }
6765
6766        boolean result = true;
6767
6768        WindowList windows = new WindowList();
6769        synchronized (mWindowMap) {
6770            //noinspection unchecked
6771            final int numDisplays = mDisplayContents.size();
6772            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6773                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
6774                windows.addAll(displayContent.getWindowList());
6775            }
6776        }
6777
6778        BufferedWriter out = null;
6779
6780        // Any uncaught exception will crash the system process
6781        try {
6782            OutputStream clientStream = client.getOutputStream();
6783            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6784
6785            final int count = windows.size();
6786            for (int i = 0; i < count; i++) {
6787                final WindowState w = windows.get(i);
6788                out.write(Integer.toHexString(System.identityHashCode(w)));
6789                out.write(' ');
6790                out.append(w.mAttrs.getTitle());
6791                out.write('\n');
6792            }
6793
6794            out.write("DONE.\n");
6795            out.flush();
6796        } catch (Exception e) {
6797            result = false;
6798        } finally {
6799            if (out != null) {
6800                try {
6801                    out.close();
6802                } catch (IOException e) {
6803                    result = false;
6804                }
6805            }
6806        }
6807
6808        return result;
6809    }
6810
6811    // TODO(multidisplay): Extend to multiple displays.
6812    /**
6813     * Returns the focused window in the following format:
6814     * windowHashCodeInHexadecimal windowName
6815     *
6816     * @param client The remote client to send the listing to.
6817     * @return False if an error occurred, true otherwise.
6818     */
6819    boolean viewServerGetFocusedWindow(Socket client) {
6820        if (isSystemSecure()) {
6821            return false;
6822        }
6823
6824        boolean result = true;
6825
6826        WindowState focusedWindow = getFocusedWindow();
6827
6828        BufferedWriter out = null;
6829
6830        // Any uncaught exception will crash the system process
6831        try {
6832            OutputStream clientStream = client.getOutputStream();
6833            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6834
6835            if(focusedWindow != null) {
6836                out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
6837                out.write(' ');
6838                out.append(focusedWindow.mAttrs.getTitle());
6839            }
6840            out.write('\n');
6841            out.flush();
6842        } catch (Exception e) {
6843            result = false;
6844        } finally {
6845            if (out != null) {
6846                try {
6847                    out.close();
6848                } catch (IOException e) {
6849                    result = false;
6850                }
6851            }
6852        }
6853
6854        return result;
6855    }
6856
6857    /**
6858     * Sends a command to a target window. The result of the command, if any, will be
6859     * written in the output stream of the specified socket.
6860     *
6861     * The parameters must follow this syntax:
6862     * windowHashcode extra
6863     *
6864     * Where XX is the length in characeters of the windowTitle.
6865     *
6866     * The first parameter is the target window. The window with the specified hashcode
6867     * will be the target. If no target can be found, nothing happens. The extra parameters
6868     * will be delivered to the target window and as parameters to the command itself.
6869     *
6870     * @param client The remote client to sent the result, if any, to.
6871     * @param command The command to execute.
6872     * @param parameters The command parameters.
6873     *
6874     * @return True if the command was successfully delivered, false otherwise. This does
6875     *         not indicate whether the command itself was successful.
6876     */
6877    boolean viewServerWindowCommand(Socket client, String command, String parameters) {
6878        if (isSystemSecure()) {
6879            return false;
6880        }
6881
6882        boolean success = true;
6883        Parcel data = null;
6884        Parcel reply = null;
6885
6886        BufferedWriter out = null;
6887
6888        // Any uncaught exception will crash the system process
6889        try {
6890            // Find the hashcode of the window
6891            int index = parameters.indexOf(' ');
6892            if (index == -1) {
6893                index = parameters.length();
6894            }
6895            final String code = parameters.substring(0, index);
6896            int hashCode = (int) Long.parseLong(code, 16);
6897
6898            // Extract the command's parameter after the window description
6899            if (index < parameters.length()) {
6900                parameters = parameters.substring(index + 1);
6901            } else {
6902                parameters = "";
6903            }
6904
6905            final WindowState window = findWindow(hashCode);
6906            if (window == null) {
6907                return false;
6908            }
6909
6910            data = Parcel.obtain();
6911            data.writeInterfaceToken("android.view.IWindow");
6912            data.writeString(command);
6913            data.writeString(parameters);
6914            data.writeInt(1);
6915            ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
6916
6917            reply = Parcel.obtain();
6918
6919            final IBinder binder = window.mClient.asBinder();
6920            // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
6921            binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
6922
6923            reply.readException();
6924
6925            if (!client.isOutputShutdown()) {
6926                out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
6927                out.write("DONE\n");
6928                out.flush();
6929            }
6930
6931        } catch (Exception e) {
6932            Slog.w(TAG_WM, "Could not send command " + command + " with parameters " + parameters, e);
6933            success = false;
6934        } finally {
6935            if (data != null) {
6936                data.recycle();
6937            }
6938            if (reply != null) {
6939                reply.recycle();
6940            }
6941            if (out != null) {
6942                try {
6943                    out.close();
6944                } catch (IOException e) {
6945
6946                }
6947            }
6948        }
6949
6950        return success;
6951    }
6952
6953    public void addWindowChangeListener(WindowChangeListener listener) {
6954        synchronized(mWindowMap) {
6955            mWindowChangeListeners.add(listener);
6956        }
6957    }
6958
6959    public void removeWindowChangeListener(WindowChangeListener listener) {
6960        synchronized(mWindowMap) {
6961            mWindowChangeListeners.remove(listener);
6962        }
6963    }
6964
6965    private void notifyWindowsChanged() {
6966        WindowChangeListener[] windowChangeListeners;
6967        synchronized(mWindowMap) {
6968            if(mWindowChangeListeners.isEmpty()) {
6969                return;
6970            }
6971            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6972            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6973        }
6974        int N = windowChangeListeners.length;
6975        for(int i = 0; i < N; i++) {
6976            windowChangeListeners[i].windowsChanged();
6977        }
6978    }
6979
6980    private void notifyFocusChanged() {
6981        WindowChangeListener[] windowChangeListeners;
6982        synchronized(mWindowMap) {
6983            if(mWindowChangeListeners.isEmpty()) {
6984                return;
6985            }
6986            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6987            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6988        }
6989        int N = windowChangeListeners.length;
6990        for(int i = 0; i < N; i++) {
6991            windowChangeListeners[i].focusChanged();
6992        }
6993    }
6994
6995    private WindowState findWindow(int hashCode) {
6996        if (hashCode == -1) {
6997            // TODO(multidisplay): Extend to multiple displays.
6998            return getFocusedWindow();
6999        }
7000
7001        synchronized (mWindowMap) {
7002            final int numDisplays = mDisplayContents.size();
7003            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
7004                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
7005                final int numWindows = windows.size();
7006                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
7007                    final WindowState w = windows.get(winNdx);
7008                    if (System.identityHashCode(w) == hashCode) {
7009                        return w;
7010                    }
7011                }
7012            }
7013        }
7014
7015        return null;
7016    }
7017
7018    /*
7019     * Instruct the Activity Manager to fetch the current configuration and broadcast
7020     * that to config-changed listeners if appropriate.
7021     */
7022    void sendNewConfiguration() {
7023        try {
7024            mActivityManager.updateConfiguration(null);
7025        } catch (RemoteException e) {
7026        }
7027    }
7028
7029    public Configuration computeNewConfiguration() {
7030        synchronized (mWindowMap) {
7031            return computeNewConfigurationLocked();
7032        }
7033    }
7034
7035    private Configuration computeNewConfigurationLocked() {
7036        if (!mDisplayReady) {
7037            return null;
7038        }
7039        Configuration config = new Configuration();
7040        config.fontScale = 0;
7041        computeScreenConfigurationLocked(config);
7042        return config;
7043    }
7044
7045    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int uiMode,
7046            int dw, int dh) {
7047        // TODO: Multidisplay: for now only use with default display.
7048        final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode);
7049        if (width < displayInfo.smallestNominalAppWidth) {
7050            displayInfo.smallestNominalAppWidth = width;
7051        }
7052        if (width > displayInfo.largestNominalAppWidth) {
7053            displayInfo.largestNominalAppWidth = width;
7054        }
7055        final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode);
7056        if (height < displayInfo.smallestNominalAppHeight) {
7057            displayInfo.smallestNominalAppHeight = height;
7058        }
7059        if (height > displayInfo.largestNominalAppHeight) {
7060            displayInfo.largestNominalAppHeight = height;
7061        }
7062    }
7063
7064    private int reduceConfigLayout(int curLayout, int rotation, float density,
7065            int dw, int dh, int uiMode) {
7066        // TODO: Multidisplay: for now only use with default display.
7067        // Get the app screen size at this rotation.
7068        int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode);
7069        int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode);
7070
7071        // Compute the screen layout size class for this rotation.
7072        int longSize = w;
7073        int shortSize = h;
7074        if (longSize < shortSize) {
7075            int tmp = longSize;
7076            longSize = shortSize;
7077            shortSize = tmp;
7078        }
7079        longSize = (int)(longSize/density);
7080        shortSize = (int)(shortSize/density);
7081        return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
7082    }
7083
7084    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
7085                  int uiMode, int dw, int dh, float density, Configuration outConfig) {
7086        // TODO: Multidisplay: for now only use with default display.
7087
7088        // We need to determine the smallest width that will occur under normal
7089        // operation.  To this, start with the base screen size and compute the
7090        // width under the different possible rotations.  We need to un-rotate
7091        // the current screen dimensions before doing this.
7092        int unrotDw, unrotDh;
7093        if (rotated) {
7094            unrotDw = dh;
7095            unrotDh = dw;
7096        } else {
7097            unrotDw = dw;
7098            unrotDh = dh;
7099        }
7100        displayInfo.smallestNominalAppWidth = 1<<30;
7101        displayInfo.smallestNominalAppHeight = 1<<30;
7102        displayInfo.largestNominalAppWidth = 0;
7103        displayInfo.largestNominalAppHeight = 0;
7104        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, uiMode, unrotDw, unrotDh);
7105        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, uiMode, unrotDh, unrotDw);
7106        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, uiMode, unrotDw, unrotDh);
7107        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, uiMode, unrotDh, unrotDw);
7108        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
7109        sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode);
7110        sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode);
7111        sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode);
7112        sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode);
7113        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
7114        outConfig.screenLayout = sl;
7115    }
7116
7117    private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
7118            DisplayMetrics dm, int dw, int dh) {
7119        // TODO: Multidisplay: for now only use with default display.
7120        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode);
7121        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode);
7122        float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
7123        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
7124        if (curSize == 0 || size < curSize) {
7125            curSize = size;
7126        }
7127        return curSize;
7128    }
7129
7130    private int computeCompatSmallestWidth(boolean rotated, int uiMode, DisplayMetrics dm, int dw, int dh) {
7131        // TODO: Multidisplay: for now only use with default display.
7132        mTmpDisplayMetrics.setTo(dm);
7133        final DisplayMetrics tmpDm = mTmpDisplayMetrics;
7134        final int unrotDw, unrotDh;
7135        if (rotated) {
7136            unrotDw = dh;
7137            unrotDh = dw;
7138        } else {
7139            unrotDw = dw;
7140            unrotDh = dh;
7141        }
7142        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh);
7143        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw);
7144        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh);
7145        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw);
7146        return sw;
7147    }
7148
7149    /** Do not call if mDisplayReady == false */
7150    DisplayInfo updateDisplayAndOrientationLocked(int uiMode) {
7151        // TODO(multidisplay): For now, apply Configuration to main screen only.
7152        final DisplayContent displayContent = getDefaultDisplayContentLocked();
7153
7154        // Use the effective "visual" dimensions based on current rotation
7155        final boolean rotated = (mRotation == Surface.ROTATION_90
7156                || mRotation == Surface.ROTATION_270);
7157        final int realdw = rotated ?
7158                displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
7159        final int realdh = rotated ?
7160                displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
7161        int dw = realdw;
7162        int dh = realdh;
7163
7164        if (mAltOrientation) {
7165            if (realdw > realdh) {
7166                // Turn landscape into portrait.
7167                int maxw = (int)(realdh/1.3f);
7168                if (maxw < realdw) {
7169                    dw = maxw;
7170                }
7171            } else {
7172                // Turn portrait into landscape.
7173                int maxh = (int)(realdw/1.3f);
7174                if (maxh < realdh) {
7175                    dh = maxh;
7176                }
7177            }
7178        }
7179
7180        // Update application display metrics.
7181        final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode);
7182        final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode);
7183        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7184        displayInfo.rotation = mRotation;
7185        displayInfo.logicalWidth = dw;
7186        displayInfo.logicalHeight = dh;
7187        displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
7188        displayInfo.appWidth = appWidth;
7189        displayInfo.appHeight = appHeight;
7190        displayInfo.getLogicalMetrics(mRealDisplayMetrics,
7191                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
7192        displayInfo.getAppMetrics(mDisplayMetrics);
7193        if (displayContent.mDisplayScalingDisabled) {
7194            displayInfo.flags |= Display.FLAG_SCALING_DISABLED;
7195        } else {
7196            displayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
7197        }
7198
7199        mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
7200                displayContent.getDisplayId(), displayInfo);
7201
7202        displayContent.mBaseDisplayRect.set(0, 0, dw, dh);
7203        if (false) {
7204            Slog.i(TAG_WM, "Set app display size: " + appWidth + " x " + appHeight);
7205        }
7206
7207        mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
7208                mCompatDisplayMetrics);
7209        return displayInfo;
7210    }
7211
7212    /** Do not call if mDisplayReady == false */
7213    void computeScreenConfigurationLocked(Configuration config) {
7214        final DisplayInfo displayInfo = updateDisplayAndOrientationLocked(
7215                config.uiMode);
7216
7217        final int dw = displayInfo.logicalWidth;
7218        final int dh = displayInfo.logicalHeight;
7219        config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
7220                Configuration.ORIENTATION_LANDSCAPE;
7221        config.screenWidthDp =
7222                (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation, config.uiMode) /
7223                        mDisplayMetrics.density);
7224        config.screenHeightDp =
7225                (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation, config.uiMode) /
7226                        mDisplayMetrics.density);
7227        final boolean rotated = (mRotation == Surface.ROTATION_90
7228                || mRotation == Surface.ROTATION_270);
7229
7230        computeSizeRangesAndScreenLayout(displayInfo, rotated, config.uiMode, dw, dh,
7231                mDisplayMetrics.density, config);
7232
7233        config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK)
7234                | ((displayInfo.flags & Display.FLAG_ROUND) != 0
7235                        ? Configuration.SCREENLAYOUT_ROUND_YES
7236                        : Configuration.SCREENLAYOUT_ROUND_NO);
7237
7238        config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
7239        config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
7240        config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode,
7241                mDisplayMetrics, dw, dh);
7242        config.densityDpi = displayInfo.logicalDensityDpi;
7243
7244        // Update the configuration based on available input devices, lid switch,
7245        // and platform configuration.
7246        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
7247        config.keyboard = Configuration.KEYBOARD_NOKEYS;
7248        config.navigation = Configuration.NAVIGATION_NONAV;
7249
7250        int keyboardPresence = 0;
7251        int navigationPresence = 0;
7252        final InputDevice[] devices = mInputManager.getInputDevices();
7253        final int len = devices.length;
7254        for (int i = 0; i < len; i++) {
7255            InputDevice device = devices[i];
7256            if (!device.isVirtual()) {
7257                final int sources = device.getSources();
7258                final int presenceFlag = device.isExternal() ?
7259                        WindowManagerPolicy.PRESENCE_EXTERNAL :
7260                                WindowManagerPolicy.PRESENCE_INTERNAL;
7261
7262                if (mIsTouchDevice) {
7263                    if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
7264                            InputDevice.SOURCE_TOUCHSCREEN) {
7265                        config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
7266                    }
7267                } else {
7268                    config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
7269                }
7270
7271                if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
7272                    config.navigation = Configuration.NAVIGATION_TRACKBALL;
7273                    navigationPresence |= presenceFlag;
7274                } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
7275                        && config.navigation == Configuration.NAVIGATION_NONAV) {
7276                    config.navigation = Configuration.NAVIGATION_DPAD;
7277                    navigationPresence |= presenceFlag;
7278                }
7279
7280                if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
7281                    config.keyboard = Configuration.KEYBOARD_QWERTY;
7282                    keyboardPresence |= presenceFlag;
7283                }
7284            }
7285        }
7286
7287        if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) {
7288            config.navigation = Configuration.NAVIGATION_DPAD;
7289            navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
7290        }
7291
7292        // Determine whether a hard keyboard is available and enabled.
7293        boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
7294        if (hardKeyboardAvailable != mHardKeyboardAvailable) {
7295            mHardKeyboardAvailable = hardKeyboardAvailable;
7296            mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
7297            mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
7298        }
7299
7300        // Let the policy update hidden states.
7301        config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
7302        config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
7303        config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
7304        mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
7305    }
7306
7307    void notifyHardKeyboardStatusChange() {
7308        final boolean available;
7309        final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener;
7310        synchronized (mWindowMap) {
7311            listener = mHardKeyboardStatusChangeListener;
7312            available = mHardKeyboardAvailable;
7313        }
7314        if (listener != null) {
7315            listener.onHardKeyboardStatusChange(available);
7316        }
7317    }
7318
7319    boolean startMovingTask(IWindow window, float startX, float startY) {
7320        WindowState win = null;
7321        synchronized (mWindowMap) {
7322            win = windowForClientLocked(null, window, false);
7323            // win shouldn't be null here, pass it down to startPositioningLocked
7324            // to get warning if it's null.
7325            if (!startPositioningLocked(win, false /*resize*/, startX, startY)) {
7326                return false;
7327            }
7328        }
7329        try {
7330            mActivityManager.setFocusedTask(win.getTask().mTaskId);
7331        } catch(RemoteException e) {}
7332        return true;
7333    }
7334
7335    private void startScrollingTask(DisplayContent displayContent, int startX, int startY) {
7336        if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM,
7337                "startScrollingTask: " + "{" + startX + ", " + startY + "}");
7338
7339        Task task = null;
7340        synchronized (mWindowMap) {
7341            int taskId = displayContent.taskIdFromPoint(startX, startY);
7342            if (taskId >= 0) {
7343                task = mTaskIdToTask.get(taskId);
7344            }
7345            if (task == null || !task.isDockedInEffect() || !startPositioningLocked(
7346                    task.getTopVisibleAppMainWindow(), false /*resize*/, startX, startY)) {
7347                return;
7348            }
7349        }
7350        try {
7351            mActivityManager.setFocusedTask(task.mTaskId);
7352        } catch(RemoteException e) {}
7353    }
7354
7355    private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
7356        int taskId = -1;
7357        synchronized (mWindowMap) {
7358            final Task task = displayContent.findTaskForControlPoint(x, y);
7359            if (task != null) {
7360                if (!startPositioningLocked(
7361                        task.getTopVisibleAppMainWindow(), true /*resize*/, x, y)) {
7362                    return;
7363                }
7364                taskId = task.mTaskId;
7365            } else {
7366                taskId = displayContent.taskIdFromPoint(x, y);
7367            }
7368        }
7369        if (taskId >= 0) {
7370            try {
7371                mActivityManager.setFocusedTask(taskId);
7372            } catch(RemoteException e) {}
7373        }
7374    }
7375
7376    private boolean startPositioningLocked(
7377            WindowState win, boolean resize, float startX, float startY) {
7378        if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "startPositioningLocked: "
7379            + "win=" + win + ", resize=" + resize + ", {" + startX + ", " + startY + "}");
7380
7381        if (win == null || win.getAppToken() == null) {
7382            Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
7383            return false;
7384        }
7385        if (win.mInputChannel == null) {
7386            Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, "
7387                    + " probably being removed");
7388            return false;
7389        }
7390
7391        final DisplayContent displayContent = win.getDisplayContent();
7392        if (displayContent == null) {
7393            Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
7394            return false;
7395        }
7396
7397        Display display = displayContent.getDisplay();
7398        mTaskPositioner = new TaskPositioner(this);
7399        mTaskPositioner.register(display);
7400        mInputMonitor.updateInputWindowsLw(true /*force*/);
7401
7402        // We need to grab the touch focus so that the touch events during the
7403        // resizing/scrolling are not sent to the app. 'win' is the main window
7404        // of the app, it may not have focus since there might be other windows
7405        // on top (eg. a dialog window).
7406        WindowState transferFocusFromWin = win;
7407        if (mCurrentFocus != null && mCurrentFocus != win
7408                && mCurrentFocus.mAppToken == win.mAppToken) {
7409            transferFocusFromWin = mCurrentFocus;
7410        }
7411        if (!mInputManager.transferTouchFocus(
7412                transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) {
7413            Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
7414            mTaskPositioner.unregister();
7415            mTaskPositioner = null;
7416            mInputMonitor.updateInputWindowsLw(true /*force*/);
7417            return false;
7418        }
7419
7420        mTaskPositioner.startDragLocked(win, resize, startX, startY);
7421        return true;
7422    }
7423
7424    private void finishPositioning() {
7425        if (DEBUG_TASK_POSITIONING) {
7426            Slog.d(TAG_WM, "finishPositioning");
7427        }
7428        synchronized (mWindowMap) {
7429            if (mTaskPositioner != null) {
7430                mTaskPositioner.unregister();
7431                mTaskPositioner = null;
7432                mInputMonitor.updateInputWindowsLw(true /*force*/);
7433            }
7434        }
7435    }
7436
7437    private void adjustForImeIfNeeded(final DisplayContent displayContent) {
7438        final WindowState imeWin = mInputMethodWindow;
7439        final TaskStack focusedStack =
7440                mCurrentFocus != null ? mCurrentFocus.getStack() : null;
7441        final boolean dockVisible = isStackVisibleLocked(DOCKED_STACK_ID);
7442        if (imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
7443                && dockVisible
7444                && focusedStack != null
7445                && focusedStack.getDockSide() == DOCKED_BOTTOM){
7446            final ArrayList<TaskStack> stacks = displayContent.getStacks();
7447            for (int i = stacks.size() - 1; i >= 0; --i) {
7448                final TaskStack stack = stacks.get(i);
7449                if (stack.isVisibleLocked()) {
7450                    stack.setAdjustedForIme(imeWin);
7451                }
7452            }
7453            displayContent.mDividerControllerLocked.setAdjustedForIme(true, true);
7454        } else {
7455            final ArrayList<TaskStack> stacks = displayContent.getStacks();
7456            for (int i = stacks.size() - 1; i >= 0; --i) {
7457                final TaskStack stack = stacks.get(i);
7458                stack.resetAdjustedForIme(!dockVisible);
7459            }
7460            displayContent.mDividerControllerLocked.setAdjustedForIme(false, dockVisible);
7461        }
7462    }
7463
7464    // -------------------------------------------------------------
7465    // Drag and drop
7466    // -------------------------------------------------------------
7467
7468    IBinder prepareDragSurface(IWindow window, SurfaceSession session,
7469            int flags, int width, int height, Surface outSurface) {
7470        if (DEBUG_DRAG) {
7471            Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height
7472                    + " flags=" + Integer.toHexString(flags) + " win=" + window
7473                    + " asbinder=" + window.asBinder());
7474        }
7475
7476        final int callerPid = Binder.getCallingPid();
7477        final int callerUid = Binder.getCallingUid();
7478        final long origId = Binder.clearCallingIdentity();
7479        IBinder token = null;
7480
7481        try {
7482            synchronized (mWindowMap) {
7483                try {
7484                    if (mDragState == null) {
7485                        // TODO(multi-display): support other displays
7486                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
7487                        final Display display = displayContent.getDisplay();
7488
7489                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
7490                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
7491                        surface.setLayerStack(display.getLayerStack());
7492                        float alpha = 1;
7493                        if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
7494                            alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
7495                        }
7496                        surface.setAlpha(alpha);
7497
7498                        if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  DRAG "
7499                                + surface + ": CREATE");
7500                        outSurface.copyFrom(surface);
7501                        final IBinder winBinder = window.asBinder();
7502                        token = new Binder();
7503                        mDragState = new DragState(this, token, surface, flags, winBinder);
7504                        mDragState.mPid = callerPid;
7505                        mDragState.mUid = callerUid;
7506                        mDragState.mOriginalAlpha = alpha;
7507                        token = mDragState.mToken = new Binder();
7508
7509                        // 5 second timeout for this window to actually begin the drag
7510                        mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
7511                        Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
7512                        mH.sendMessageDelayed(msg, 5000);
7513                    } else {
7514                        Slog.w(TAG_WM, "Drag already in progress");
7515                    }
7516                } catch (OutOfResourcesException e) {
7517                    Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height, e);
7518                    if (mDragState != null) {
7519                        mDragState.reset();
7520                        mDragState = null;
7521                    }
7522                }
7523            }
7524        } finally {
7525            Binder.restoreCallingIdentity(origId);
7526        }
7527
7528        return token;
7529    }
7530
7531    // -------------------------------------------------------------
7532    // Input Events and Focus Management
7533    // -------------------------------------------------------------
7534
7535    final InputMonitor mInputMonitor = new InputMonitor(this);
7536    private boolean mEventDispatchingEnabled;
7537
7538    @Override
7539    public void pauseKeyDispatching(IBinder _token) {
7540        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7541                "pauseKeyDispatching()")) {
7542            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7543        }
7544
7545        synchronized (mWindowMap) {
7546            WindowToken token = mTokenMap.get(_token);
7547            if (token != null) {
7548                mInputMonitor.pauseDispatchingLw(token);
7549            }
7550        }
7551    }
7552
7553    @Override
7554    public void resumeKeyDispatching(IBinder _token) {
7555        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7556                "resumeKeyDispatching()")) {
7557            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7558        }
7559
7560        synchronized (mWindowMap) {
7561            WindowToken token = mTokenMap.get(_token);
7562            if (token != null) {
7563                mInputMonitor.resumeDispatchingLw(token);
7564            }
7565        }
7566    }
7567
7568    @Override
7569    public void setEventDispatching(boolean enabled) {
7570        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7571                "setEventDispatching()")) {
7572            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7573        }
7574
7575        synchronized (mWindowMap) {
7576            mEventDispatchingEnabled = enabled;
7577            if (mDisplayEnabled) {
7578                mInputMonitor.setEventDispatchingLw(enabled);
7579            }
7580        }
7581    }
7582
7583    private WindowState getFocusedWindow() {
7584        synchronized (mWindowMap) {
7585            return getFocusedWindowLocked();
7586        }
7587    }
7588
7589    private WindowState getFocusedWindowLocked() {
7590        return mCurrentFocus;
7591    }
7592
7593    private void showAuditSafeModeNotification() {
7594        PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
7595                new Intent(Intent.ACTION_VIEW,
7596                           Uri.parse("https://support.google.com/nexus/answer/2852139")), 0);
7597
7598        String title = mContext.getString(R.string.audit_safemode_notification);
7599
7600        Notification notification = new Notification.Builder(mContext)
7601                .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning)
7602                .setWhen(0)
7603                .setOngoing(true)
7604                .setTicker(title)
7605                .setLocalOnly(true)
7606                .setPriority(Notification.PRIORITY_HIGH)
7607                .setVisibility(Notification.VISIBILITY_PUBLIC)
7608                .setColor(mContext.getColor(
7609                        com.android.internal.R.color.system_notification_accent_color))
7610                .setContentTitle(title)
7611                .setContentText(mContext.getString(R.string.audit_safemode_notification_details))
7612                .setContentIntent(pendingIntent)
7613                .build();
7614
7615        NotificationManager notificationManager = (NotificationManager) mContext
7616                .getSystemService(Context.NOTIFICATION_SERVICE);
7617
7618        notificationManager.notifyAsUser(null, R.string.audit_safemode_notification, notification,
7619                UserHandle.ALL);
7620    }
7621
7622    public boolean detectSafeMode() {
7623        if (!mInputMonitor.waitForInputDevicesReady(
7624                INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
7625            Slog.w(TAG_WM, "Devices still not ready after waiting "
7626                   + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
7627                   + " milliseconds before attempting to detect safe mode.");
7628        }
7629
7630        if (Settings.Global.getInt(
7631                mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) {
7632            return false;
7633        }
7634
7635        int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7636                KeyEvent.KEYCODE_MENU);
7637        int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
7638        int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
7639                KeyEvent.KEYCODE_DPAD_CENTER);
7640        int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
7641                InputManagerService.BTN_MOUSE);
7642        int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7643                KeyEvent.KEYCODE_VOLUME_DOWN);
7644        mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
7645                || volumeDownState > 0;
7646        try {
7647            if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0
7648                    || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) {
7649                int auditSafeMode = SystemProperties.getInt(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, 0);
7650
7651                if (auditSafeMode == 0) {
7652                    mSafeMode = true;
7653                    SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
7654                } else {
7655                    // stay in safe mode until we have updated to a newer build
7656                    int buildDate = SystemProperties.getInt(PROPERTY_BUILD_DATE_UTC, 0);
7657
7658                    if (auditSafeMode >= buildDate) {
7659                        mSafeMode = true;
7660                        showAuditSafeModeNotification();
7661                    } else {
7662                        SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
7663                        SystemProperties.set(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, "");
7664                    }
7665                }
7666            }
7667        } catch (IllegalArgumentException e) {
7668        }
7669        if (mSafeMode) {
7670            Log.i(TAG_WM, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
7671                    + " dpad=" + dpadState + " trackball=" + trackballState + ")");
7672            SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1");
7673        } else {
7674            Log.i(TAG_WM, "SAFE MODE not enabled");
7675        }
7676        mPolicy.setSafeMode(mSafeMode);
7677        return mSafeMode;
7678    }
7679
7680    public void displayReady() {
7681        for (Display display : mDisplays) {
7682            displayReady(display.getDisplayId());
7683        }
7684
7685        synchronized(mWindowMap) {
7686            final DisplayContent displayContent = getDefaultDisplayContentLocked();
7687            readForcedDisplayPropertiesLocked(displayContent);
7688            mDisplayReady = true;
7689        }
7690
7691        try {
7692            mActivityManager.updateConfiguration(null);
7693        } catch (RemoteException e) {
7694        }
7695
7696        synchronized(mWindowMap) {
7697            mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
7698                    PackageManager.FEATURE_TOUCHSCREEN);
7699            configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
7700        }
7701
7702        try {
7703            mActivityManager.updateConfiguration(null);
7704        } catch (RemoteException e) {
7705        }
7706
7707        updateCircularDisplayMaskIfNeeded();
7708    }
7709
7710    private void displayReady(int displayId) {
7711        synchronized(mWindowMap) {
7712            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7713            if (displayContent != null) {
7714                mAnimator.addDisplayLocked(displayId);
7715                displayContent.initializeDisplayBaseInfo();
7716                if (displayContent.mTapDetector != null) {
7717                    displayContent.mTapDetector.init();
7718                }
7719            }
7720        }
7721    }
7722
7723    public void systemReady() {
7724        mPolicy.systemReady();
7725    }
7726
7727    // -------------------------------------------------------------
7728    // Async Handler
7729    // -------------------------------------------------------------
7730
7731    final class H extends Handler {
7732        public static final int REPORT_FOCUS_CHANGE = 2;
7733        public static final int REPORT_LOSING_FOCUS = 3;
7734        public static final int DO_TRAVERSAL = 4;
7735        public static final int ADD_STARTING = 5;
7736        public static final int REMOVE_STARTING = 6;
7737        public static final int FINISHED_STARTING = 7;
7738        public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
7739        public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
7740        public static final int WINDOW_FREEZE_TIMEOUT = 11;
7741
7742        public static final int APP_TRANSITION_TIMEOUT = 13;
7743        public static final int PERSIST_ANIMATION_SCALE = 14;
7744        public static final int FORCE_GC = 15;
7745        public static final int ENABLE_SCREEN = 16;
7746        public static final int APP_FREEZE_TIMEOUT = 17;
7747        public static final int SEND_NEW_CONFIGURATION = 18;
7748        public static final int REPORT_WINDOWS_CHANGE = 19;
7749        public static final int DRAG_START_TIMEOUT = 20;
7750        public static final int DRAG_END_TIMEOUT = 21;
7751        public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
7752        public static final int BOOT_TIMEOUT = 23;
7753        public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
7754        public static final int SHOW_STRICT_MODE_VIOLATION = 25;
7755        public static final int DO_ANIMATION_CALLBACK = 26;
7756
7757        public static final int DO_DISPLAY_ADDED = 27;
7758        public static final int DO_DISPLAY_REMOVED = 28;
7759        public static final int DO_DISPLAY_CHANGED = 29;
7760
7761        public static final int CLIENT_FREEZE_TIMEOUT = 30;
7762        public static final int TAP_OUTSIDE_TASK = 31;
7763        public static final int NOTIFY_ACTIVITY_DRAWN = 32;
7764
7765        public static final int ALL_WINDOWS_DRAWN = 33;
7766
7767        public static final int NEW_ANIMATOR_SCALE = 34;
7768
7769        public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35;
7770        public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
7771
7772        public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37;
7773        public static final int RESET_ANR_MESSAGE = 38;
7774        public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39;
7775
7776        public static final int FINISH_TASK_POSITIONING = 40;
7777
7778        public static final int UPDATE_DOCKED_STACK_DIVIDER = 41;
7779
7780        public static final int RESIZE_STACK = 42;
7781        public static final int RESIZE_TASK = 43;
7782
7783        public static final int TWO_FINGER_SCROLL_START = 44;
7784
7785        public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
7786
7787        public static final int NOTIFY_APP_TRANSITION_STARTING = 47;
7788        public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48;
7789        public static final int NOTIFY_APP_TRANSITION_FINISHED = 49;
7790        public static final int NOTIFY_STARTING_WINDOW_DRAWN = 50;
7791
7792        public static final int UPDATE_ANIMATION_SCALE = 51;
7793
7794        /**
7795         * Used to denote that an integer field in a message will not be used.
7796         */
7797        public static final int UNUSED = 0;
7798
7799        @Override
7800        public void handleMessage(Message msg) {
7801            if (DEBUG_WINDOW_TRACE) {
7802                Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what);
7803            }
7804            switch (msg.what) {
7805                case REPORT_FOCUS_CHANGE: {
7806                    WindowState lastFocus;
7807                    WindowState newFocus;
7808
7809                    AccessibilityController accessibilityController = null;
7810
7811                    synchronized(mWindowMap) {
7812                        // TODO(multidisplay): Accessibility supported only of default desiplay.
7813                        if (mAccessibilityController != null && getDefaultDisplayContentLocked()
7814                                .getDisplayId() == Display.DEFAULT_DISPLAY) {
7815                            accessibilityController = mAccessibilityController;
7816                        }
7817
7818                        lastFocus = mLastFocus;
7819                        newFocus = mCurrentFocus;
7820                        if (lastFocus == newFocus) {
7821                            // Focus is not changing, so nothing to do.
7822                            return;
7823                        }
7824                        mLastFocus = newFocus;
7825                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Focus moving from " + lastFocus +
7826                                " to " + newFocus);
7827                        if (newFocus != null && lastFocus != null
7828                                && !newFocus.isDisplayedLw()) {
7829                            //Slog.i(TAG_WM, "Delaying loss of focus...");
7830                            mLosingFocus.add(lastFocus);
7831                            lastFocus = null;
7832                        }
7833                    }
7834
7835                    // First notify the accessibility manager for the change so it has
7836                    // the windows before the newly focused one starts firing eventgs.
7837                    if (accessibilityController != null) {
7838                        accessibilityController.onWindowFocusChangedNotLocked();
7839                    }
7840
7841                    //System.out.println("Changing focus from " + lastFocus
7842                    //                   + " to " + newFocus);
7843                    if (newFocus != null) {
7844                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus);
7845                        newFocus.reportFocusChangedSerialized(true, mInTouchMode);
7846                        notifyFocusChanged();
7847                    }
7848
7849                    if (lastFocus != null) {
7850                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus);
7851                        lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
7852                    }
7853                } break;
7854
7855                case REPORT_LOSING_FOCUS: {
7856                    ArrayList<WindowState> losers;
7857
7858                    synchronized(mWindowMap) {
7859                        losers = mLosingFocus;
7860                        mLosingFocus = new ArrayList<WindowState>();
7861                    }
7862
7863                    final int N = losers.size();
7864                    for (int i=0; i<N; i++) {
7865                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " +
7866                                losers.get(i));
7867                        losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
7868                    }
7869                } break;
7870
7871                case DO_TRAVERSAL: {
7872                    synchronized(mWindowMap) {
7873                        mWindowPlacerLocked.performSurfacePlacement();
7874                    }
7875                } break;
7876
7877                case ADD_STARTING: {
7878                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7879                    final StartingData sd = wtoken.startingData;
7880
7881                    if (sd == null) {
7882                        // Animation has been canceled... do nothing.
7883                        return;
7884                    }
7885
7886                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting "
7887                            + wtoken + ": pkg=" + sd.pkg);
7888
7889                    View view = null;
7890                    try {
7891                        view = mPolicy.addStartingWindow(
7892                            wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
7893                            sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags);
7894                    } catch (Exception e) {
7895                        Slog.w(TAG_WM, "Exception when adding starting window", e);
7896                    }
7897
7898                    if (view != null) {
7899                        boolean abort = false;
7900
7901                        synchronized(mWindowMap) {
7902                            if (wtoken.removed || wtoken.startingData == null) {
7903                                // If the window was successfully added, then
7904                                // we need to remove it.
7905                                if (wtoken.startingWindow != null) {
7906                                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
7907                                            "Aborted starting " + wtoken
7908                                            + ": removed=" + wtoken.removed
7909                                            + " startingData=" + wtoken.startingData);
7910                                    wtoken.startingWindow = null;
7911                                    wtoken.startingData = null;
7912                                    abort = true;
7913                                }
7914                            } else {
7915                                wtoken.startingView = view;
7916                            }
7917                            if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM,
7918                                    "Added starting " + wtoken
7919                                    + ": startingWindow="
7920                                    + wtoken.startingWindow + " startingView="
7921                                    + wtoken.startingView);
7922                        }
7923
7924                        if (abort) {
7925                            try {
7926                                mPolicy.removeStartingWindow(wtoken.token, view);
7927                            } catch (Exception e) {
7928                                Slog.w(TAG_WM, "Exception when removing starting window", e);
7929                            }
7930                        }
7931                    }
7932                } break;
7933
7934                case REMOVE_STARTING: {
7935                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7936                    IBinder token = null;
7937                    View view = null;
7938                    synchronized (mWindowMap) {
7939                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting "
7940                                + wtoken + ": startingWindow="
7941                                + wtoken.startingWindow + " startingView="
7942                                + wtoken.startingView);
7943                        if (wtoken.startingWindow != null) {
7944                            view = wtoken.startingView;
7945                            token = wtoken.token;
7946                            wtoken.startingData = null;
7947                            wtoken.startingView = null;
7948                            wtoken.startingWindow = null;
7949                            wtoken.startingDisplayed = false;
7950                        }
7951                    }
7952                    if (view != null) {
7953                        try {
7954                            mPolicy.removeStartingWindow(token, view);
7955                        } catch (Exception e) {
7956                            Slog.w(TAG_WM, "Exception when removing starting window", e);
7957                        }
7958                    }
7959                } break;
7960
7961                case FINISHED_STARTING: {
7962                    IBinder token = null;
7963                    View view = null;
7964                    while (true) {
7965                        synchronized (mWindowMap) {
7966                            final int N = mFinishedStarting.size();
7967                            if (N <= 0) {
7968                                break;
7969                            }
7970                            AppWindowToken wtoken = mFinishedStarting.remove(N-1);
7971
7972                            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
7973                                    "Finished starting " + wtoken
7974                                    + ": startingWindow=" + wtoken.startingWindow
7975                                    + " startingView=" + wtoken.startingView);
7976
7977                            if (wtoken.startingWindow == null) {
7978                                continue;
7979                            }
7980
7981                            view = wtoken.startingView;
7982                            token = wtoken.token;
7983                            wtoken.startingData = null;
7984                            wtoken.startingView = null;
7985                            wtoken.startingWindow = null;
7986                            wtoken.startingDisplayed = false;
7987                        }
7988
7989                        try {
7990                            mPolicy.removeStartingWindow(token, view);
7991                        } catch (Exception e) {
7992                            Slog.w(TAG_WM, "Exception when removing starting window", e);
7993                        }
7994                    }
7995                } break;
7996
7997                case REPORT_APPLICATION_TOKEN_DRAWN: {
7998                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7999
8000                    try {
8001                        if (DEBUG_VISIBILITY) Slog.v(
8002                                TAG_WM, "Reporting drawn in " + wtoken);
8003                        wtoken.appToken.windowsDrawn();
8004                    } catch (RemoteException ex) {
8005                    }
8006                } break;
8007
8008                case REPORT_APPLICATION_TOKEN_WINDOWS: {
8009                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8010
8011                    boolean nowVisible = msg.arg1 != 0;
8012                    boolean nowGone = msg.arg2 != 0;
8013
8014                    try {
8015                        if (DEBUG_VISIBILITY) Slog.v(
8016                                TAG_WM, "Reporting visible in " + wtoken
8017                                + " visible=" + nowVisible
8018                                + " gone=" + nowGone);
8019                        if (nowVisible) {
8020                            wtoken.appToken.windowsVisible();
8021                        } else {
8022                            wtoken.appToken.windowsGone();
8023                        }
8024                    } catch (RemoteException ex) {
8025                    }
8026                } break;
8027
8028                case WINDOW_FREEZE_TIMEOUT: {
8029                    // TODO(multidisplay): Can non-default displays rotate?
8030                    synchronized (mWindowMap) {
8031                        Slog.w(TAG_WM, "Window freeze timeout expired.");
8032                        mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
8033                        final WindowList windows = getDefaultWindowListLocked();
8034                        int i = windows.size();
8035                        while (i > 0) {
8036                            i--;
8037                            WindowState w = windows.get(i);
8038                            if (w.mOrientationChanging) {
8039                                w.mOrientationChanging = false;
8040                                w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
8041                                        - mDisplayFreezeTime);
8042                                Slog.w(TAG_WM, "Force clearing orientation change: " + w);
8043                            }
8044                        }
8045                        mWindowPlacerLocked.performSurfacePlacement();
8046                    }
8047                    break;
8048                }
8049
8050                case APP_TRANSITION_TIMEOUT: {
8051                    synchronized (mWindowMap) {
8052                        if (mAppTransition.isTransitionSet() || !mOpeningApps.isEmpty()
8053                                    || !mClosingApps.isEmpty()) {
8054                            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "*** APP TRANSITION TIMEOUT."
8055                                    + " isTransitionSet()=" + mAppTransition.isTransitionSet()
8056                                    + " mOpeningApps.size()=" + mOpeningApps.size()
8057                                    + " mClosingApps.size()=" + mClosingApps.size());
8058                            mAppTransition.setTimeout();
8059                            mWindowPlacerLocked.performSurfacePlacement();
8060                        }
8061                    }
8062                    break;
8063                }
8064
8065                case PERSIST_ANIMATION_SCALE: {
8066                    Settings.Global.putFloat(mContext.getContentResolver(),
8067                            Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
8068                    Settings.Global.putFloat(mContext.getContentResolver(),
8069                            Settings.Global.TRANSITION_ANIMATION_SCALE,
8070                            mTransitionAnimationScaleSetting);
8071                    Settings.Global.putFloat(mContext.getContentResolver(),
8072                            Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting);
8073                    break;
8074                }
8075
8076                case UPDATE_ANIMATION_SCALE: {
8077                    @UpdateAnimationScaleMode
8078                    final int mode = msg.arg1;
8079                    switch (mode) {
8080                        case WINDOW_ANIMATION_SCALE: {
8081                            mWindowAnimationScaleSetting = Settings.Global.getFloat(
8082                                    mContext.getContentResolver(),
8083                                    Settings.Global.WINDOW_ANIMATION_SCALE,
8084                                    mWindowAnimationScaleSetting);
8085                            break;
8086                        }
8087                        case TRANSITION_ANIMATION_SCALE: {
8088                            mTransitionAnimationScaleSetting = Settings.Global.getFloat(
8089                                    mContext.getContentResolver(),
8090                                    Settings.Global.TRANSITION_ANIMATION_SCALE,
8091                                    mTransitionAnimationScaleSetting);
8092                            break;
8093                        }
8094                        case ANIMATION_DURATION_SCALE: {
8095                            mAnimatorDurationScaleSetting = Settings.Global.getFloat(
8096                                    mContext.getContentResolver(),
8097                                    Settings.Global.ANIMATOR_DURATION_SCALE,
8098                                    mAnimatorDurationScaleSetting);
8099                            dispatchNewAnimatorScaleLocked(null);
8100                            break;
8101                        }
8102                    }
8103                    break;
8104                }
8105
8106                case FORCE_GC: {
8107                    synchronized (mWindowMap) {
8108                        // Since we're holding both mWindowMap and mAnimator we don't need to
8109                        // hold mAnimator.mLayoutToAnim.
8110                        if (mAnimator.isAnimating() || mAnimationScheduled) {
8111                            // If we are animating, don't do the gc now but
8112                            // delay a bit so we don't interrupt the animation.
8113                            sendEmptyMessageDelayed(H.FORCE_GC, 2000);
8114                            return;
8115                        }
8116                        // If we are currently rotating the display, it will
8117                        // schedule a new message when done.
8118                        if (mDisplayFrozen) {
8119                            return;
8120                        }
8121                    }
8122                    Runtime.getRuntime().gc();
8123                    break;
8124                }
8125
8126                case ENABLE_SCREEN: {
8127                    performEnableScreen();
8128                    break;
8129                }
8130
8131                case APP_FREEZE_TIMEOUT: {
8132                    synchronized (mWindowMap) {
8133                        Slog.w(TAG_WM, "App freeze timeout expired.");
8134                        mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
8135                        final int numStacks = mStackIdToStack.size();
8136                        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8137                            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
8138                            final ArrayList<Task> tasks = stack.getTasks();
8139                            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
8140                                AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8141                                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
8142                                    AppWindowToken tok = tokens.get(tokenNdx);
8143                                    if (tok.mAppAnimator.freezingScreen) {
8144                                        Slog.w(TAG_WM, "Force clearing freeze: " + tok);
8145                                        unsetAppFreezingScreenLocked(tok, true, true);
8146                                    }
8147                                }
8148                            }
8149                        }
8150                    }
8151                    break;
8152                }
8153
8154                case CLIENT_FREEZE_TIMEOUT: {
8155                    synchronized (mWindowMap) {
8156                        if (mClientFreezingScreen) {
8157                            mClientFreezingScreen = false;
8158                            mLastFinishedFreezeSource = "client-timeout";
8159                            stopFreezingDisplayLocked();
8160                        }
8161                    }
8162                    break;
8163                }
8164
8165                case SEND_NEW_CONFIGURATION: {
8166                    removeMessages(SEND_NEW_CONFIGURATION);
8167                    sendNewConfiguration();
8168                    break;
8169                }
8170
8171                case REPORT_WINDOWS_CHANGE: {
8172                    if (mWindowsChanged) {
8173                        synchronized (mWindowMap) {
8174                            mWindowsChanged = false;
8175                        }
8176                        notifyWindowsChanged();
8177                    }
8178                    break;
8179                }
8180
8181                case DRAG_START_TIMEOUT: {
8182                    IBinder win = (IBinder)msg.obj;
8183                    if (DEBUG_DRAG) {
8184                        Slog.w(TAG_WM, "Timeout starting drag by win " + win);
8185                    }
8186                    synchronized (mWindowMap) {
8187                        // !!! TODO: ANR the app that has failed to start the drag in time
8188                        if (mDragState != null) {
8189                            mDragState.unregister();
8190                            mInputMonitor.updateInputWindowsLw(true /*force*/);
8191                            mDragState.reset();
8192                            mDragState = null;
8193                        }
8194                    }
8195                    break;
8196                }
8197
8198                case DRAG_END_TIMEOUT: {
8199                    IBinder win = (IBinder)msg.obj;
8200                    if (DEBUG_DRAG) {
8201                        Slog.w(TAG_WM, "Timeout ending drag to win " + win);
8202                    }
8203                    synchronized (mWindowMap) {
8204                        // !!! TODO: ANR the drag-receiving app
8205                        if (mDragState != null) {
8206                            mDragState.mDragResult = false;
8207                            mDragState.endDragLw();
8208                        }
8209                    }
8210                    break;
8211                }
8212
8213                case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
8214                    notifyHardKeyboardStatusChange();
8215                    break;
8216                }
8217
8218                case BOOT_TIMEOUT: {
8219                    performBootTimeout();
8220                    break;
8221                }
8222
8223                case WAITING_FOR_DRAWN_TIMEOUT: {
8224                    Runnable callback = null;
8225                    synchronized (mWindowMap) {
8226                        Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
8227                        mWaitingForDrawn.clear();
8228                        callback = mWaitingForDrawnCallback;
8229                        mWaitingForDrawnCallback = null;
8230                    }
8231                    if (callback != null) {
8232                        callback.run();
8233                    }
8234                    break;
8235                }
8236
8237                case SHOW_STRICT_MODE_VIOLATION: {
8238                    showStrictModeViolation(msg.arg1, msg.arg2);
8239                    break;
8240                }
8241
8242                case SHOW_CIRCULAR_DISPLAY_MASK: {
8243                    showCircularMask(msg.arg1 == 1);
8244                    break;
8245                }
8246
8247                case SHOW_EMULATOR_DISPLAY_OVERLAY: {
8248                    showEmulatorDisplayOverlay();
8249                    break;
8250                }
8251
8252                case DO_ANIMATION_CALLBACK: {
8253                    try {
8254                        ((IRemoteCallback)msg.obj).sendResult(null);
8255                    } catch (RemoteException e) {
8256                    }
8257                    break;
8258                }
8259
8260                case DO_DISPLAY_ADDED:
8261                    handleDisplayAdded(msg.arg1);
8262                    break;
8263
8264                case DO_DISPLAY_REMOVED:
8265                    synchronized (mWindowMap) {
8266                        handleDisplayRemovedLocked(msg.arg1);
8267                    }
8268                    break;
8269
8270                case DO_DISPLAY_CHANGED:
8271                    synchronized (mWindowMap) {
8272                        handleDisplayChangedLocked(msg.arg1);
8273                    }
8274                    break;
8275
8276                case TWO_FINGER_SCROLL_START: {
8277                    startScrollingTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
8278                }
8279                break;
8280
8281                case TAP_OUTSIDE_TASK: {
8282                    handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
8283                }
8284                break;
8285
8286                case FINISH_TASK_POSITIONING: {
8287                    finishPositioning();
8288                }
8289                break;
8290
8291                case NOTIFY_ACTIVITY_DRAWN:
8292                    try {
8293                        mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
8294                    } catch (RemoteException e) {
8295                    }
8296                    break;
8297                case ALL_WINDOWS_DRAWN: {
8298                    Runnable callback;
8299                    synchronized (mWindowMap) {
8300                        callback = mWaitingForDrawnCallback;
8301                        mWaitingForDrawnCallback = null;
8302                    }
8303                    if (callback != null) {
8304                        callback.run();
8305                    }
8306                }
8307                case NEW_ANIMATOR_SCALE: {
8308                    float scale = getCurrentAnimatorScale();
8309                    ValueAnimator.setDurationScale(scale);
8310                    Session session = (Session)msg.obj;
8311                    if (session != null) {
8312                        try {
8313                            session.mCallback.onAnimatorScaleChanged(scale);
8314                        } catch (RemoteException e) {
8315                        }
8316                    } else {
8317                        ArrayList<IWindowSessionCallback> callbacks
8318                                = new ArrayList<IWindowSessionCallback>();
8319                        synchronized (mWindowMap) {
8320                            for (int i=0; i<mSessions.size(); i++) {
8321                                callbacks.add(mSessions.valueAt(i).mCallback);
8322                            }
8323
8324                        }
8325                        for (int i=0; i<callbacks.size(); i++) {
8326                            try {
8327                                callbacks.get(i).onAnimatorScaleChanged(scale);
8328                            } catch (RemoteException e) {
8329                            }
8330                        }
8331                    }
8332                }
8333                break;
8334                case CHECK_IF_BOOT_ANIMATION_FINISHED: {
8335                    final boolean bootAnimationComplete;
8336                    synchronized (mWindowMap) {
8337                        if (DEBUG_BOOT) Slog.i(TAG_WM, "CHECK_IF_BOOT_ANIMATION_FINISHED:");
8338                        bootAnimationComplete = checkBootAnimationCompleteLocked();
8339                    }
8340                    if (bootAnimationComplete) {
8341                        performEnableScreen();
8342                    }
8343                }
8344                break;
8345                case RESET_ANR_MESSAGE: {
8346                    synchronized (mWindowMap) {
8347                        mLastANRState = null;
8348                    }
8349                }
8350                break;
8351                case WALLPAPER_DRAW_PENDING_TIMEOUT: {
8352                    synchronized (mWindowMap) {
8353                        if (mWallpaperControllerLocked.processWallpaperDrawPendingTimeout()) {
8354                            mWindowPlacerLocked.performSurfacePlacement();
8355                        }
8356                    }
8357                }
8358                case UPDATE_DOCKED_STACK_DIVIDER: {
8359                    synchronized (mWindowMap) {
8360                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
8361                        displayContent.getDockedDividerController().reevaluateVisibility(false);
8362                        adjustForImeIfNeeded(displayContent);
8363                    }
8364                }
8365                break;
8366                case RESIZE_TASK: {
8367                    try {
8368                        mActivityManager.resizeTask(msg.arg1, (Rect) msg.obj, msg.arg2);
8369                    } catch (RemoteException e) {
8370                        // This will not happen since we are in the same process.
8371                    }
8372                }
8373                break;
8374                case RESIZE_STACK: {
8375                    try {
8376                        mActivityManager.resizeStack(
8377                                msg.arg1, (Rect) msg.obj, msg.arg2 == 1, false, false, -1);
8378                    } catch (RemoteException e) {
8379                        // This will not happen since we are in the same process.
8380                    }
8381                }
8382                break;
8383                case WINDOW_REPLACEMENT_TIMEOUT: {
8384                    final AppWindowToken token = (AppWindowToken) msg.obj;
8385                    synchronized (mWindowMap) {
8386                        token.clearTimedoutReplacesLocked();
8387                    }
8388                }
8389                case NOTIFY_APP_TRANSITION_STARTING: {
8390                    mAmInternal.notifyAppTransitionStarting(msg.arg1);
8391                }
8392                break;
8393                case NOTIFY_APP_TRANSITION_CANCELLED: {
8394                    mAmInternal.notifyAppTransitionCancelled();
8395                }
8396                break;
8397                case NOTIFY_APP_TRANSITION_FINISHED: {
8398                    mAmInternal.notifyAppTransitionFinished();
8399                }
8400                break;
8401                case NOTIFY_STARTING_WINDOW_DRAWN: {
8402                    mAmInternal.notifyStartingWindowDrawn();
8403                }
8404                break;
8405            }
8406            if (DEBUG_WINDOW_TRACE) {
8407                Slog.v(TAG_WM, "handleMessage: exit");
8408            }
8409        }
8410    }
8411
8412    void destroyPreservedSurfaceLocked() {
8413        for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) {
8414            final WindowState w = mDestroyPreservedSurface.get(i);
8415            w.mWinAnimator.destroyPreservedSurfaceLocked();
8416        }
8417        mDestroyPreservedSurface.clear();
8418    }
8419    // -------------------------------------------------------------
8420    // IWindowManager API
8421    // -------------------------------------------------------------
8422
8423    @Override
8424    public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
8425            IInputContext inputContext) {
8426        if (client == null) throw new IllegalArgumentException("null client");
8427        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
8428        Session session = new Session(this, callback, client, inputContext);
8429        return session;
8430    }
8431
8432    @Override
8433    public boolean inputMethodClientHasFocus(IInputMethodClient client) {
8434        synchronized (mWindowMap) {
8435            // The focus for the client is the window immediately below
8436            // where we would place the input method window.
8437            int idx = findDesiredInputMethodWindowIndexLocked(false);
8438            if (idx > 0) {
8439                // TODO(multidisplay): IMEs are only supported on the default display.
8440                WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
8441                if (DEBUG_INPUT_METHOD) {
8442                    Slog.i(TAG_WM, "Desired input method target: " + imFocus);
8443                    Slog.i(TAG_WM, "Current focus: " + mCurrentFocus);
8444                    Slog.i(TAG_WM, "Last focus: " + mLastFocus);
8445                }
8446                if (imFocus != null) {
8447                    // This may be a starting window, in which case we still want
8448                    // to count it as okay.
8449                    if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
8450                            && imFocus.mAppToken != null) {
8451                        // The client has definitely started, so it really should
8452                        // have a window in this app token.  Let's look for it.
8453                        for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
8454                            WindowState w = imFocus.mAppToken.windows.get(i);
8455                            if (w != imFocus) {
8456                                Log.i(TAG_WM, "Switching to real app window: " + w);
8457                                imFocus = w;
8458                                break;
8459                            }
8460                        }
8461                    }
8462                    if (DEBUG_INPUT_METHOD) {
8463                        Slog.i(TAG_WM, "IM target client: " + imFocus.mSession.mClient);
8464                        if (imFocus.mSession.mClient != null) {
8465                            Slog.i(TAG_WM, "IM target client binder: "
8466                                    + imFocus.mSession.mClient.asBinder());
8467                            Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder());
8468                        }
8469                    }
8470                    if (imFocus.mSession.mClient != null &&
8471                            imFocus.mSession.mClient.asBinder() == client.asBinder()) {
8472                        return true;
8473                    }
8474                }
8475            }
8476
8477            // Okay, how about this...  what is the current focus?
8478            // It seems in some cases we may not have moved the IM
8479            // target window, such as when it was in a pop-up window,
8480            // so let's also look at the current focus.  (An example:
8481            // go to Gmail, start searching so the keyboard goes up,
8482            // press home.  Sometimes the IME won't go down.)
8483            // Would be nice to fix this more correctly, but it's
8484            // way at the end of a release, and this should be good enough.
8485            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
8486                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
8487                return true;
8488            }
8489        }
8490        return false;
8491    }
8492
8493    @Override
8494    public void getInitialDisplaySize(int displayId, Point size) {
8495        synchronized (mWindowMap) {
8496            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8497            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8498                size.x = displayContent.mInitialDisplayWidth;
8499                size.y = displayContent.mInitialDisplayHeight;
8500            }
8501        }
8502    }
8503
8504    @Override
8505    public void getBaseDisplaySize(int displayId, Point size) {
8506        synchronized (mWindowMap) {
8507            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8508            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8509                size.x = displayContent.mBaseDisplayWidth;
8510                size.y = displayContent.mBaseDisplayHeight;
8511            }
8512        }
8513    }
8514
8515    @Override
8516    public void setForcedDisplaySize(int displayId, int width, int height) {
8517        if (mContext.checkCallingOrSelfPermission(
8518                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8519                PackageManager.PERMISSION_GRANTED) {
8520            throw new SecurityException("Must hold permission " +
8521                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8522        }
8523        if (displayId != Display.DEFAULT_DISPLAY) {
8524            throw new IllegalArgumentException("Can only set the default display");
8525        }
8526        final long ident = Binder.clearCallingIdentity();
8527        try {
8528            synchronized(mWindowMap) {
8529                // Set some sort of reasonable bounds on the size of the display that we
8530                // will try to emulate.
8531                final int MIN_WIDTH = 200;
8532                final int MIN_HEIGHT = 200;
8533                final int MAX_SCALE = 2;
8534                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8535                if (displayContent != null) {
8536                    width = Math.min(Math.max(width, MIN_WIDTH),
8537                            displayContent.mInitialDisplayWidth * MAX_SCALE);
8538                    height = Math.min(Math.max(height, MIN_HEIGHT),
8539                            displayContent.mInitialDisplayHeight * MAX_SCALE);
8540                    setForcedDisplaySizeLocked(displayContent, width, height);
8541                    Settings.Global.putString(mContext.getContentResolver(),
8542                            Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
8543                }
8544            }
8545        } finally {
8546            Binder.restoreCallingIdentity(ident);
8547        }
8548    }
8549
8550    @Override
8551    public void setForcedDisplayScalingMode(int displayId, int mode) {
8552        if (mContext.checkCallingOrSelfPermission(
8553                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8554                PackageManager.PERMISSION_GRANTED) {
8555            throw new SecurityException("Must hold permission " +
8556                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8557        }
8558        if (displayId != Display.DEFAULT_DISPLAY) {
8559            throw new IllegalArgumentException("Can only set the default display");
8560        }
8561        final long ident = Binder.clearCallingIdentity();
8562        try {
8563            synchronized(mWindowMap) {
8564                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8565                if (displayContent != null) {
8566                    if (mode < 0 || mode > 1) {
8567                        mode = 0;
8568                    }
8569                    setForcedDisplayScalingModeLocked(displayContent, mode);
8570                    Settings.Global.putInt(mContext.getContentResolver(),
8571                            Settings.Global.DISPLAY_SCALING_FORCE, mode);
8572                }
8573            }
8574        } finally {
8575            Binder.restoreCallingIdentity(ident);
8576        }
8577    }
8578
8579    private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode) {
8580        Slog.i(TAG_WM, "Using display scaling mode: " + (mode == 0 ? "auto" : "off"));
8581        displayContent.mDisplayScalingDisabled = (mode != 0);
8582        reconfigureDisplayLocked(displayContent);
8583    }
8584
8585    private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) {
8586        // Display size.
8587        String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
8588                Settings.Global.DISPLAY_SIZE_FORCED);
8589        if (sizeStr == null || sizeStr.length() == 0) {
8590            sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
8591        }
8592        if (sizeStr != null && sizeStr.length() > 0) {
8593            final int pos = sizeStr.indexOf(',');
8594            if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
8595                int width, height;
8596                try {
8597                    width = Integer.parseInt(sizeStr.substring(0, pos));
8598                    height = Integer.parseInt(sizeStr.substring(pos+1));
8599                    if (displayContent.mBaseDisplayWidth != width
8600                            || displayContent.mBaseDisplayHeight != height) {
8601                        Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
8602                        displayContent.mBaseDisplayWidth = width;
8603                        displayContent.mBaseDisplayHeight = height;
8604                    }
8605                } catch (NumberFormatException ex) {
8606                }
8607            }
8608        }
8609
8610        // Display density.
8611        final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId);
8612        if (density != 0) {
8613            displayContent.mBaseDisplayDensity = density;
8614        }
8615
8616        // Display scaling mode.
8617        int mode = Settings.Global.getInt(mContext.getContentResolver(),
8618                Settings.Global.DISPLAY_SCALING_FORCE, 0);
8619        if (mode != 0) {
8620            Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED");
8621            displayContent.mDisplayScalingDisabled = true;
8622        }
8623    }
8624
8625    // displayContent must not be null
8626    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
8627        Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
8628        displayContent.mBaseDisplayWidth = width;
8629        displayContent.mBaseDisplayHeight = height;
8630        reconfigureDisplayLocked(displayContent);
8631    }
8632
8633    @Override
8634    public void clearForcedDisplaySize(int displayId) {
8635        if (mContext.checkCallingOrSelfPermission(
8636                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8637                PackageManager.PERMISSION_GRANTED) {
8638            throw new SecurityException("Must hold permission " +
8639                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8640        }
8641        if (displayId != Display.DEFAULT_DISPLAY) {
8642            throw new IllegalArgumentException("Can only set the default display");
8643        }
8644        final long ident = Binder.clearCallingIdentity();
8645        try {
8646            synchronized(mWindowMap) {
8647                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8648                if (displayContent != null) {
8649                    setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
8650                            displayContent.mInitialDisplayHeight);
8651                    Settings.Global.putString(mContext.getContentResolver(),
8652                            Settings.Global.DISPLAY_SIZE_FORCED, "");
8653                }
8654            }
8655        } finally {
8656            Binder.restoreCallingIdentity(ident);
8657        }
8658    }
8659
8660    @Override
8661    public int getInitialDisplayDensity(int displayId) {
8662        synchronized (mWindowMap) {
8663            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8664            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8665                return displayContent.mInitialDisplayDensity;
8666            }
8667        }
8668        return -1;
8669    }
8670
8671    @Override
8672    public int getBaseDisplayDensity(int displayId) {
8673        synchronized (mWindowMap) {
8674            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8675            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8676                return displayContent.mBaseDisplayDensity;
8677            }
8678        }
8679        return -1;
8680    }
8681
8682    @Override
8683    public void setForcedDisplayDensity(int displayId, int density) {
8684        if (mContext.checkCallingOrSelfPermission(
8685                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8686                PackageManager.PERMISSION_GRANTED) {
8687            throw new SecurityException("Must hold permission " +
8688                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8689        }
8690        if (displayId != Display.DEFAULT_DISPLAY) {
8691            throw new IllegalArgumentException("Can only set the default display");
8692        }
8693        final long ident = Binder.clearCallingIdentity();
8694        try {
8695            synchronized(mWindowMap) {
8696                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8697                if (displayContent != null) {
8698                    setForcedDisplayDensityLocked(displayContent, density);
8699                    Settings.Secure.putStringForUser(mContext.getContentResolver(),
8700                            Settings.Secure.DISPLAY_DENSITY_FORCED,
8701                            Integer.toString(density), mCurrentUserId);
8702                }
8703            }
8704        } finally {
8705            Binder.restoreCallingIdentity(ident);
8706        }
8707    }
8708
8709    @Override
8710    public void clearForcedDisplayDensity(int displayId) {
8711        if (mContext.checkCallingOrSelfPermission(
8712                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8713                PackageManager.PERMISSION_GRANTED) {
8714            throw new SecurityException("Must hold permission " +
8715                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8716        }
8717        if (displayId != Display.DEFAULT_DISPLAY) {
8718            throw new IllegalArgumentException("Can only set the default display");
8719        }
8720        final long ident = Binder.clearCallingIdentity();
8721        try {
8722            synchronized(mWindowMap) {
8723                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8724                if (displayContent != null) {
8725                    setForcedDisplayDensityLocked(displayContent,
8726                            displayContent.mInitialDisplayDensity);
8727                    Settings.Secure.putStringForUser(mContext.getContentResolver(),
8728                            Settings.Secure.DISPLAY_DENSITY_FORCED, "", mCurrentUserId);
8729                }
8730            }
8731        } finally {
8732            Binder.restoreCallingIdentity(ident);
8733        }
8734    }
8735
8736    /**
8737     * @param userId the ID of the user
8738     * @return the forced display density for the specified user, if set, or
8739     *         {@code 0} if not set
8740     */
8741    private int getForcedDisplayDensityForUserLocked(int userId) {
8742        String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(),
8743                Settings.Secure.DISPLAY_DENSITY_FORCED, userId);
8744        if (densityStr == null || densityStr.length() == 0) {
8745            densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
8746        }
8747        if (densityStr != null && densityStr.length() > 0) {
8748            try {
8749                return Integer.parseInt(densityStr);
8750            } catch (NumberFormatException ex) {
8751            }
8752        }
8753        return 0;
8754    }
8755
8756    /**
8757     * Forces the given display to the use the specified density.
8758     *
8759     * @param displayContent the display to modify
8760     * @param density the density in DPI to use
8761     */
8762    private void setForcedDisplayDensityLocked(@NonNull DisplayContent displayContent,
8763            int density) {
8764        displayContent.mBaseDisplayDensity = density;
8765        reconfigureDisplayLocked(displayContent);
8766    }
8767
8768    // displayContent must not be null
8769    private void reconfigureDisplayLocked(DisplayContent displayContent) {
8770        // TODO: Multidisplay: for now only use with default display.
8771        if (!mDisplayReady) {
8772            return;
8773        }
8774        configureDisplayPolicyLocked(displayContent);
8775        displayContent.layoutNeeded = true;
8776
8777        boolean configChanged = updateOrientationFromAppTokensLocked(false);
8778        mTempConfiguration.setToDefaults();
8779        mTempConfiguration.fontScale = mCurConfiguration.fontScale;
8780        mTempConfiguration.uiMode = mCurConfiguration.uiMode;
8781        computeScreenConfigurationLocked(mTempConfiguration);
8782        configChanged |= mCurConfiguration.diff(mTempConfiguration) != 0;
8783
8784        if (configChanged) {
8785            mWaitingForConfig = true;
8786            startFreezingDisplayLocked(false, 0, 0);
8787            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
8788        }
8789
8790        mWindowPlacerLocked.performSurfacePlacement();
8791    }
8792
8793    private void configureDisplayPolicyLocked(DisplayContent displayContent) {
8794        mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
8795                displayContent.mBaseDisplayWidth,
8796                displayContent.mBaseDisplayHeight,
8797                displayContent.mBaseDisplayDensity);
8798
8799        DisplayInfo displayInfo = displayContent.getDisplayInfo();
8800        mPolicy.setDisplayOverscan(displayContent.getDisplay(),
8801                displayInfo.overscanLeft, displayInfo.overscanTop,
8802                displayInfo.overscanRight, displayInfo.overscanBottom);
8803    }
8804
8805    @Override
8806    public void setOverscan(int displayId, int left, int top, int right, int bottom) {
8807        if (mContext.checkCallingOrSelfPermission(
8808                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8809                PackageManager.PERMISSION_GRANTED) {
8810            throw new SecurityException("Must hold permission " +
8811                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8812        }
8813        final long ident = Binder.clearCallingIdentity();
8814        try {
8815            synchronized(mWindowMap) {
8816                DisplayContent displayContent = getDisplayContentLocked(displayId);
8817                if (displayContent != null) {
8818                    setOverscanLocked(displayContent, left, top, right, bottom);
8819                }
8820            }
8821        } finally {
8822            Binder.restoreCallingIdentity(ident);
8823        }
8824    }
8825
8826    private void setOverscanLocked(DisplayContent displayContent,
8827            int left, int top, int right, int bottom) {
8828        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
8829        displayInfo.overscanLeft = left;
8830        displayInfo.overscanTop = top;
8831        displayInfo.overscanRight = right;
8832        displayInfo.overscanBottom = bottom;
8833
8834        mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top,
8835                right, bottom);
8836        mDisplaySettings.writeSettingsLocked();
8837
8838        reconfigureDisplayLocked(displayContent);
8839    }
8840
8841    // -------------------------------------------------------------
8842    // Internals
8843    // -------------------------------------------------------------
8844
8845    final WindowState windowForClientLocked(Session session, IWindow client,
8846            boolean throwOnError) {
8847        return windowForClientLocked(session, client.asBinder(), throwOnError);
8848    }
8849
8850    final WindowState windowForClientLocked(Session session, IBinder client,
8851            boolean throwOnError) {
8852        WindowState win = mWindowMap.get(client);
8853        if (localLOGV) Slog.v(
8854            TAG_WM, "Looking up client " + client + ": " + win);
8855        if (win == null) {
8856            RuntimeException ex = new IllegalArgumentException(
8857                    "Requested window " + client + " does not exist");
8858            if (throwOnError) {
8859                throw ex;
8860            }
8861            Slog.w(TAG_WM, "Failed looking up window", ex);
8862            return null;
8863        }
8864        if (session != null && win.mSession != session) {
8865            RuntimeException ex = new IllegalArgumentException(
8866                    "Requested window " + client + " is in session " +
8867                    win.mSession + ", not " + session);
8868            if (throwOnError) {
8869                throw ex;
8870            }
8871            Slog.w(TAG_WM, "Failed looking up window", ex);
8872            return null;
8873        }
8874
8875        return win;
8876    }
8877
8878    final void rebuildAppWindowListLocked() {
8879        rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
8880    }
8881
8882    private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
8883        final WindowList windows = displayContent.getWindowList();
8884        int NW = windows.size();
8885        int i;
8886        int lastBelow = -1;
8887        int numRemoved = 0;
8888
8889        if (mRebuildTmp.length < NW) {
8890            mRebuildTmp = new WindowState[NW+10];
8891        }
8892
8893        // First remove all existing app windows.
8894        i=0;
8895        while (i < NW) {
8896            WindowState w = windows.get(i);
8897            if (w.mAppToken != null) {
8898                WindowState win = windows.remove(i);
8899                win.mRebuilding = true;
8900                mRebuildTmp[numRemoved] = win;
8901                mWindowsChanged = true;
8902                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win);
8903                NW--;
8904                numRemoved++;
8905                continue;
8906            } else if (lastBelow == i-1) {
8907                if (w.mAttrs.type == TYPE_WALLPAPER) {
8908                    lastBelow = i;
8909                }
8910            }
8911            i++;
8912        }
8913
8914        // Keep whatever windows were below the app windows still below,
8915        // by skipping them.
8916        lastBelow++;
8917        i = lastBelow;
8918
8919        // First add all of the exiting app tokens...  these are no longer
8920        // in the main app list, but still have windows shown.  We put them
8921        // in the back because now that the animation is over we no longer
8922        // will care about them.
8923        final ArrayList<TaskStack> stacks = displayContent.getStacks();
8924        final int numStacks = stacks.size();
8925        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8926            AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens;
8927            int NT = exitingAppTokens.size();
8928            for (int j = 0; j < NT; j++) {
8929                i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
8930            }
8931        }
8932
8933        // And add in the still active app tokens in Z order.
8934        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8935            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
8936            final int numTasks = tasks.size();
8937            for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
8938                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8939                final int numTokens = tokens.size();
8940                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
8941                    final AppWindowToken wtoken = tokens.get(tokenNdx);
8942                    if (wtoken.mIsExiting && !wtoken.waitingForReplacement()) {
8943                        continue;
8944                    }
8945                    i = reAddAppWindowsLocked(displayContent, i, wtoken);
8946                }
8947            }
8948        }
8949
8950        i -= lastBelow;
8951        if (i != numRemoved) {
8952            displayContent.layoutNeeded = true;
8953            Slog.w(TAG_WM, "On display=" + displayContent.getDisplayId() + " Rebuild removed "
8954                    + numRemoved + " windows but added " + i + " rebuildAppWindowListLocked() "
8955                    + " callers=" + Debug.getCallers(10));
8956            for (i = 0; i < numRemoved; i++) {
8957                WindowState ws = mRebuildTmp[i];
8958                if (ws.mRebuilding) {
8959                    StringWriter sw = new StringWriter();
8960                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
8961                    ws.dump(pw, "", true);
8962                    pw.flush();
8963                    Slog.w(TAG_WM, "This window was lost: " + ws);
8964                    Slog.w(TAG_WM, sw.toString());
8965                    ws.mWinAnimator.destroySurfaceLocked();
8966                }
8967            }
8968            Slog.w(TAG_WM, "Current app token list:");
8969            dumpAppTokensLocked();
8970            Slog.w(TAG_WM, "Final window list:");
8971            dumpWindowsLocked();
8972        }
8973        Arrays.fill(mRebuildTmp, null);
8974    }
8975
8976    void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
8977        // If the screen is currently frozen or off, then keep
8978        // it frozen/off until this window draws at its new
8979        // orientation.
8980        if (!okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
8981            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w);
8982            w.mOrientationChanging = true;
8983            w.mLastFreezeDuration = 0;
8984            mWindowPlacerLocked.mOrientationChangeComplete = false;
8985            if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) {
8986                mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
8987                // XXX should probably keep timeout from
8988                // when we first froze the display.
8989                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8990                mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
8991                        WINDOW_FREEZE_TIMEOUT_DURATION);
8992            }
8993        }
8994    }
8995
8996    /**
8997     * @return bitmap indicating if another pass through layout must be made.
8998     */
8999    int handleAnimatingStoppedAndTransitionLocked() {
9000        int changes = 0;
9001
9002        mAppTransition.setIdle();
9003
9004        for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) {
9005            final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i);
9006            mAppTransition.notifyAppTransitionFinishedLocked(token);
9007        }
9008        mNoAnimationNotifyOnTransitionFinished.clear();
9009
9010        mWallpaperControllerLocked.hideDeferredWallpapersIfNeeded();
9011
9012        // Restore window app tokens to the ActivityManager views
9013        ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks();
9014        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
9015            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9016            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9017                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9018                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9019                    tokens.get(tokenNdx).sendingToBottom = false;
9020                }
9021            }
9022        }
9023        rebuildAppWindowListLocked();
9024
9025        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
9026        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
9027                "Wallpaper layer changed: assigning layers + relayout");
9028        moveInputMethodWindowsIfNeededLocked(true);
9029        mWindowPlacerLocked.mWallpaperMayChange = true;
9030        // Since the window list has been rebuilt, focus might
9031        // have to be recomputed since the actual order of windows
9032        // might have changed again.
9033        mFocusMayChange = true;
9034
9035        return changes;
9036    }
9037
9038    void updateResizingWindows(final WindowState w) {
9039        final WindowStateAnimator winAnimator = w.mWinAnimator;
9040        if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
9041            w.setInsetsChanged();
9042            boolean configChanged = w.isConfigChanged();
9043            if (DEBUG_CONFIGURATION && configChanged) {
9044                Slog.v(TAG_WM, "Win " + w + " config changed: "
9045                        + mCurConfiguration);
9046            }
9047            final boolean dragResizingChanged = w.isDragResizeChanged()
9048                    && !w.isDragResizingChangeReported();
9049            if (localLOGV) Slog.v(TAG_WM, "Resizing " + w
9050                    + ": configChanged=" + configChanged
9051                    + " dragResizingChanged=" + dragResizingChanged
9052                    + " last=" + w.mLastFrame + " frame=" + w.mFrame);
9053            w.mLastFrame.set(w.mFrame);
9054            if (w.mContentInsetsChanged
9055                    || w.mVisibleInsetsChanged
9056                    || winAnimator.mSurfaceResized
9057                    || w.mOutsetsChanged
9058                    || configChanged
9059                    || dragResizingChanged
9060                    || w.mResizedWhileNotDragResizing) {
9061                if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
9062                    Slog.v(TAG_WM, "Resize reasons for w=" + w + ": "
9063                            + " contentInsetsChanged=" + w.mContentInsetsChanged
9064                            + " " + w.mContentInsets.toShortString()
9065                            + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
9066                            + " " + w.mVisibleInsets.toShortString()
9067                            + " stableInsetsChanged=" + w.mStableInsetsChanged
9068                            + " " + w.mStableInsets.toShortString()
9069                            + " outsetsChanged=" + w.mOutsetsChanged
9070                            + " " + w.mOutsets.toShortString()
9071                            + " surfaceResized=" + winAnimator.mSurfaceResized
9072                            + " configChanged=" + configChanged
9073                            + " dragResizingChanged=" + dragResizingChanged);
9074                }
9075
9076                // If it's a dead window left on screen, and the configuration changed,
9077                // there is nothing we can do about it. Remove the window now.
9078                if (w.mAppToken != null && w.mAppDied) {
9079                    w.mAppToken.removeAllDeadWindows();
9080                    return;
9081                }
9082
9083                w.mLastOverscanInsets.set(w.mOverscanInsets);
9084                w.mLastContentInsets.set(w.mContentInsets);
9085                w.mLastVisibleInsets.set(w.mVisibleInsets);
9086                w.mLastStableInsets.set(w.mStableInsets);
9087                w.mLastOutsets.set(w.mOutsets);
9088                makeWindowFreezingScreenIfNeededLocked(w);
9089                // If the orientation is changing, or we're starting or ending
9090                // a drag resizing action, then we need to hold off on unfreezing
9091                // the display until this window has been redrawn; to do that,
9092                // we need to go through the process of getting informed by the
9093                // application when it has finished drawing.
9094                if (w.mOrientationChanging || dragResizingChanged
9095                        || w.mResizedWhileNotDragResizing) {
9096                    if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
9097                        Slog.v(TAG_WM, "Orientation or resize start waiting for draw"
9098                                + ", mDrawState=DRAW_PENDING in " + w
9099                                + ", surfaceController " + winAnimator.mSurfaceController);
9100                    }
9101                    winAnimator.mDrawState = DRAW_PENDING;
9102                    if (w.mAppToken != null) {
9103                        w.mAppToken.allDrawn = false;
9104                        w.mAppToken.deferClearAllDrawn = false;
9105                    }
9106                }
9107                if (!mResizingWindows.contains(w)) {
9108                    if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG_WM,
9109                            "Resizing window " + w);
9110                    mResizingWindows.add(w);
9111                }
9112            } else if (w.mOrientationChanging) {
9113                if (w.isDrawnLw()) {
9114                    if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
9115                            "Orientation not waiting for draw in "
9116                            + w + ", surfaceController " + winAnimator.mSurfaceController);
9117                    w.mOrientationChanging = false;
9118                    w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
9119                            - mDisplayFreezeTime);
9120                }
9121            }
9122        }
9123    }
9124
9125    void checkDrawnWindowsLocked() {
9126        if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
9127            return;
9128        }
9129        for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
9130            WindowState win = mWaitingForDrawn.get(j);
9131            if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win +
9132                    ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
9133                    " mHasSurface=" + win.mHasSurface +
9134                    " drawState=" + win.mWinAnimator.mDrawState);
9135            if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) {
9136                // Window has been removed or hidden; no draw will now happen, so stop waiting.
9137                if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win);
9138                mWaitingForDrawn.remove(win);
9139            } else if (win.hasDrawnLw()) {
9140                // Window is now drawn (and shown).
9141                if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win);
9142                mWaitingForDrawn.remove(win);
9143            }
9144        }
9145        if (mWaitingForDrawn.isEmpty()) {
9146            if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!");
9147            mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
9148            mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
9149        }
9150    }
9151
9152    void setHoldScreenLocked(final Session newHoldScreen) {
9153        final boolean hold = newHoldScreen != null;
9154
9155        if (hold && mHoldingScreenOn != newHoldScreen) {
9156            mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
9157        }
9158        mHoldingScreenOn = newHoldScreen;
9159
9160        final boolean state = mHoldingScreenWakeLock.isHeld();
9161        if (hold != state) {
9162            if (hold) {
9163                mHoldingScreenWakeLock.acquire();
9164                mPolicy.keepScreenOnStartedLw();
9165            } else {
9166                mPolicy.keepScreenOnStoppedLw();
9167                mHoldingScreenWakeLock.release();
9168            }
9169        }
9170    }
9171
9172    void requestTraversal() {
9173        synchronized (mWindowMap) {
9174            mWindowPlacerLocked.requestTraversal();
9175        }
9176    }
9177
9178    /** Note that Locked in this case is on mLayoutToAnim */
9179    void scheduleAnimationLocked() {
9180        if (!mAnimationScheduled) {
9181            mAnimationScheduled = true;
9182            mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback);
9183        }
9184    }
9185
9186    boolean needsLayout() {
9187        final int numDisplays = mDisplayContents.size();
9188        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9189            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9190            if (displayContent.layoutNeeded) {
9191                return true;
9192            }
9193        }
9194        return false;
9195    }
9196
9197    /** If a window that has an animation specifying a colored background and the current wallpaper
9198     * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
9199     * suddenly disappear. */
9200    int adjustAnimationBackground(WindowStateAnimator winAnimator) {
9201        WindowList windows = winAnimator.mWin.getWindowList();
9202        for (int i = windows.size() - 1; i >= 0; --i) {
9203            WindowState testWin = windows.get(i);
9204            if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
9205                return testWin.mWinAnimator.mAnimLayer;
9206            }
9207        }
9208        return winAnimator.mAnimLayer;
9209    }
9210
9211    boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
9212                                           boolean secure) {
9213        final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
9214        boolean leakedSurface = false;
9215        boolean killedApps = false;
9216
9217        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
9218                winAnimator.mSession.mPid, operation);
9219
9220        final long callingIdentity = Binder.clearCallingIdentity();
9221        try {
9222            // There was some problem...   first, do a sanity check of the window list to make sure
9223            // we haven't left any dangling surfaces around.
9224
9225            Slog.i(TAG_WM, "Out of memory for surface!  Looking for leaks...");
9226            final int numDisplays = mDisplayContents.size();
9227            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9228                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9229                final int numWindows = windows.size();
9230                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9231                    final WindowState ws = windows.get(winNdx);
9232                    final WindowStateAnimator wsa = ws.mWinAnimator;
9233                    if (wsa.mSurfaceController == null) {
9234                        continue;
9235                    }
9236                    if (!mSessions.contains(wsa.mSession)) {
9237                        Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
9238                                + ws + " surface=" + wsa.mSurfaceController
9239                                + " token=" + ws.mToken
9240                                + " pid=" + ws.mSession.mPid
9241                                + " uid=" + ws.mSession.mUid);
9242                        wsa.destroySurface();
9243                        mForceRemoves.add(ws);
9244                        leakedSurface = true;
9245                    } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
9246                        Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
9247                                + ws + " surface=" + wsa.mSurfaceController
9248                                + " token=" + ws.mAppToken
9249                                + " saved=" + ws.mAppToken.hasSavedSurface());
9250                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
9251                        wsa.destroySurface();
9252                        leakedSurface = true;
9253                    }
9254                }
9255            }
9256
9257            if (!leakedSurface) {
9258                Slog.w(TAG_WM, "No leaked surfaces; killing applicatons!");
9259                SparseIntArray pidCandidates = new SparseIntArray();
9260                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9261                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9262                    final int numWindows = windows.size();
9263                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9264                        final WindowState ws = windows.get(winNdx);
9265                        if (mForceRemoves.contains(ws)) {
9266                            continue;
9267                        }
9268                        WindowStateAnimator wsa = ws.mWinAnimator;
9269                        if (wsa.mSurfaceController != null) {
9270                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
9271                        }
9272                    }
9273                    if (pidCandidates.size() > 0) {
9274                        int[] pids = new int[pidCandidates.size()];
9275                        for (int i=0; i<pids.length; i++) {
9276                            pids[i] = pidCandidates.keyAt(i);
9277                        }
9278                        try {
9279                            if (mActivityManager.killPids(pids, "Free memory", secure)) {
9280                                killedApps = true;
9281                            }
9282                        } catch (RemoteException e) {
9283                        }
9284                    }
9285                }
9286            }
9287
9288            if (leakedSurface || killedApps) {
9289                // We managed to reclaim some memory, so get rid of the trouble
9290                // surface and ask the app to request another one.
9291                Slog.w(TAG_WM, "Looks like we have reclaimed some memory, clearing surface for retry.");
9292                if (surfaceController != null) {
9293                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
9294                            "RECOVER DESTROY", false);
9295                    winAnimator.destroySurface();
9296                    scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken);
9297                }
9298
9299                try {
9300                    winAnimator.mWin.mClient.dispatchGetNewSurface();
9301                } catch (RemoteException e) {
9302                }
9303            }
9304        } finally {
9305            Binder.restoreCallingIdentity(callingIdentity);
9306        }
9307
9308        return leakedSurface || killedApps;
9309    }
9310
9311    boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
9312        WindowState newFocus = computeFocusedWindowLocked();
9313        if (mCurrentFocus != newFocus) {
9314            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
9315            // This check makes sure that we don't already have the focus
9316            // change message pending.
9317            mH.removeMessages(H.REPORT_FOCUS_CHANGE);
9318            mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
9319            // TODO(multidisplay): Focused windows on default display only.
9320            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9321            final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
9322                    mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
9323                            && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
9324            if (imWindowChanged) {
9325                displayContent.layoutNeeded = true;
9326                newFocus = computeFocusedWindowLocked();
9327            }
9328
9329            if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG_WM, "Changing focus from " +
9330                    mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
9331            final WindowState oldFocus = mCurrentFocus;
9332            mCurrentFocus = newFocus;
9333            mLosingFocus.remove(newFocus);
9334
9335            int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
9336
9337            if (imWindowChanged && oldFocus != mInputMethodWindow) {
9338                // Focus of the input method window changed. Perform layout if needed.
9339                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9340                    mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
9341                            updateInputWindows);
9342                    focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9343                } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
9344                    // Client will do the layout, but we need to assign layers
9345                    // for handleNewWindowLocked() below.
9346                    mLayersController.assignLayersLocked(displayContent.getWindowList());
9347                }
9348            }
9349
9350            if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9351                // The change in focus caused us to need to do a layout.  Okay.
9352                displayContent.layoutNeeded = true;
9353                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9354                    mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
9355                            updateInputWindows);
9356                }
9357            }
9358
9359            if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
9360                // If we defer assigning layers, then the caller is responsible for
9361                // doing this part.
9362                mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
9363            }
9364
9365            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
9366            return true;
9367        }
9368        return false;
9369    }
9370
9371    private WindowState computeFocusedWindowLocked() {
9372        final int displayCount = mDisplayContents.size();
9373        for (int i = 0; i < displayCount; i++) {
9374            final DisplayContent displayContent = mDisplayContents.valueAt(i);
9375            WindowState win = findFocusedWindowLocked(displayContent);
9376            if (win != null) {
9377                return win;
9378            }
9379        }
9380        return null;
9381    }
9382
9383    WindowState findFocusedWindowLocked(DisplayContent displayContent) {
9384        final WindowList windows = displayContent.getWindowList();
9385        for (int i = windows.size() - 1; i >= 0; i--) {
9386            final WindowState win = windows.get(i);
9387
9388            if (localLOGV || DEBUG_FOCUS) Slog.v(
9389                TAG_WM, "Looking for focus: " + i
9390                + " = " + win
9391                + ", flags=" + win.mAttrs.flags
9392                + ", canReceive=" + win.canReceiveKeys());
9393
9394            if (!win.canReceiveKeys()) {
9395                continue;
9396            }
9397
9398            AppWindowToken wtoken = win.mAppToken;
9399
9400            // If this window's application has been removed, just skip it.
9401            if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
9402                if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
9403                        + (wtoken.removed ? "removed" : "sendingToBottom"));
9404                continue;
9405            }
9406
9407            // Descend through all of the app tokens and find the first that either matches
9408            // win.mAppToken (return win) or mFocusedApp (return null).
9409            if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
9410                    mFocusedApp != null) {
9411                ArrayList<Task> tasks = displayContent.getTasks();
9412                for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9413                    AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9414                    int tokenNdx = tokens.size() - 1;
9415                    for ( ; tokenNdx >= 0; --tokenNdx) {
9416                        final AppWindowToken token = tokens.get(tokenNdx);
9417                        if (wtoken == token) {
9418                            break;
9419                        }
9420                        if (mFocusedApp == token && token.windowsAreFocusable()) {
9421                            // Whoops, we are below the focused app whose windows are focusable...
9422                            // No focus for you!!!
9423                            if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
9424                                    "findFocusedWindow: Reached focused app=" + mFocusedApp);
9425                            return null;
9426                        }
9427                    }
9428                    if (tokenNdx >= 0) {
9429                        // Early exit from loop, must have found the matching token.
9430                        break;
9431                    }
9432                }
9433            }
9434
9435            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + i +
9436                        " = " + win);
9437            return win;
9438        }
9439
9440        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
9441        return null;
9442    }
9443
9444    private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
9445        if (mDisplayFrozen) {
9446            return;
9447        }
9448
9449        if (!mDisplayReady || !mPolicy.isScreenOn()) {
9450            // No need to freeze the screen before the system is ready or if
9451            // the screen is off.
9452            return;
9453        }
9454
9455        if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
9456                "startFreezingDisplayLocked: inTransaction=" + inTransaction
9457                + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim
9458                + " called by " + Debug.getCallers(8));
9459        mScreenFrozenLock.acquire();
9460
9461        mDisplayFrozen = true;
9462        mDisplayFreezeTime = SystemClock.elapsedRealtime();
9463        mLastFinishedFreezeSource = null;
9464
9465        mInputMonitor.freezeInputDispatchingLw();
9466
9467        // Clear the last input window -- that is just used for
9468        // clean transitions between IMEs, and if we are freezing
9469        // the screen then the whole world is changing behind the scenes.
9470        mPolicy.setLastInputMethodWindowLw(null, null);
9471
9472        if (mAppTransition.isTransitionSet()) {
9473            mAppTransition.freeze();
9474        }
9475
9476        if (PROFILE_ORIENTATION) {
9477            File file = new File("/data/system/frozen");
9478            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
9479        }
9480
9481        if (CUSTOM_SCREEN_ROTATION) {
9482            mExitAnimId = exitAnim;
9483            mEnterAnimId = enterAnim;
9484            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9485            final int displayId = displayContent.getDisplayId();
9486            ScreenRotationAnimation screenRotationAnimation =
9487                    mAnimator.getScreenRotationAnimationLocked(displayId);
9488            if (screenRotationAnimation != null) {
9489                screenRotationAnimation.kill();
9490            }
9491
9492            // Check whether the current screen contains any secure content.
9493            boolean isSecure = false;
9494            final WindowList windows = getDefaultWindowListLocked();
9495            final int N = windows.size();
9496            for (int i = 0; i < N; i++) {
9497                WindowState ws = windows.get(i);
9498                if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
9499                    isSecure = true;
9500                    break;
9501                }
9502            }
9503
9504            // TODO(multidisplay): rotation on main screen only.
9505            displayContent.updateDisplayInfo();
9506            screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
9507                    mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure);
9508            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9509        }
9510    }
9511
9512    void stopFreezingDisplayLocked() {
9513        if (!mDisplayFrozen) {
9514            return;
9515        }
9516
9517        if (mWaitingForConfig || mAppsFreezingScreen > 0
9518                || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE
9519                || mClientFreezingScreen || !mOpeningApps.isEmpty()) {
9520            if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
9521                "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
9522                + ", mAppsFreezingScreen=" + mAppsFreezingScreen
9523                + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
9524                + ", mClientFreezingScreen=" + mClientFreezingScreen
9525                + ", mOpeningApps.size()=" + mOpeningApps.size());
9526            return;
9527        }
9528
9529        if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
9530                "stopFreezingDisplayLocked: Unfreezing now");
9531
9532        mDisplayFrozen = false;
9533        mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
9534        StringBuilder sb = new StringBuilder(128);
9535        sb.append("Screen frozen for ");
9536        TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
9537        if (mLastFinishedFreezeSource != null) {
9538            sb.append(" due to ");
9539            sb.append(mLastFinishedFreezeSource);
9540        }
9541        Slog.i(TAG_WM, sb.toString());
9542        mH.removeMessages(H.APP_FREEZE_TIMEOUT);
9543        mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
9544        if (PROFILE_ORIENTATION) {
9545            Debug.stopMethodTracing();
9546        }
9547
9548        boolean updateRotation = false;
9549
9550        final DisplayContent displayContent = getDefaultDisplayContentLocked();
9551        final int displayId = displayContent.getDisplayId();
9552        ScreenRotationAnimation screenRotationAnimation =
9553                mAnimator.getScreenRotationAnimationLocked(displayId);
9554        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
9555                && screenRotationAnimation.hasScreenshot()) {
9556            if (DEBUG_ORIENTATION) Slog.i(TAG_WM, "**** Dismissing screen rotation animation");
9557            // TODO(multidisplay): rotation on main screen only.
9558            DisplayInfo displayInfo = displayContent.getDisplayInfo();
9559            // Get rotation animation again, with new top window
9560            boolean isDimming = displayContent.isDimming();
9561            if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
9562                mExitAnimId = mEnterAnimId = 0;
9563            }
9564            if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
9565                    getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
9566                        displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
9567                scheduleAnimationLocked();
9568            } else {
9569                screenRotationAnimation.kill();
9570                mAnimator.setScreenRotationAnimationLocked(displayId, null);
9571                updateRotation = true;
9572            }
9573        } else {
9574            if (screenRotationAnimation != null) {
9575                screenRotationAnimation.kill();
9576                mAnimator.setScreenRotationAnimationLocked(displayId, null);
9577            }
9578            updateRotation = true;
9579        }
9580
9581        mInputMonitor.thawInputDispatchingLw();
9582
9583        boolean configChanged;
9584
9585        // While the display is frozen we don't re-compute the orientation
9586        // to avoid inconsistent states.  However, something interesting
9587        // could have actually changed during that time so re-evaluate it
9588        // now to catch that.
9589        configChanged = updateOrientationFromAppTokensLocked(false);
9590
9591        // A little kludge: a lot could have happened while the
9592        // display was frozen, so now that we are coming back we
9593        // do a gc so that any remote references the system
9594        // processes holds on others can be released if they are
9595        // no longer needed.
9596        mH.removeMessages(H.FORCE_GC);
9597        mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
9598
9599        mScreenFrozenLock.release();
9600
9601        if (updateRotation) {
9602            if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation");
9603            configChanged |= updateRotationUncheckedLocked(false);
9604        }
9605
9606        if (configChanged) {
9607            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9608        }
9609    }
9610
9611    static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
9612            DisplayMetrics dm) {
9613        if (index < tokens.length) {
9614            String str = tokens[index];
9615            if (str != null && str.length() > 0) {
9616                try {
9617                    int val = Integer.parseInt(str);
9618                    return val;
9619                } catch (Exception e) {
9620                }
9621            }
9622        }
9623        if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
9624            return defDps;
9625        }
9626        int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
9627        return val;
9628    }
9629
9630    void createWatermarkInTransaction() {
9631        if (mWatermark != null) {
9632            return;
9633        }
9634
9635        File file = new File("/system/etc/setup.conf");
9636        FileInputStream in = null;
9637        DataInputStream ind = null;
9638        try {
9639            in = new FileInputStream(file);
9640            ind = new DataInputStream(in);
9641            String line = ind.readLine();
9642            if (line != null) {
9643                String[] toks = line.split("%");
9644                if (toks != null && toks.length > 0) {
9645                    mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
9646                            mRealDisplayMetrics, mFxSession, toks);
9647                }
9648            }
9649        } catch (FileNotFoundException e) {
9650        } catch (IOException e) {
9651        } finally {
9652            if (ind != null) {
9653                try {
9654                    ind.close();
9655                } catch (IOException e) {
9656                }
9657            } else if (in != null) {
9658                try {
9659                    in.close();
9660                } catch (IOException e) {
9661                }
9662            }
9663        }
9664    }
9665
9666    @Override
9667    public void statusBarVisibilityChanged(int visibility) {
9668        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
9669                != PackageManager.PERMISSION_GRANTED) {
9670            throw new SecurityException("Caller does not hold permission "
9671                    + android.Manifest.permission.STATUS_BAR);
9672        }
9673
9674        synchronized (mWindowMap) {
9675            mLastStatusBarVisibility = visibility;
9676            visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
9677            updateStatusBarVisibilityLocked(visibility);
9678        }
9679    }
9680
9681    // TOOD(multidisplay): StatusBar on multiple screens?
9682    boolean updateStatusBarVisibilityLocked(int visibility) {
9683        if (mLastDispatchedSystemUiVisibility == visibility) {
9684            return false;
9685        }
9686        final int globalDiff = (visibility ^ mLastDispatchedSystemUiVisibility)
9687                // We are only interested in differences of one of the
9688                // clearable flags...
9689                & View.SYSTEM_UI_CLEARABLE_FLAGS
9690                // ...if it has actually been cleared.
9691                & ~visibility;
9692
9693        mLastDispatchedSystemUiVisibility = visibility;
9694        mInputManager.setSystemUiVisibility(visibility);
9695        final WindowList windows = getDefaultWindowListLocked();
9696        final int N = windows.size();
9697        for (int i = 0; i < N; i++) {
9698            WindowState ws = windows.get(i);
9699            try {
9700                int curValue = ws.mSystemUiVisibility;
9701                int diff = (curValue ^ visibility) & globalDiff;
9702                int newValue = (curValue&~diff) | (visibility&diff);
9703                if (newValue != curValue) {
9704                    ws.mSeq++;
9705                    ws.mSystemUiVisibility = newValue;
9706                }
9707                if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
9708                    ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
9709                            visibility, newValue, diff);
9710                }
9711            } catch (RemoteException e) {
9712                // so sorry
9713            }
9714        }
9715        return true;
9716    }
9717
9718    @Override
9719    public void reevaluateStatusBarVisibility() {
9720        synchronized (mWindowMap) {
9721            int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
9722            if (updateStatusBarVisibilityLocked(visibility)) {
9723                mWindowPlacerLocked.requestTraversal();
9724            }
9725        }
9726    }
9727
9728    private static final class HideNavInputConsumer extends InputConsumerImpl
9729            implements WindowManagerPolicy.InputConsumer {
9730        private final InputEventReceiver mInputEventReceiver;
9731
9732        HideNavInputConsumer(WindowManagerService service, Looper looper,
9733                             InputEventReceiver.Factory inputEventReceiverFactory) {
9734            super(service, "input consumer", null);
9735            mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver(
9736                    mClientChannel, looper);
9737        }
9738
9739        @Override
9740        public void dismiss() {
9741            if (mService.removeInputConsumer()) {
9742                synchronized (mService.mWindowMap) {
9743                    mInputEventReceiver.dispose();
9744                    disposeChannelsLw();
9745                }
9746            }
9747        }
9748    }
9749
9750    @Override
9751    public WindowManagerPolicy.InputConsumer addInputConsumer(Looper looper,
9752            InputEventReceiver.Factory inputEventReceiverFactory) {
9753        synchronized (mWindowMap) {
9754            HideNavInputConsumer inputConsumerImpl = new HideNavInputConsumer(
9755                    this, looper, inputEventReceiverFactory);
9756            mInputConsumer = inputConsumerImpl;
9757            mInputMonitor.updateInputWindowsLw(true);
9758            return inputConsumerImpl;
9759        }
9760    }
9761
9762    boolean removeInputConsumer() {
9763        synchronized (mWindowMap) {
9764            if (mInputConsumer != null) {
9765                mInputConsumer = null;
9766                mInputMonitor.updateInputWindowsLw(true);
9767                return true;
9768            }
9769            return false;
9770        }
9771    }
9772
9773    public void createWallpaperInputConsumer(InputChannel inputChannel) {
9774        synchronized (mWindowMap) {
9775            mWallpaperInputConsumer = new InputConsumerImpl(this, "wallpaper input", inputChannel);
9776            mWallpaperInputConsumer.mWindowHandle.hasWallpaper = true;
9777            mInputMonitor.updateInputWindowsLw(true);
9778        }
9779    }
9780
9781    public void removeWallpaperInputConsumer() {
9782        synchronized (mWindowMap) {
9783            if (mWallpaperInputConsumer != null) {
9784                mWallpaperInputConsumer.disposeChannelsLw();
9785                mWallpaperInputConsumer = null;
9786                mInputMonitor.updateInputWindowsLw(true);
9787            }
9788        }
9789    }
9790
9791    @Override
9792    public boolean hasNavigationBar() {
9793        return mPolicy.hasNavigationBar();
9794    }
9795
9796    @Override
9797    public void lockNow(Bundle options) {
9798        mPolicy.lockNow(options);
9799    }
9800
9801    public void showRecentApps() {
9802        mPolicy.showRecentApps();
9803    }
9804
9805    @Override
9806    public boolean isSafeModeEnabled() {
9807        return mSafeMode;
9808    }
9809
9810    @Override
9811    public boolean clearWindowContentFrameStats(IBinder token) {
9812        if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
9813                "clearWindowContentFrameStats()")) {
9814            throw new SecurityException("Requires FRAME_STATS permission");
9815        }
9816        synchronized (mWindowMap) {
9817            WindowState windowState = mWindowMap.get(token);
9818            if (windowState == null) {
9819                return false;
9820            }
9821            WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
9822            if (surfaceController == null) {
9823                return false;
9824            }
9825            return surfaceController.clearWindowContentFrameStats();
9826        }
9827    }
9828
9829    @Override
9830    public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
9831        if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
9832                "getWindowContentFrameStats()")) {
9833            throw new SecurityException("Requires FRAME_STATS permission");
9834        }
9835        synchronized (mWindowMap) {
9836            WindowState windowState = mWindowMap.get(token);
9837            if (windowState == null) {
9838                return null;
9839            }
9840            WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
9841            if (surfaceController == null) {
9842                return null;
9843            }
9844            if (mTempWindowRenderStats == null) {
9845                mTempWindowRenderStats = new WindowContentFrameStats();
9846            }
9847            WindowContentFrameStats stats = mTempWindowRenderStats;
9848            if (!surfaceController.getWindowContentFrameStats(stats)) {
9849                return null;
9850            }
9851            return stats;
9852        }
9853    }
9854
9855    public void notifyAppRelaunching(IBinder token) {
9856        synchronized (mWindowMap) {
9857            AppWindowToken appWindow = findAppWindowToken(token);
9858            if (appWindow != null) {
9859                appWindow.startRelaunching();
9860            }
9861        }
9862    }
9863
9864    public void notifyAppRelaunchingFinished(IBinder token) {
9865        synchronized (mWindowMap) {
9866            AppWindowToken appWindow = findAppWindowToken(token);
9867            if (appWindow != null) {
9868                appWindow.finishRelaunching();
9869            }
9870        }
9871    }
9872
9873    @Override
9874    public int getDockedDividerInsetsLw() {
9875        return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets();
9876    }
9877
9878    void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
9879        pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
9880        mPolicy.dump("    ", pw, args);
9881    }
9882
9883    void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
9884        pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
9885        mAnimator.dumpLocked(pw, "    ", dumpAll);
9886    }
9887
9888    void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
9889        pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
9890        if (!mTokenMap.isEmpty()) {
9891            pw.println("  All tokens:");
9892            Iterator<WindowToken> it = mTokenMap.values().iterator();
9893            while (it.hasNext()) {
9894                WindowToken token = it.next();
9895                pw.print("  "); pw.print(token);
9896                if (dumpAll) {
9897                    pw.println(':');
9898                    token.dump(pw, "    ");
9899                } else {
9900                    pw.println();
9901                }
9902            }
9903        }
9904        mWallpaperControllerLocked.dumpTokens(pw, "  ", dumpAll);
9905        if (!mFinishedStarting.isEmpty()) {
9906            pw.println();
9907            pw.println("  Finishing start of application tokens:");
9908            for (int i=mFinishedStarting.size()-1; i>=0; i--) {
9909                WindowToken token = mFinishedStarting.get(i);
9910                pw.print("  Finished Starting #"); pw.print(i);
9911                        pw.print(' '); pw.print(token);
9912                if (dumpAll) {
9913                    pw.println(':');
9914                    token.dump(pw, "    ");
9915                } else {
9916                    pw.println();
9917                }
9918            }
9919        }
9920        if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) {
9921            pw.println();
9922            if (mOpeningApps.size() > 0) {
9923                pw.print("  mOpeningApps="); pw.println(mOpeningApps);
9924            }
9925            if (mClosingApps.size() > 0) {
9926                pw.print("  mClosingApps="); pw.println(mClosingApps);
9927            }
9928        }
9929    }
9930
9931    void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
9932        pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
9933        for (int i=0; i<mSessions.size(); i++) {
9934            Session s = mSessions.valueAt(i);
9935            pw.print("  Session "); pw.print(s); pw.println(':');
9936            s.dump(pw, "    ");
9937        }
9938    }
9939
9940    void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
9941        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
9942        if (mDisplayReady) {
9943            final int numDisplays = mDisplayContents.size();
9944            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9945                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9946                displayContent.dump("  ", pw);
9947            }
9948        } else {
9949            pw.println("  NO DISPLAY");
9950        }
9951    }
9952
9953    void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
9954            ArrayList<WindowState> windows) {
9955        pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
9956        dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
9957    }
9958
9959    void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
9960            ArrayList<WindowState> windows) {
9961        final int numDisplays = mDisplayContents.size();
9962        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9963            final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
9964            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
9965                final WindowState w = windowList.get(winNdx);
9966                if (windows == null || windows.contains(w)) {
9967                    pw.print("  Window #"); pw.print(winNdx); pw.print(' ');
9968                            pw.print(w); pw.println(":");
9969                    w.dump(pw, "    ", dumpAll || windows != null);
9970                }
9971            }
9972        }
9973        if (mInputMethodDialogs.size() > 0) {
9974            pw.println();
9975            pw.println("  Input method dialogs:");
9976            for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
9977                WindowState w = mInputMethodDialogs.get(i);
9978                if (windows == null || windows.contains(w)) {
9979                    pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
9980                }
9981            }
9982        }
9983        if (mPendingRemove.size() > 0) {
9984            pw.println();
9985            pw.println("  Remove pending for:");
9986            for (int i=mPendingRemove.size()-1; i>=0; i--) {
9987                WindowState w = mPendingRemove.get(i);
9988                if (windows == null || windows.contains(w)) {
9989                    pw.print("  Remove #"); pw.print(i); pw.print(' ');
9990                            pw.print(w);
9991                    if (dumpAll) {
9992                        pw.println(":");
9993                        w.dump(pw, "    ", true);
9994                    } else {
9995                        pw.println();
9996                    }
9997                }
9998            }
9999        }
10000        if (mForceRemoves != null && mForceRemoves.size() > 0) {
10001            pw.println();
10002            pw.println("  Windows force removing:");
10003            for (int i=mForceRemoves.size()-1; i>=0; i--) {
10004                WindowState w = mForceRemoves.get(i);
10005                pw.print("  Removing #"); pw.print(i); pw.print(' ');
10006                        pw.print(w);
10007                if (dumpAll) {
10008                    pw.println(":");
10009                    w.dump(pw, "    ", true);
10010                } else {
10011                    pw.println();
10012                }
10013            }
10014        }
10015        if (mDestroySurface.size() > 0) {
10016            pw.println();
10017            pw.println("  Windows waiting to destroy their surface:");
10018            for (int i=mDestroySurface.size()-1; i>=0; i--) {
10019                WindowState w = mDestroySurface.get(i);
10020                if (windows == null || windows.contains(w)) {
10021                    pw.print("  Destroy #"); pw.print(i); pw.print(' ');
10022                            pw.print(w);
10023                    if (dumpAll) {
10024                        pw.println(":");
10025                        w.dump(pw, "    ", true);
10026                    } else {
10027                        pw.println();
10028                    }
10029                }
10030            }
10031        }
10032        if (mLosingFocus.size() > 0) {
10033            pw.println();
10034            pw.println("  Windows losing focus:");
10035            for (int i=mLosingFocus.size()-1; i>=0; i--) {
10036                WindowState w = mLosingFocus.get(i);
10037                if (windows == null || windows.contains(w)) {
10038                    pw.print("  Losing #"); pw.print(i); pw.print(' ');
10039                            pw.print(w);
10040                    if (dumpAll) {
10041                        pw.println(":");
10042                        w.dump(pw, "    ", true);
10043                    } else {
10044                        pw.println();
10045                    }
10046                }
10047            }
10048        }
10049        if (mResizingWindows.size() > 0) {
10050            pw.println();
10051            pw.println("  Windows waiting to resize:");
10052            for (int i=mResizingWindows.size()-1; i>=0; i--) {
10053                WindowState w = mResizingWindows.get(i);
10054                if (windows == null || windows.contains(w)) {
10055                    pw.print("  Resizing #"); pw.print(i); pw.print(' ');
10056                            pw.print(w);
10057                    if (dumpAll) {
10058                        pw.println(":");
10059                        w.dump(pw, "    ", true);
10060                    } else {
10061                        pw.println();
10062                    }
10063                }
10064            }
10065        }
10066        if (mWaitingForDrawn.size() > 0) {
10067            pw.println();
10068            pw.println("  Clients waiting for these windows to be drawn:");
10069            for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
10070                WindowState win = mWaitingForDrawn.get(i);
10071                pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
10072            }
10073        }
10074        pw.println();
10075        pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
10076        pw.print("  mHasPermanentDpad="); pw.println(mHasPermanentDpad);
10077        pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
10078        if (mLastFocus != mCurrentFocus) {
10079            pw.print("  mLastFocus="); pw.println(mLastFocus);
10080        }
10081        pw.print("  mFocusedApp="); pw.println(mFocusedApp);
10082        if (mInputMethodTarget != null) {
10083            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
10084        }
10085        pw.print("  mInTouchMode="); pw.print(mInTouchMode);
10086                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
10087        pw.print("  mLastDisplayFreezeDuration=");
10088                TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
10089                if ( mLastFinishedFreezeSource != null) {
10090                    pw.print(" due to ");
10091                    pw.print(mLastFinishedFreezeSource);
10092                }
10093                pw.println();
10094
10095        mInputMonitor.dump(pw, "  ");
10096
10097        if (dumpAll) {
10098            pw.print("  mSystemDecorLayer="); pw.print(mSystemDecorLayer);
10099                    pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
10100            if (mLastStatusBarVisibility != 0) {
10101                pw.print("  mLastStatusBarVisibility=0x");
10102                        pw.println(Integer.toHexString(mLastStatusBarVisibility));
10103            }
10104            if (mInputMethodWindow != null) {
10105                pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
10106            }
10107            mWindowPlacerLocked.dump(pw, "  ");
10108            mWallpaperControllerLocked.dump(pw, "  ");
10109            mLayersController.dump(pw, "  ");
10110            pw.print("  mSystemBooted="); pw.print(mSystemBooted);
10111                    pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10112            if (needsLayout()) {
10113                pw.print("  layoutNeeded on displays=");
10114                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10115                    final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10116                    if (displayContent.layoutNeeded) {
10117                        pw.print(displayContent.getDisplayId());
10118                    }
10119                }
10120                pw.println();
10121            }
10122            pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
10123            pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
10124                    pw.print(" windows="); pw.print(mWindowsFreezingScreen);
10125                    pw.print(" client="); pw.print(mClientFreezingScreen);
10126                    pw.print(" apps="); pw.print(mAppsFreezingScreen);
10127                    pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
10128            pw.print("  mRotation="); pw.print(mRotation);
10129                    pw.print(" mAltOrientation="); pw.println(mAltOrientation);
10130            pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
10131                    pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
10132            pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
10133            pw.print("  Animation settings: disabled="); pw.print(mAnimationsDisabled);
10134                    pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
10135                    pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
10136                    pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
10137            pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation);
10138            pw.println("  mLayoutToAnim:");
10139            mAppTransition.dump(pw, "    ");
10140        }
10141    }
10142
10143    boolean dumpWindows(PrintWriter pw, String name, String[] args,
10144            int opti, boolean dumpAll) {
10145        WindowList windows = new WindowList();
10146        if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
10147            final boolean appsOnly = name.contains("apps");
10148            final boolean visibleOnly = name.contains("visible");
10149            synchronized(mWindowMap) {
10150                if (appsOnly) {
10151                    dumpDisplayContentsLocked(pw, true);
10152                }
10153
10154                final int numDisplays = mDisplayContents.size();
10155                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10156                    final WindowList windowList =
10157                            mDisplayContents.valueAt(displayNdx).getWindowList();
10158                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10159                        final WindowState w = windowList.get(winNdx);
10160                        if ((!visibleOnly || w.mWinAnimator.getShown())
10161                                && (!appsOnly || w.mAppToken != null)) {
10162                            windows.add(w);
10163                        }
10164                    }
10165                }
10166            }
10167        } else {
10168            int objectId = 0;
10169            // See if this is an object ID.
10170            try {
10171                objectId = Integer.parseInt(name, 16);
10172                name = null;
10173            } catch (RuntimeException e) {
10174            }
10175            synchronized(mWindowMap) {
10176                final int numDisplays = mDisplayContents.size();
10177                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10178                    final WindowList windowList =
10179                            mDisplayContents.valueAt(displayNdx).getWindowList();
10180                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10181                        final WindowState w = windowList.get(winNdx);
10182                        if (name != null) {
10183                            if (w.mAttrs.getTitle().toString().contains(name)) {
10184                                windows.add(w);
10185                            }
10186                        } else if (System.identityHashCode(w) == objectId) {
10187                            windows.add(w);
10188                        }
10189                    }
10190                }
10191            }
10192        }
10193
10194        if (windows.size() <= 0) {
10195            return false;
10196        }
10197
10198        synchronized(mWindowMap) {
10199            dumpWindowsLocked(pw, dumpAll, windows);
10200        }
10201        return true;
10202    }
10203
10204    void dumpLastANRLocked(PrintWriter pw) {
10205        pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
10206        if (mLastANRState == null) {
10207            pw.println("  <no ANR has occurred since boot>");
10208        } else {
10209            pw.println(mLastANRState);
10210        }
10211    }
10212
10213    /**
10214     * Saves information about the state of the window manager at
10215     * the time an ANR occurred before anything else in the system changes
10216     * in response.
10217     *
10218     * @param appWindowToken The application that ANR'd, may be null.
10219     * @param windowState The window that ANR'd, may be null.
10220     * @param reason The reason for the ANR, may be null.
10221     */
10222    public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
10223            String reason) {
10224        StringWriter sw = new StringWriter();
10225        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
10226        pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
10227        if (appWindowToken != null) {
10228            pw.println("  Application at fault: " + appWindowToken.stringName);
10229        }
10230        if (windowState != null) {
10231            pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
10232        }
10233        if (reason != null) {
10234            pw.println("  Reason: " + reason);
10235        }
10236        pw.println();
10237        dumpWindowsNoHeaderLocked(pw, true, null);
10238        pw.println();
10239        pw.println("Last ANR continued");
10240        dumpDisplayContentsLocked(pw, true);
10241        pw.close();
10242        mLastANRState = sw.toString();
10243
10244        mH.removeMessages(H.RESET_ANR_MESSAGE);
10245        mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS);
10246    }
10247
10248    @Override
10249    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10250        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
10251                != PackageManager.PERMISSION_GRANTED) {
10252            pw.println("Permission Denial: can't dump WindowManager from from pid="
10253                    + Binder.getCallingPid()
10254                    + ", uid=" + Binder.getCallingUid());
10255            return;
10256        }
10257
10258        boolean dumpAll = false;
10259
10260        int opti = 0;
10261        while (opti < args.length) {
10262            String opt = args[opti];
10263            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10264                break;
10265            }
10266            opti++;
10267            if ("-a".equals(opt)) {
10268                dumpAll = true;
10269            } else if ("-h".equals(opt)) {
10270                pw.println("Window manager dump options:");
10271                pw.println("  [-a] [-h] [cmd] ...");
10272                pw.println("  cmd may be one of:");
10273                pw.println("    l[astanr]: last ANR information");
10274                pw.println("    p[policy]: policy state");
10275                pw.println("    a[animator]: animator state");
10276                pw.println("    s[essions]: active sessions");
10277                pw.println("    surfaces: active surfaces (debugging enabled only)");
10278                pw.println("    d[isplays]: active display contents");
10279                pw.println("    t[okens]: token list");
10280                pw.println("    w[indows]: window list");
10281                pw.println("  cmd may also be a NAME to dump windows.  NAME may");
10282                pw.println("    be a partial substring in a window name, a");
10283                pw.println("    Window hex object identifier, or");
10284                pw.println("    \"all\" for all windows, or");
10285                pw.println("    \"visible\" for the visible windows.");
10286                pw.println("    \"visible-apps\" for the visible app windows.");
10287                pw.println("  -a: include all available server state.");
10288                return;
10289            } else {
10290                pw.println("Unknown argument: " + opt + "; use -h for help");
10291            }
10292        }
10293
10294        // Is the caller requesting to dump a particular piece of data?
10295        if (opti < args.length) {
10296            String cmd = args[opti];
10297            opti++;
10298            if ("lastanr".equals(cmd) || "l".equals(cmd)) {
10299                synchronized(mWindowMap) {
10300                    dumpLastANRLocked(pw);
10301                }
10302                return;
10303            } else if ("policy".equals(cmd) || "p".equals(cmd)) {
10304                synchronized(mWindowMap) {
10305                    dumpPolicyLocked(pw, args, true);
10306                }
10307                return;
10308            } else if ("animator".equals(cmd) || "a".equals(cmd)) {
10309                synchronized(mWindowMap) {
10310                    dumpAnimatorLocked(pw, args, true);
10311                }
10312                return;
10313            } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
10314                synchronized(mWindowMap) {
10315                    dumpSessionsLocked(pw, true);
10316                }
10317                return;
10318            } else if ("surfaces".equals(cmd)) {
10319                synchronized(mWindowMap) {
10320                    WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, null);
10321                }
10322                return;
10323            } else if ("displays".equals(cmd) || "d".equals(cmd)) {
10324                synchronized(mWindowMap) {
10325                    dumpDisplayContentsLocked(pw, true);
10326                }
10327                return;
10328            } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
10329                synchronized(mWindowMap) {
10330                    dumpTokensLocked(pw, true);
10331                }
10332                return;
10333            } else if ("windows".equals(cmd) || "w".equals(cmd)) {
10334                synchronized(mWindowMap) {
10335                    dumpWindowsLocked(pw, true, null);
10336                }
10337                return;
10338            } else if ("all".equals(cmd) || "a".equals(cmd)) {
10339                synchronized(mWindowMap) {
10340                    dumpWindowsLocked(pw, true, null);
10341                }
10342                return;
10343            } else {
10344                // Dumping a single name?
10345                if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
10346                    pw.println("Bad window command, or no windows match: " + cmd);
10347                    pw.println("Use -h for help.");
10348                }
10349                return;
10350            }
10351        }
10352
10353        synchronized(mWindowMap) {
10354            pw.println();
10355            if (dumpAll) {
10356                pw.println("-------------------------------------------------------------------------------");
10357            }
10358            dumpLastANRLocked(pw);
10359            pw.println();
10360            if (dumpAll) {
10361                pw.println("-------------------------------------------------------------------------------");
10362            }
10363            dumpPolicyLocked(pw, args, dumpAll);
10364            pw.println();
10365            if (dumpAll) {
10366                pw.println("-------------------------------------------------------------------------------");
10367            }
10368            dumpAnimatorLocked(pw, args, dumpAll);
10369            pw.println();
10370            if (dumpAll) {
10371                pw.println("-------------------------------------------------------------------------------");
10372            }
10373            dumpSessionsLocked(pw, dumpAll);
10374            pw.println();
10375            if (dumpAll) {
10376                pw.println("-------------------------------------------------------------------------------");
10377            }
10378            WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ?
10379                    "-------------------------------------------------------------------------------"
10380                    : null);
10381            pw.println();
10382            if (dumpAll) {
10383                pw.println("-------------------------------------------------------------------------------");
10384            }
10385            dumpDisplayContentsLocked(pw, dumpAll);
10386            pw.println();
10387            if (dumpAll) {
10388                pw.println("-------------------------------------------------------------------------------");
10389            }
10390            dumpTokensLocked(pw, dumpAll);
10391            pw.println();
10392            if (dumpAll) {
10393                pw.println("-------------------------------------------------------------------------------");
10394            }
10395            dumpWindowsLocked(pw, dumpAll, null);
10396        }
10397    }
10398
10399    // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
10400    @Override
10401    public void monitor() {
10402        synchronized (mWindowMap) { }
10403    }
10404
10405    private DisplayContent newDisplayContentLocked(final Display display) {
10406        DisplayContent displayContent = new DisplayContent(display, this);
10407        final int displayId = display.getDisplayId();
10408        if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
10409        mDisplayContents.put(displayId, displayContent);
10410
10411        DisplayInfo displayInfo = displayContent.getDisplayInfo();
10412        final Rect rect = new Rect();
10413        mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
10414        displayInfo.overscanLeft = rect.left;
10415        displayInfo.overscanTop = rect.top;
10416        displayInfo.overscanRight = rect.right;
10417        displayInfo.overscanBottom = rect.bottom;
10418        mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId, displayInfo);
10419        configureDisplayPolicyLocked(displayContent);
10420
10421        // TODO: Create an input channel for each display with touch capability.
10422        if (displayId == Display.DEFAULT_DISPLAY) {
10423            displayContent.mTapDetector = new TaskTapPointerEventListener(this, displayContent);
10424            registerPointerEventListener(displayContent.mTapDetector);
10425            registerPointerEventListener(mMousePositionTracker);
10426        }
10427
10428        return displayContent;
10429    }
10430
10431    public void createDisplayContentLocked(final Display display) {
10432        if (display == null) {
10433            throw new IllegalArgumentException("getDisplayContent: display must not be null");
10434        }
10435        getDisplayContentLocked(display.getDisplayId());
10436    }
10437
10438    /**
10439     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
10440     * there is a Display for the displayId.
10441     * @param displayId The display the caller is interested in.
10442     * @return The DisplayContent associated with displayId or null if there is no Display for it.
10443     */
10444    public DisplayContent getDisplayContentLocked(final int displayId) {
10445        DisplayContent displayContent = mDisplayContents.get(displayId);
10446        if (displayContent == null) {
10447            final Display display = mDisplayManager.getDisplay(displayId);
10448            if (display != null) {
10449                displayContent = newDisplayContentLocked(display);
10450            }
10451        }
10452        return displayContent;
10453    }
10454
10455    // There is an inherent assumption that this will never return null.
10456    public DisplayContent getDefaultDisplayContentLocked() {
10457        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
10458    }
10459
10460    public WindowList getDefaultWindowListLocked() {
10461        return getDefaultDisplayContentLocked().getWindowList();
10462    }
10463
10464    public DisplayInfo getDefaultDisplayInfoLocked() {
10465        return getDefaultDisplayContentLocked().getDisplayInfo();
10466    }
10467
10468    /**
10469     * Return the list of WindowStates associated on the passed display.
10470     * @param display The screen to return windows from.
10471     * @return The list of WindowStates on the screen, or null if the there is no screen.
10472     */
10473    public WindowList getWindowListLocked(final Display display) {
10474        return getWindowListLocked(display.getDisplayId());
10475    }
10476
10477    /**
10478     * Return the list of WindowStates associated on the passed display.
10479     * @param displayId The screen to return windows from.
10480     * @return The list of WindowStates on the screen, or null if the there is no screen.
10481     */
10482    public WindowList getWindowListLocked(final int displayId) {
10483        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10484        return displayContent != null ? displayContent.getWindowList() : null;
10485    }
10486
10487    public void onDisplayAdded(int displayId) {
10488        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
10489    }
10490
10491    public void handleDisplayAdded(int displayId) {
10492        synchronized (mWindowMap) {
10493            final Display display = mDisplayManager.getDisplay(displayId);
10494            if (display != null) {
10495                createDisplayContentLocked(display);
10496                displayReady(displayId);
10497            }
10498            mWindowPlacerLocked.requestTraversal();
10499        }
10500    }
10501
10502    public void onDisplayRemoved(int displayId) {
10503        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
10504    }
10505
10506    private void handleDisplayRemovedLocked(int displayId) {
10507        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10508        if (displayContent != null) {
10509            if (displayContent.isAnimating()) {
10510                displayContent.mDeferredRemoval = true;
10511                return;
10512            }
10513            if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + displayContent);
10514            mDisplayContents.delete(displayId);
10515            displayContent.close();
10516            if (displayId == Display.DEFAULT_DISPLAY) {
10517                unregisterPointerEventListener(displayContent.mTapDetector);
10518                unregisterPointerEventListener(mMousePositionTracker);
10519            }
10520        }
10521        mAnimator.removeDisplayLocked(displayId);
10522        mWindowPlacerLocked.requestTraversal();
10523    }
10524
10525    public void onDisplayChanged(int displayId) {
10526        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
10527    }
10528
10529    private void handleDisplayChangedLocked(int displayId) {
10530        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10531        if (displayContent != null) {
10532            displayContent.updateDisplayInfo();
10533        }
10534        mWindowPlacerLocked.requestTraversal();
10535    }
10536
10537    @Override
10538    public Object getWindowManagerLock() {
10539        return mWindowMap;
10540    }
10541
10542    /**
10543     * Hint to a token that its activity will relaunch, which will trigger removal and addition of
10544     * a window.
10545     * @param token Application token for which the activity will be relaunched.
10546     */
10547    public void setReplacingWindow(IBinder token, boolean animate) {
10548        AppWindowToken appWindowToken = null;
10549        synchronized (mWindowMap) {
10550            appWindowToken = findAppWindowToken(token);
10551            if (appWindowToken == null || !appWindowToken.isVisible()) {
10552                Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
10553                        + token);
10554                return;
10555            }
10556            appWindowToken.setReplacingWindows(animate);
10557        }
10558    }
10559
10560    /**
10561     * Hint to a token that its children will be replaced across activity relaunch.
10562     * The children would otherwise be removed  shortly following this as the
10563     * activity is torn down.
10564     * @param token Application token for which the activity will be relaunched.
10565     */
10566    public void setReplacingChildren(IBinder token) {
10567        AppWindowToken appWindowToken = null;
10568        synchronized (mWindowMap) {
10569            appWindowToken = findAppWindowToken(token);
10570            if (appWindowToken == null || !appWindowToken.isVisible()) {
10571                Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
10572                        + token);
10573                return;
10574            }
10575
10576            appWindowToken.setReplacingChildren();
10577            scheduleClearReplacingWindowIfNeeded(token, true /* replacing */);
10578        }
10579    }
10580
10581    /**
10582     * If we're replacing the window, schedule a timer to clear the replaced window
10583     * after a timeout, in case the replacing window is not coming.
10584     *
10585     * If we're not replacing the window, clear the replace window settings of the app.
10586     *
10587     * @param token Application token for the activity whose window might be replaced.
10588     * @param replacing Whether the window is being replaced or not.
10589     */
10590    public void scheduleClearReplacingWindowIfNeeded(IBinder token, boolean replacing) {
10591        AppWindowToken appWindowToken = null;
10592        synchronized (mWindowMap) {
10593            appWindowToken = findAppWindowToken(token);
10594            if (appWindowToken == null) {
10595                Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token "
10596                        + token);
10597                return;
10598            }
10599            if (replacing) {
10600                mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
10601                mH.sendMessageDelayed(
10602                        mH.obtainMessage(H.WINDOW_REPLACEMENT_TIMEOUT, appWindowToken),
10603                        WINDOW_REPLACEMENT_TIMEOUT_DURATION);
10604            } else {
10605                appWindowToken.resetReplacingWindows();
10606            }
10607        }
10608    }
10609
10610    @Override
10611    public int getDockedStackSide() {
10612        synchronized (mWindowMap) {
10613            final TaskStack dockedStack = getDefaultDisplayContentLocked()
10614                    .getDockedStackVisibleForUserLocked();
10615            return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide();
10616        }
10617    }
10618
10619    @Override
10620    public void setDockedStackResizing(boolean resizing) {
10621        synchronized (mWindowMap) {
10622            getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing);
10623            requestTraversal();
10624        }
10625    }
10626
10627    @Override
10628    public void setDockedStackDividerTouchRegion(Rect touchRegion) {
10629        synchronized (mWindowMap) {
10630            getDefaultDisplayContentLocked().getDockedDividerController()
10631                    .setTouchRegion(touchRegion);
10632            setFocusTaskRegionLocked();
10633        }
10634    }
10635
10636    @Override
10637    public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
10638        synchronized (mWindowMap) {
10639            getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer(
10640                    visible, targetStackId, alpha);
10641        }
10642    }
10643
10644    public void animateResizePinnedStack(final Rect bounds, final int animationDuration) {
10645        synchronized (mWindowMap) {
10646            final TaskStack stack = mStackIdToStack.get(PINNED_STACK_ID);
10647            if (stack == null) {
10648                Slog.w(TAG, "animateResizePinnedStack: stackId " + PINNED_STACK_ID + " not found.");
10649                return;
10650            }
10651            final Rect originalBounds = new Rect();
10652            stack.getBounds(originalBounds);
10653            UiThread.getHandler().post(new Runnable() {
10654                @Override
10655                public void run() {
10656                    mBoundsAnimationController.animateBounds(
10657                            stack, originalBounds, bounds, animationDuration);
10658                }
10659            });
10660        }
10661    }
10662
10663    public void setTaskResizeable(int taskId, int resizeMode) {
10664        synchronized (mWindowMap) {
10665            final Task task = mTaskIdToTask.get(taskId);
10666            if (task != null) {
10667                task.setResizeable(resizeMode);
10668            }
10669        }
10670    }
10671
10672    public void setForceResizableTasks(boolean forceResizableTasks) {
10673        synchronized (mWindowMap) {
10674            mForceResizableTasks = forceResizableTasks;
10675        }
10676    }
10677
10678    static int dipToPixel(int dip, DisplayMetrics displayMetrics) {
10679        return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
10680    }
10681
10682    @Override
10683    public void registerDockedStackListener(IDockedStackListener listener) {
10684        if (!checkCallingPermission(android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS,
10685                "registerDockedStackListener()")) {
10686            return;
10687        }
10688        // TODO(multi-display): The listener is registered on the default display only.
10689        getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener(
10690                listener);
10691    }
10692
10693    @Override
10694    public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
10695        try {
10696            WindowState focusedWindow = getFocusedWindow();
10697            if (focusedWindow != null && focusedWindow.mClient != null) {
10698                getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId);
10699            }
10700        } catch (RemoteException e) {
10701        }
10702    }
10703
10704    @Override
10705    public void getStableInsets(Rect outInsets) throws RemoteException {
10706        synchronized (mWindowMap) {
10707            getStableInsetsLocked(outInsets);
10708        }
10709    }
10710
10711    void getStableInsetsLocked(Rect outInsets) {
10712        final DisplayInfo di = getDefaultDisplayInfoLocked();
10713        mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
10714    }
10715
10716    private void getNonDecorInsetsLocked(Rect outInsets) {
10717        final DisplayInfo di = getDefaultDisplayInfoLocked();
10718        mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
10719    }
10720
10721    /**
10722     * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
10723     * inset areas.
10724     *
10725     * @param inOutBounds The inOutBounds to subtract the stable inset areas from.
10726     */
10727    public void subtractStableInsets(Rect inOutBounds) {
10728        synchronized (mWindowMap) {
10729            getStableInsetsLocked(mTmpRect2);
10730            final DisplayInfo di = getDefaultDisplayInfoLocked();
10731            mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
10732            mTmpRect.inset(mTmpRect2);
10733            inOutBounds.intersect(mTmpRect);
10734        }
10735    }
10736
10737    /**
10738     * Intersects the specified {@code inOutBounds} with the display frame that excludes
10739     * areas that could never be removed in Honeycomb. See
10740     * {@link WindowManagerPolicy#getNonDecorInsetsLw}.
10741     *
10742     * @param inOutBounds The inOutBounds to subtract the inset areas from.
10743     */
10744    public void subtractNonDecorInsets(Rect inOutBounds) {
10745        synchronized (mWindowMap) {
10746            getNonDecorInsetsLocked(mTmpRect2);
10747            final DisplayInfo di = getDefaultDisplayInfoLocked();
10748            mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
10749            mTmpRect.inset(mTmpRect2);
10750            inOutBounds.intersect(mTmpRect);
10751        }
10752    }
10753
10754    private MousePositionTracker mMousePositionTracker = new MousePositionTracker();
10755
10756    private static class MousePositionTracker implements PointerEventListener {
10757        private boolean mLatestEventWasMouse;
10758        private float mLatestMouseX;
10759        private float mLatestMouseY;
10760
10761        void updatePosition(float x, float y) {
10762            synchronized (this) {
10763                mLatestEventWasMouse = true;
10764                mLatestMouseX = x;
10765                mLatestMouseY = y;
10766            }
10767        }
10768
10769        @Override
10770        public void onPointerEvent(MotionEvent motionEvent) {
10771            if (motionEvent.isFromSource(InputDevice.SOURCE_MOUSE)) {
10772                updatePosition(motionEvent.getRawX(), motionEvent.getRawY());
10773            } else {
10774                synchronized (this) {
10775                    mLatestEventWasMouse = false;
10776                }
10777            }
10778        }
10779    };
10780
10781    void updatePointerIcon(IWindow client) {
10782        float mouseX, mouseY;
10783
10784        synchronized(mMousePositionTracker) {
10785            if (!mMousePositionTracker.mLatestEventWasMouse) {
10786                return;
10787            }
10788            mouseX = mMousePositionTracker.mLatestMouseX;
10789            mouseY = mMousePositionTracker.mLatestMouseY;
10790        }
10791
10792        synchronized (mWindowMap) {
10793            if (mDragState != null) {
10794                // Drag cursor overrides the app cursor.
10795                return;
10796            }
10797            WindowState callingWin = windowForClientLocked(null, client, false);
10798            if (callingWin == null) {
10799                Slog.w(TAG_WM, "Bad requesting window " + client);
10800                return;
10801            }
10802            final DisplayContent displayContent = callingWin.getDisplayContent();
10803            if (displayContent == null) {
10804                return;
10805            }
10806            WindowState windowUnderPointer =
10807                    displayContent.getTouchableWinAtPointLocked(mouseX, mouseY);
10808            if (windowUnderPointer != callingWin) {
10809                return;
10810            }
10811            try {
10812                windowUnderPointer.mClient.updatePointerIcon(
10813                        windowUnderPointer.translateToWindowX(mouseX),
10814                        windowUnderPointer.translateToWindowY(mouseY));
10815            } catch (RemoteException e) {
10816                Slog.w(TAG_WM, "unable to update pointer icon");
10817            }
10818        }
10819    }
10820
10821    void restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY) {
10822        // Mouse position tracker has not been getting updates while dragging, update it now.
10823        mMousePositionTracker.updatePosition(latestX, latestY);
10824
10825        WindowState windowUnderPointer =
10826                displayContent.getTouchableWinAtPointLocked(latestX, latestY);
10827        if (windowUnderPointer != null) {
10828            try {
10829                windowUnderPointer.mClient.updatePointerIcon(
10830                        windowUnderPointer.translateToWindowX(latestX),
10831                        windowUnderPointer.translateToWindowY(latestY));
10832            } catch (RemoteException e) {
10833                Slog.w(TAG_WM, "unable to restore pointer icon");
10834            }
10835        } else {
10836            InputManager.getInstance().setPointerIconShape(PointerIcon.STYLE_DEFAULT);
10837        }
10838    }
10839
10840    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
10841            throws RemoteException {
10842        if (!checkCallingPermission(Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS,
10843                "registerShortcutKey")) {
10844            throw new SecurityException(
10845                    "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission");
10846        }
10847        mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
10848    }
10849
10850    private final class LocalService extends WindowManagerInternal {
10851        @Override
10852        public void requestTraversalFromDisplayManager() {
10853            requestTraversal();
10854        }
10855
10856        @Override
10857        public void setMagnificationSpec(MagnificationSpec spec) {
10858            synchronized (mWindowMap) {
10859                if (mAccessibilityController != null) {
10860                    mAccessibilityController.setMagnificationSpecLocked(spec);
10861                } else {
10862                    throw new IllegalStateException("Magnification callbacks not set!");
10863                }
10864            }
10865            if (Binder.getCallingPid() != android.os.Process.myPid()) {
10866                spec.recycle();
10867            }
10868        }
10869
10870        @Override
10871        public void getMagnificationRegions(@NonNull Region outMagnified,
10872                @NonNull Region outAvailable) {
10873            synchronized (mWindowMap) {
10874                if (mAccessibilityController != null) {
10875                    mAccessibilityController.getMagnificationRegionsLocked(
10876                            outMagnified, outAvailable);
10877                } else {
10878                    throw new IllegalStateException("Magnification callbacks not set!");
10879                }
10880            }
10881        }
10882
10883        @Override
10884        public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
10885            synchronized (mWindowMap) {
10886                WindowState windowState = mWindowMap.get(windowToken);
10887                if (windowState == null) {
10888                    return null;
10889                }
10890                MagnificationSpec spec = null;
10891                if (mAccessibilityController != null) {
10892                    spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState);
10893                }
10894                if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
10895                    return null;
10896                }
10897                spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
10898                spec.scale *= windowState.mGlobalScale;
10899                return spec;
10900            }
10901        }
10902
10903        @Override
10904        public void setMagnificationCallbacks(@Nullable MagnificationCallbacks callbacks) {
10905            synchronized (mWindowMap) {
10906                if (mAccessibilityController == null) {
10907                    mAccessibilityController = new AccessibilityController(
10908                            WindowManagerService.this);
10909                }
10910                mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
10911                if (!mAccessibilityController.hasCallbacksLocked()) {
10912                    mAccessibilityController = null;
10913                }
10914            }
10915        }
10916
10917        @Override
10918        public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
10919            synchronized (mWindowMap) {
10920                if (mAccessibilityController == null) {
10921                    mAccessibilityController = new AccessibilityController(
10922                            WindowManagerService.this);
10923                }
10924                mAccessibilityController.setWindowsForAccessibilityCallback(callback);
10925                if (!mAccessibilityController.hasCallbacksLocked()) {
10926                    mAccessibilityController = null;
10927                }
10928            }
10929        }
10930
10931        @Override
10932        public void setInputFilter(IInputFilter filter) {
10933            mInputManager.setInputFilter(filter);
10934        }
10935
10936        @Override
10937        public IBinder getFocusedWindowToken() {
10938            synchronized (mWindowMap) {
10939                WindowState windowState = getFocusedWindowLocked();
10940                if (windowState != null) {
10941                    return windowState.mClient.asBinder();
10942                }
10943                return null;
10944            }
10945        }
10946
10947        @Override
10948        public boolean isKeyguardLocked() {
10949            return WindowManagerService.this.isKeyguardLocked();
10950        }
10951
10952        @Override
10953        public void showGlobalActions() {
10954            WindowManagerService.this.showGlobalActions();
10955        }
10956
10957        @Override
10958        public void getWindowFrame(IBinder token, Rect outBounds) {
10959            synchronized (mWindowMap) {
10960                WindowState windowState = mWindowMap.get(token);
10961                if (windowState != null) {
10962                    outBounds.set(windowState.mFrame);
10963                } else {
10964                    outBounds.setEmpty();
10965                }
10966            }
10967        }
10968
10969        @Override
10970        public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
10971            boolean allWindowsDrawn = false;
10972            synchronized (mWindowMap) {
10973                mWaitingForDrawnCallback = callback;
10974                final WindowList windows = getDefaultWindowListLocked();
10975                for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
10976                    final WindowState win = windows.get(winNdx);
10977                    final boolean isForceHiding = mPolicy.isForceHiding(win.mAttrs);
10978                    if (win.isVisibleLw()
10979                            && (win.mAppToken != null || isForceHiding)) {
10980                        win.mWinAnimator.mDrawState = DRAW_PENDING;
10981                        // Force add to mResizingWindows.
10982                        win.mLastContentInsets.set(-1, -1, -1, -1);
10983                        mWaitingForDrawn.add(win);
10984
10985                        // No need to wait for the windows below Keyguard.
10986                        if (isForceHiding) {
10987                            break;
10988                        }
10989                    }
10990                }
10991                mWindowPlacerLocked.requestTraversal();
10992                mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
10993                if (mWaitingForDrawn.isEmpty()) {
10994                    allWindowsDrawn = true;
10995                } else {
10996                    mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
10997                    checkDrawnWindowsLocked();
10998                }
10999            }
11000            if (allWindowsDrawn) {
11001                callback.run();
11002            }
11003        }
11004
11005        @Override
11006        public void addWindowToken(IBinder token, int type) {
11007            WindowManagerService.this.addWindowToken(token, type);
11008        }
11009
11010        @Override
11011        public void removeWindowToken(IBinder token, boolean removeWindows) {
11012            synchronized(mWindowMap) {
11013                if (removeWindows) {
11014                    WindowToken wtoken = mTokenMap.remove(token);
11015                    if (wtoken != null) {
11016                        wtoken.removeAllWindows();
11017                    }
11018                }
11019                WindowManagerService.this.removeWindowToken(token);
11020            }
11021        }
11022
11023        @Override
11024        public void registerAppTransitionListener(AppTransitionListener listener) {
11025            synchronized (mWindowMap) {
11026                mAppTransition.registerListenerLocked(listener);
11027            }
11028        }
11029
11030        @Override
11031        public int getInputMethodWindowVisibleHeight() {
11032            synchronized (mWindowMap) {
11033                return mPolicy.getInputMethodWindowVisibleHeightLw();
11034            }
11035        }
11036
11037        @Override
11038        public void saveLastInputMethodWindowForTransition() {
11039            synchronized (mWindowMap) {
11040                if (mInputMethodWindow != null) {
11041                    mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
11042                }
11043            }
11044        }
11045
11046        @Override
11047        public boolean isHardKeyboardAvailable() {
11048            synchronized (mWindowMap) {
11049                return mHardKeyboardAvailable;
11050            }
11051        }
11052
11053        @Override
11054        public void setOnHardKeyboardStatusChangeListener(
11055                OnHardKeyboardStatusChangeListener listener) {
11056            synchronized (mWindowMap) {
11057                mHardKeyboardStatusChangeListener = listener;
11058            }
11059        }
11060
11061        @Override
11062        public boolean isStackVisible(int stackId) {
11063            synchronized (mWindowMap) {
11064                return WindowManagerService.this.isStackVisibleLocked(stackId);
11065            }
11066        }
11067
11068        @Override
11069        public boolean isDockedDividerResizing() {
11070            synchronized (mWindowMap) {
11071                return getDefaultDisplayContentLocked().getDockedDividerController().isResizing();
11072            }
11073        }
11074    }
11075}
11076