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