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