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