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