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