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