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