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     boolean mAnimateWallpaperWithTarget;
    534 
    535     AppWindowToken mFocusedApp = null;
    536 
    537     PowerManagerService mPowerManager;
    538 
    539     float mWindowAnimationScale = 1.0f;
    540     float mTransitionAnimationScale = 1.0f;
    541     float mAnimatorDurationScale = 1.0f;
    542 
    543     final InputManagerService mInputManager;
    544     final DisplayManagerService mDisplayManagerService;
    545     final DisplayManager mDisplayManager;
    546 
    547     // Who is holding the screen on.
    548     Session mHoldingScreenOn;
    549     PowerManager.WakeLock mHoldingScreenWakeLock;
    550 
    551     boolean mTurnOnScreen;
    552 
    553     DragState mDragState = null;
    554 
    555     // For frozen screen animations.
    556     int mExitAnimId, mEnterAnimId;
    557 
    558     /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple
    559      * methods. */
    560     class LayoutFields {
    561         static final int SET_UPDATE_ROTATION                = 1 << 0;
    562         static final int SET_WALLPAPER_MAY_CHANGE           = 1 << 1;
    563         static final int SET_FORCE_HIDING_CHANGED           = 1 << 2;
    564         static final int SET_ORIENTATION_CHANGE_COMPLETE    = 1 << 3;
    565         static final int SET_TURN_ON_SCREEN                 = 1 << 4;
    566         static final int SET_WALLPAPER_ACTION_PENDING       = 1 << 5;
    567 
    568         boolean mWallpaperForceHidingChanged = false;
    569         boolean mWallpaperMayChange = false;
    570         boolean mOrientationChangeComplete = true;
    571         Object mLastWindowFreezeSource = null;
    572         private Session mHoldScreen = null;
    573         private boolean mObscured = false;
    574         private boolean mSyswin = false;
    575         private float mScreenBrightness = -1;
    576         private float mButtonBrightness = -1;
    577         private long mUserActivityTimeout = -1;
    578         private boolean mUpdateRotation = false;
    579         boolean mWallpaperActionPending = false;
    580 
    581         // Set to true when the display contains content to show the user.
    582         // When false, the display manager may choose to mirror or blank the display.
    583         boolean mDisplayHasContent = false;
    584 
    585         // Only set while traversing the default display based on its content.
    586         // Affects the behavior of mirroring on secondary displays.
    587         boolean mObscureApplicationContentOnSecondaryDisplays = false;
    588     }
    589     final LayoutFields mInnerFields = new LayoutFields();
    590 
    591     boolean mAnimationScheduled;
    592 
    593     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
    594      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
    595     private int mTransactionSequence;
    596 
    597     /** Only do a maximum of 6 repeated layouts. After that quit */
    598     private int mLayoutRepeatCount;
    599 
    600     final WindowAnimator mAnimator;
    601 
    602     SparseArray<Task> mTaskIdToTask = new SparseArray<Task>();
    603     SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>();
    604 
    605     private final PointerEventDispatcher mPointerEventDispatcher;
    606 
    607     final class DragInputEventReceiver extends InputEventReceiver {
    608         public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
    609             super(inputChannel, looper);
    610         }
    611 
    612         @Override
    613         public void onInputEvent(InputEvent event) {
    614             boolean handled = false;
    615             try {
    616                 if (event instanceof MotionEvent
    617                         && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
    618                         && mDragState != null) {
    619                     final MotionEvent motionEvent = (MotionEvent)event;
    620                     boolean endDrag = false;
    621                     final float newX = motionEvent.getRawX();
    622                     final float newY = motionEvent.getRawY();
    623 
    624                     switch (motionEvent.getAction()) {
    625                     case MotionEvent.ACTION_DOWN: {
    626                         if (DEBUG_DRAG) {
    627                             Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer");
    628                         }
    629                     } break;
    630 
    631                     case MotionEvent.ACTION_MOVE: {
    632                         synchronized (mWindowMap) {
    633                             // move the surface and tell the involved window(s) where we are
    634                             mDragState.notifyMoveLw(newX, newY);
    635                         }
    636                     } break;
    637 
    638                     case MotionEvent.ACTION_UP: {
    639                         if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at "
    640                                 + newX + "," + newY);
    641                         synchronized (mWindowMap) {
    642                             endDrag = mDragState.notifyDropLw(newX, newY);
    643                         }
    644                     } break;
    645 
    646                     case MotionEvent.ACTION_CANCEL: {
    647                         if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!");
    648                         endDrag = true;
    649                     } break;
    650                     }
    651 
    652                     if (endDrag) {
    653                         if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state");
    654                         // tell all the windows that the drag has ended
    655                         synchronized (mWindowMap) {
    656                             mDragState.endDragLw();
    657                         }
    658                     }
    659 
    660                     handled = true;
    661                 }
    662             } catch (Exception e) {
    663                 Slog.e(TAG, "Exception caught by drag handleMotion", e);
    664             } finally {
    665                 finishInputEvent(event, handled);
    666             }
    667         }
    668     }
    669 
    670     /**
    671      * Whether the UI is currently running in touch mode (not showing
    672      * navigational focus because the user is directly pressing the screen).
    673      */
    674     boolean mInTouchMode = true;
    675 
    676     private ViewServer mViewServer;
    677     private final ArrayList<WindowChangeListener> mWindowChangeListeners =
    678         new ArrayList<WindowChangeListener>();
    679     private boolean mWindowsChanged = false;
    680 
    681     public interface WindowChangeListener {
    682         public void windowsChanged();
    683         public void focusChanged();
    684     }
    685 
    686     final Configuration mTempConfiguration = new Configuration();
    687 
    688     // The desired scaling factor for compatible apps.
    689     float mCompatibleScreenScale;
    690 
    691     // If true, only the core apps and services are being launched because the device
    692     // is in a special boot mode, such as being encrypted or waiting for a decryption password.
    693     // For example, when this flag is true, there will be no wallpaper service.
    694     final boolean mOnlyCore;
    695 
    696     public static WindowManagerService main(final Context context,
    697             final PowerManagerService pm, final DisplayManagerService dm,
    698             final InputManagerService im, final Handler wmHandler,
    699             final boolean haveInputMethods, final boolean showBootMsgs,
    700             final boolean onlyCore) {
    701         final WindowManagerService[] holder = new WindowManagerService[1];
    702         wmHandler.runWithScissors(new Runnable() {
    703             @Override
    704             public void run() {
    705                 holder[0] = new WindowManagerService(context, pm, dm, im,
    706                         haveInputMethods, showBootMsgs, onlyCore);
    707             }
    708         }, 0);
    709         return holder[0];
    710     }
    711 
    712     private void initPolicy(Handler uiHandler) {
    713         uiHandler.runWithScissors(new Runnable() {
    714             @Override
    715             public void run() {
    716                 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
    717 
    718                 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
    719                 mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer()
    720                         * TYPE_LAYER_MULTIPLIER
    721                         + TYPE_LAYER_OFFSET;
    722             }
    723         }, 0);
    724     }
    725 
    726     private WindowManagerService(Context context, PowerManagerService pm,
    727             DisplayManagerService displayManager, InputManagerService inputManager,
    728             boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
    729         mContext = context;
    730         mHaveInputMethods = haveInputMethods;
    731         mAllowBootMessages = showBootMsgs;
    732         mOnlyCore = onlyCore;
    733         mLimitedAlphaCompositing = context.getResources().getBoolean(
    734                 com.android.internal.R.bool.config_sf_limitedAlpha);
    735         mInputManager = inputManager; // Must be before createDisplayContentLocked.
    736         mDisplayManagerService = displayManager;
    737         mHeadless = displayManager.isHeadless();
    738         mDisplaySettings = new DisplaySettings(context);
    739         mDisplaySettings.readSettingsLocked();
    740 
    741         mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG));
    742 
    743         mFxSession = new SurfaceSession();
    744         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
    745         mDisplayManager.registerDisplayListener(this, null);
    746         Display[] displays = mDisplayManager.getDisplays();
    747         for (Display display : displays) {
    748             createDisplayContentLocked(display);
    749         }
    750 
    751         mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
    752 
    753         mPowerManager = pm;
    754         mPowerManager.setPolicy(mPolicy);
    755         PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    756         mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
    757         mScreenFrozenLock.setReferenceCounted(false);
    758 
    759         mAppTransition = new AppTransition(context, mH);
    760 
    761         mActivityManager = ActivityManagerNative.getDefault();
    762         mBatteryStats = BatteryStatsService.getService();
    763         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
    764         mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null,
    765                 new AppOpsManager.OnOpChangedInternalListener() {
    766                     @Override
    767                     public void onOpChanged(int op, String packageName) {
    768                         updateAppOpsState();
    769                     }
    770                 }
    771         );
    772 
    773         // Get persisted window scale setting
    774         mWindowAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
    775                 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
    776         mTransitionAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
    777                 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
    778         setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
    779                 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale));
    780 
    781         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
    782         IntentFilter filter = new IntentFilter();
    783         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
    784         mContext.registerReceiver(mBroadcastReceiver, filter);
    785 
    786         mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
    787                 | PowerManager.ON_AFTER_RELEASE, TAG);
    788         mHoldingScreenWakeLock.setReferenceCounted(false);
    789 
    790         mAnimator = new WindowAnimator(this);
    791 
    792         initPolicy(UiThread.getHandler());
    793 
    794         // Add ourself to the Watchdog monitors.
    795         Watchdog.getInstance().addMonitor(this);
    796 
    797         SurfaceControl.openTransaction();
    798         try {
    799             createWatermarkInTransaction();
    800             mFocusedStackFrame = new FocusedStackFrame(
    801                     getDefaultDisplayContentLocked().getDisplay(), mFxSession);
    802         } finally {
    803             SurfaceControl.closeTransaction();
    804         }
    805     }
    806 
    807     public InputMonitor getInputMonitor() {
    808         return mInputMonitor;
    809     }
    810 
    811     @Override
    812     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
    813             throws RemoteException {
    814         try {
    815             return super.onTransact(code, data, reply, flags);
    816         } catch (RuntimeException e) {
    817             // The window manager only throws security exceptions, so let's
    818             // log all others.
    819             if (!(e instanceof SecurityException)) {
    820                 Slog.wtf(TAG, "Window Manager Crash", e);
    821             }
    822             throw e;
    823         }
    824     }
    825 
    826     private void placeWindowAfter(WindowState pos, WindowState window) {
    827         final WindowList windows = pos.getWindowList();
    828         final int i = windows.indexOf(pos);
    829         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
    830             TAG, "Adding window " + window + " at "
    831             + (i+1) + " of " + windows.size() + " (after " + pos + ")");
    832         windows.add(i+1, window);
    833         mWindowsChanged = true;
    834     }
    835 
    836     private void placeWindowBefore(WindowState pos, WindowState window) {
    837         final WindowList windows = pos.getWindowList();
    838         int i = windows.indexOf(pos);
    839         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
    840             TAG, "Adding window " + window + " at "
    841             + i + " of " + windows.size() + " (before " + pos + ")");
    842         if (i < 0) {
    843             Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows);
    844             i = 0;
    845         }
    846         windows.add(i, window);
    847         mWindowsChanged = true;
    848     }
    849 
    850     //This method finds out the index of a window that has the same app token as
    851     //win. used for z ordering the windows in mWindows
    852     private int findIdxBasedOnAppTokens(WindowState win) {
    853         WindowList windows = win.getWindowList();
    854         for(int j = windows.size() - 1; j >= 0; j--) {
    855             WindowState wentry = windows.get(j);
    856             if(wentry.mAppToken == win.mAppToken) {
    857                 return j;
    858             }
    859         }
    860         return -1;
    861     }
    862 
    863     /**
    864      * Return the list of Windows from the passed token on the given Display.
    865      * @param token The token with all the windows.
    866      * @param displayContent The display we are interested in.
    867      * @return List of windows from token that are on displayContent.
    868      */
    869     WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) {
    870         final WindowList windowList = new WindowList();
    871         final int count = token.windows.size();
    872         for (int i = 0; i < count; i++) {
    873             final WindowState win = token.windows.get(i);
    874             if (win.mDisplayContent == displayContent) {
    875                 windowList.add(win);
    876             }
    877         }
    878         return windowList;
    879     }
    880 
    881     /**
    882      * Recursive search through a WindowList and all of its windows' children.
    883      * @param targetWin The window to search for.
    884      * @param windows The list to search.
    885      * @return The index of win in windows or of the window that is an ancestor of win.
    886      */
    887     private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) {
    888         for (int i = windows.size() - 1; i >= 0; i--) {
    889             final WindowState w = windows.get(i);
    890             if (w == targetWin) {
    891                 return i;
    892             }
    893             if (!w.mChildWindows.isEmpty()) {
    894                 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) {
    895                     return i;
    896                 }
    897             }
    898         }
    899         return -1;
    900     }
    901 
    902     private int addAppWindowToListLocked(final WindowState win) {
    903         final IWindow client = win.mClient;
    904         final WindowToken token = win.mToken;
    905         final DisplayContent displayContent = win.mDisplayContent;
    906 
    907         final WindowList windows = win.getWindowList();
    908         final int N = windows.size();
    909         WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
    910         int tokenWindowsPos = 0;
    911         int windowListPos = tokenWindowList.size();
    912         if (!tokenWindowList.isEmpty()) {
    913             // If this application has existing windows, we
    914             // simply place the new window on top of them... but
    915             // keep the starting window on top.
    916             if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
    917                 // Base windows go behind everything else.
    918                 WindowState lowestWindow = tokenWindowList.get(0);
    919                 placeWindowBefore(lowestWindow, win);
    920                 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows);
    921             } else {
    922                 AppWindowToken atoken = win.mAppToken;
    923                 WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
    924                 if (atoken != null && lastWindow == atoken.startingWindow) {
    925                     placeWindowBefore(lastWindow, win);
    926                     tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows);
    927                 } else {
    928                     int newIdx = findIdxBasedOnAppTokens(win);
    929                     //there is a window above this one associated with the same
    930                     //apptoken note that the window could be a floating window
    931                     //that was created later or a window at the top of the list of
    932                     //windows associated with this token.
    933                     if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
    934                             "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " +
    935                             N);
    936                     windows.add(newIdx + 1, win);
    937                     if (newIdx < 0) {
    938                         // No window from token found on win's display.
    939                         tokenWindowsPos = 0;
    940                     } else {
    941                         tokenWindowsPos = indexOfWinInWindowList(
    942                                 windows.get(newIdx), token.windows) + 1;
    943                     }
    944                     mWindowsChanged = true;
    945                 }
    946             }
    947             return tokenWindowsPos;
    948         }
    949 
    950         // No windows from this token on this display
    951         if (localLOGV) Slog.v(TAG, "Figuring out where to add app window " + client.asBinder()
    952                 + " (token=" + token + ")");
    953         // Figure out where the window should go, based on the
    954         // order of applications.
    955         WindowState pos = null;
    956 
    957         final ArrayList<Task> tasks = displayContent.getTasks();
    958         int taskNdx;
    959         int tokenNdx = -1;
    960         for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
    961             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
    962             for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
    963                 final AppWindowToken t = tokens.get(tokenNdx);
    964                 if (t == token) {
    965                     --tokenNdx;
    966                     if (tokenNdx < 0) {
    967                         --taskNdx;
    968                         if (taskNdx >= 0) {
    969                             tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1;
    970                         }
    971                     }
    972                     break;
    973                 }
    974 
    975                 // We haven't reached the token yet; if this token
    976                 // is not going to the bottom and has windows on this display, we can
    977                 // use it as an anchor for when we do reach the token.
    978                 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
    979                 if (!t.sendingToBottom && tokenWindowList.size() > 0) {
    980                     pos = tokenWindowList.get(0);
    981                 }
    982             }
    983             if (tokenNdx >= 0) {
    984                 // early exit
    985                 break;
    986             }
    987         }
    988 
    989         // We now know the index into the apps.  If we found
    990         // an app window above, that gives us the position; else
    991         // we need to look some more.
    992         if (pos != null) {
    993             // Move behind any windows attached to this one.
    994             WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
    995             if (atoken != null) {
    996                 tokenWindowList =
    997                         getTokenWindowsOnDisplay(atoken, displayContent);
    998                 final int NC = tokenWindowList.size();
    999                 if (NC > 0) {
   1000                     WindowState bottom = tokenWindowList.get(0);
   1001                     if (bottom.mSubLayer < 0) {
   1002                         pos = bottom;
   1003                     }
   1004                 }
   1005             }
   1006             placeWindowBefore(pos, win);
   1007             return tokenWindowsPos;
   1008         }
   1009 
   1010         // Continue looking down until we find the first
   1011         // token that has windows on this display.
   1012         for ( ; taskNdx >= 0; --taskNdx) {
   1013             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
   1014             for ( ; tokenNdx >= 0; --tokenNdx) {
   1015                 final AppWindowToken t = tokens.get(tokenNdx);
   1016                 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
   1017                 final int NW = tokenWindowList.size();
   1018                 if (NW > 0) {
   1019                     pos = tokenWindowList.get(NW-1);
   1020                     break;
   1021                 }
   1022             }
   1023             if (tokenNdx >= 0) {
   1024                 // found
   1025                 break;
   1026             }
   1027         }
   1028 
   1029         if (pos != null) {
   1030             // Move in front of any windows attached to this
   1031             // one.
   1032             WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
   1033             if (atoken != null) {
   1034                 final int NC = atoken.windows.size();
   1035                 if (NC > 0) {
   1036                     WindowState top = atoken.windows.get(NC-1);
   1037                     if (top.mSubLayer >= 0) {
   1038                         pos = top;
   1039                     }
   1040                 }
   1041             }
   1042             placeWindowAfter(pos, win);
   1043             return tokenWindowsPos;
   1044         }
   1045 
   1046         // Just search for the start of this layer.
   1047         final int myLayer = win.mBaseLayer;
   1048         int i;
   1049         for (i = 0; i < N; i++) {
   1050             WindowState w = windows.get(i);
   1051             if (w.mBaseLayer > myLayer) {
   1052                 break;
   1053             }
   1054         }
   1055         if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
   1056                 "Based on layer: Adding window " + win + " at " + i + " of " + N);
   1057         windows.add(i, win);
   1058         mWindowsChanged = true;
   1059         return tokenWindowsPos;
   1060     }
   1061 
   1062     private void addFreeWindowToListLocked(final WindowState win) {
   1063         final WindowList windows = win.getWindowList();
   1064 
   1065         // Figure out where window should go, based on layer.
   1066         final int myLayer = win.mBaseLayer;
   1067         int i;
   1068         for (i = windows.size() - 1; i >= 0; i--) {
   1069             if (windows.get(i).mBaseLayer <= myLayer) {
   1070                 break;
   1071             }
   1072         }
   1073         i++;
   1074         if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
   1075                 "Free window: Adding window " + win + " at " + i + " of " + windows.size());
   1076         windows.add(i, win);
   1077         mWindowsChanged = true;
   1078     }
   1079 
   1080     private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) {
   1081         final WindowToken token = win.mToken;
   1082         final DisplayContent displayContent = win.mDisplayContent;
   1083         final WindowState attached = win.mAttachedWindow;
   1084 
   1085         WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
   1086 
   1087         // Figure out this window's ordering relative to the window
   1088         // it is attached to.
   1089         final int NA = tokenWindowList.size();
   1090         final int sublayer = win.mSubLayer;
   1091         int largestSublayer = Integer.MIN_VALUE;
   1092         WindowState windowWithLargestSublayer = null;
   1093         int i;
   1094         for (i = 0; i < NA; i++) {
   1095             WindowState w = tokenWindowList.get(i);
   1096             final int wSublayer = w.mSubLayer;
   1097             if (wSublayer >= largestSublayer) {
   1098                 largestSublayer = wSublayer;
   1099                 windowWithLargestSublayer = w;
   1100             }
   1101             if (sublayer < 0) {
   1102                 // For negative sublayers, we go below all windows
   1103                 // in the same sublayer.
   1104                 if (wSublayer >= sublayer) {
   1105                     if (addToToken) {
   1106                         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
   1107                         token.windows.add(i, win);
   1108                     }
   1109                     placeWindowBefore(wSublayer >= 0 ? attached : w, win);
   1110                     break;
   1111                 }
   1112             } else {
   1113                 // For positive sublayers, we go above all windows
   1114                 // in the same sublayer.
   1115                 if (wSublayer > sublayer) {
   1116                     if (addToToken) {
   1117                         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
   1118                         token.windows.add(i, win);
   1119                     }
   1120                     placeWindowBefore(w, win);
   1121                     break;
   1122                 }
   1123             }
   1124         }
   1125         if (i >= NA) {
   1126             if (addToToken) {
   1127                 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
   1128                 token.windows.add(win);
   1129             }
   1130             if (sublayer < 0) {
   1131                 placeWindowBefore(attached, win);
   1132             } else {
   1133                 placeWindowAfter(largestSublayer >= 0
   1134                                  ? windowWithLargestSublayer
   1135                                  : attached,
   1136                                  win);
   1137             }
   1138         }
   1139     }
   1140 
   1141     private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) {
   1142         if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win +
   1143                 " Callers=" + Debug.getCallers(4));
   1144         if (win.mAttachedWindow == null) {
   1145             final WindowToken token = win.mToken;
   1146             int tokenWindowsPos = 0;
   1147             if (token.appWindowToken != null) {
   1148                 tokenWindowsPos = addAppWindowToListLocked(win);
   1149             } else {
   1150                 addFreeWindowToListLocked(win);
   1151             }
   1152             if (addToToken) {
   1153                 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
   1154                 token.windows.add(tokenWindowsPos, win);
   1155             }
   1156         } else {
   1157             addAttachedWindowToListLocked(win, addToToken);
   1158         }
   1159 
   1160         if (win.mAppToken != null && addToToken) {
   1161             win.mAppToken.allAppWindows.add(win);
   1162         }
   1163     }
   1164 
   1165     static boolean canBeImeTarget(WindowState w) {
   1166         final int fl = w.mAttrs.flags
   1167                 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
   1168         if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)
   1169                 || w.mAttrs.type == TYPE_APPLICATION_STARTING) {
   1170             if (DEBUG_INPUT_METHOD) {
   1171                 Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
   1172                 if (!w.isVisibleOrAdding()) {
   1173                     Slog.i(TAG, "  mSurface=" + w.mWinAnimator.mSurfaceControl
   1174                             + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility
   1175                             + " policyVis=" + w.mPolicyVisibility
   1176                             + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
   1177                             + " attachHid=" + w.mAttachedHidden
   1178                             + " exiting=" + w.mExiting + " destroying=" + w.mDestroying);
   1179                     if (w.mAppToken != null) {
   1180                         Slog.i(TAG, "  mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
   1181                     }
   1182                 }
   1183             }
   1184             return w.isVisibleOrAdding();
   1185         }
   1186         return false;
   1187     }
   1188 
   1189     /**
   1190      * Dig through the WindowStates and find the one that the Input Method will target.
   1191      * @param willMove
   1192      * @return The index+1 in mWindows of the discovered target.
   1193      */
   1194     int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
   1195         // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
   1196         // same display. Or even when the current IME/target are not on the same screen as the next
   1197         // IME/target. For now only look for input windows on the main screen.
   1198         WindowList windows = getDefaultWindowListLocked();
   1199         WindowState w = null;
   1200         int i;
   1201         for (i = windows.size() - 1; i >= 0; --i) {
   1202             WindowState win = windows.get(i);
   1203 
   1204             if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i
   1205                     + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
   1206             if (canBeImeTarget(win)) {
   1207                 w = win;
   1208                 //Slog.i(TAG, "Putting input method here!");
   1209 
   1210                 // Yet more tricksyness!  If this window is a "starting"
   1211                 // window, we do actually want to be on top of it, but
   1212                 // it is not -really- where input will go.  So if the caller
   1213                 // is not actually looking to move the IME, look down below
   1214                 // for a real window to target...
   1215                 if (!willMove
   1216                         && w.mAttrs.type == TYPE_APPLICATION_STARTING
   1217                         && i > 0) {
   1218                     WindowState wb = windows.get(i-1);
   1219                     if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
   1220                         i--;
   1221                         w = wb;
   1222                     }
   1223                 }
   1224                 break;
   1225             }
   1226         }
   1227 
   1228         // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
   1229 
   1230         if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w);
   1231 
   1232         // Now, a special case -- if the last target's window is in the
   1233         // process of exiting, and is above the new target, keep on the
   1234         // last target to avoid flicker.  Consider for example a Dialog with
   1235         // the IME shown: when the Dialog is dismissed, we want to keep
   1236         // the IME above it until it is completely gone so it doesn't drop
   1237         // behind the dialog or its full-screen scrim.
   1238         final WindowState curTarget = mInputMethodTarget;
   1239         if (curTarget != null
   1240                 && curTarget.isDisplayedLw()
   1241                 && curTarget.isClosing()
   1242                 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
   1243             if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing");
   1244             return windows.indexOf(curTarget) + 1;
   1245         }
   1246 
   1247         if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
   1248                 + w + " willMove=" + willMove);
   1249 
   1250         if (willMove && w != null) {
   1251             AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
   1252             if (token != null) {
   1253 
   1254                 // Now some fun for dealing with window animations that
   1255                 // modify the Z order.  We need to look at all windows below
   1256                 // the current target that are in this app, finding the highest
   1257                 // visible one in layering.
   1258                 WindowState highestTarget = null;
   1259                 int highestPos = 0;
   1260                 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
   1261                     WindowList curWindows = curTarget.getWindowList();
   1262                     int pos = curWindows.indexOf(curTarget);
   1263                     while (pos >= 0) {
   1264                         WindowState win = curWindows.get(pos);
   1265                         if (win.mAppToken != token) {
   1266                             break;
   1267                         }
   1268                         if (!win.mRemoved) {
   1269                             if (highestTarget == null || win.mWinAnimator.mAnimLayer >
   1270                                     highestTarget.mWinAnimator.mAnimLayer) {
   1271                                 highestTarget = win;
   1272                                 highestPos = pos;
   1273                             }
   1274                         }
   1275                         pos--;
   1276                     }
   1277                 }
   1278 
   1279                 if (highestTarget != null) {
   1280                     if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget
   1281                             + " animating=" + highestTarget.mWinAnimator.isAnimating()
   1282                             + " layer=" + highestTarget.mWinAnimator.mAnimLayer
   1283                             + " new layer=" + w.mWinAnimator.mAnimLayer);
   1284 
   1285                     if (mAppTransition.isTransitionSet()) {
   1286                         // If we are currently setting up for an animation,
   1287                         // hold everything until we can find out what will happen.
   1288                         mInputMethodTargetWaitingAnim = true;
   1289                         mInputMethodTarget = highestTarget;
   1290                         return highestPos + 1;
   1291                     } else if (highestTarget.mWinAnimator.isAnimating() &&
   1292                             highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
   1293                         // If the window we are currently targeting is involved
   1294                         // with an animation, and it is on top of the next target
   1295                         // we will be over, then hold off on moving until
   1296                         // that is done.
   1297                         mInputMethodTargetWaitingAnim = true;
   1298                         mInputMethodTarget = highestTarget;
   1299                         return highestPos + 1;
   1300                     }
   1301                 }
   1302             }
   1303         }
   1304 
   1305         //Slog.i(TAG, "Placing input method @" + (i+1));
   1306         if (w != null) {
   1307             if (willMove) {
   1308                 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to "
   1309                         + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
   1310                 mInputMethodTarget = w;
   1311                 mInputMethodTargetWaitingAnim = false;
   1312                 if (w.mAppToken != null) {
   1313                     setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment);
   1314                 } else {
   1315                     setInputMethodAnimLayerAdjustment(0);
   1316                 }
   1317             }
   1318             return i+1;
   1319         }
   1320         if (willMove) {
   1321             if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null."
   1322                     + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
   1323             mInputMethodTarget = null;
   1324             setInputMethodAnimLayerAdjustment(0);
   1325         }
   1326         return -1;
   1327     }
   1328 
   1329     void addInputMethodWindowToListLocked(WindowState win) {
   1330         int pos = findDesiredInputMethodWindowIndexLocked(true);
   1331         if (pos >= 0) {
   1332             win.mTargetAppToken = mInputMethodTarget.mAppToken;
   1333             if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
   1334                     TAG, "Adding input method window " + win + " at " + pos);
   1335             // TODO(multidisplay): IMEs are only supported on the default display.
   1336             getDefaultWindowListLocked().add(pos, win);
   1337             mWindowsChanged = true;
   1338             moveInputMethodDialogsLocked(pos+1);
   1339             return;
   1340         }
   1341         win.mTargetAppToken = null;
   1342         addWindowToListInOrderLocked(win, true);
   1343         moveInputMethodDialogsLocked(pos);
   1344     }
   1345 
   1346     void setInputMethodAnimLayerAdjustment(int adj) {
   1347         if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj);
   1348         mInputMethodAnimLayerAdjustment = adj;
   1349         WindowState imw = mInputMethodWindow;
   1350         if (imw != null) {
   1351             imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
   1352             if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
   1353                     + " anim layer: " + imw.mWinAnimator.mAnimLayer);
   1354             int wi = imw.mChildWindows.size();
   1355             while (wi > 0) {
   1356                 wi--;
   1357                 WindowState cw = imw.mChildWindows.get(wi);
   1358                 cw.mWinAnimator.mAnimLayer = cw.mLayer + adj;
   1359                 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw
   1360                         + " anim layer: " + cw.mWinAnimator.mAnimLayer);
   1361             }
   1362         }
   1363         int di = mInputMethodDialogs.size();
   1364         while (di > 0) {
   1365             di --;
   1366             imw = mInputMethodDialogs.get(di);
   1367             imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
   1368             if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
   1369                     + " anim layer: " + imw.mWinAnimator.mAnimLayer);
   1370         }
   1371     }
   1372 
   1373     private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
   1374         WindowList windows = win.getWindowList();
   1375         int wpos = windows.indexOf(win);
   1376         if (wpos >= 0) {
   1377             if (wpos < interestingPos) interestingPos--;
   1378             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
   1379             windows.remove(wpos);
   1380             mWindowsChanged = true;
   1381             int NC = win.mChildWindows.size();
   1382             while (NC > 0) {
   1383                 NC--;
   1384                 WindowState cw = win.mChildWindows.get(NC);
   1385                 int cpos = windows.indexOf(cw);
   1386                 if (cpos >= 0) {
   1387                     if (cpos < interestingPos) interestingPos--;
   1388                     if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
   1389                             + cpos + ": " + cw);
   1390                     windows.remove(cpos);
   1391                 }
   1392             }
   1393         }
   1394         return interestingPos;
   1395     }
   1396 
   1397     private void reAddWindowToListInOrderLocked(WindowState win) {
   1398         addWindowToListInOrderLocked(win, false);
   1399         // This is a hack to get all of the child windows added as well
   1400         // at the right position.  Child windows should be rare and
   1401         // this case should be rare, so it shouldn't be that big a deal.
   1402         WindowList windows = win.getWindowList();
   1403         int wpos = windows.indexOf(win);
   1404         if (wpos >= 0) {
   1405             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win);
   1406             windows.remove(wpos);
   1407             mWindowsChanged = true;
   1408             reAddWindowLocked(wpos, win);
   1409         }
   1410     }
   1411 
   1412     void logWindowList(final WindowList windows, String prefix) {
   1413         int N = windows.size();
   1414         while (N > 0) {
   1415             N--;
   1416             Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N));
   1417         }
   1418     }
   1419 
   1420     void moveInputMethodDialogsLocked(int pos) {
   1421         ArrayList<WindowState> dialogs = mInputMethodDialogs;
   1422 
   1423         // TODO(multidisplay): IMEs are only supported on the default display.
   1424         WindowList windows = getDefaultWindowListLocked();
   1425         final int N = dialogs.size();
   1426         if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
   1427         for (int i=0; i<N; i++) {
   1428             pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
   1429         }
   1430         if (DEBUG_INPUT_METHOD) {
   1431             Slog.v(TAG, "Window list w/pos=" + pos);
   1432             logWindowList(windows, "  ");
   1433         }
   1434 
   1435         if (pos >= 0) {
   1436             final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
   1437             if (pos < windows.size()) {
   1438                 WindowState wp = windows.get(pos);
   1439                 if (wp == mInputMethodWindow) {
   1440                     pos++;
   1441                 }
   1442             }
   1443             if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
   1444             for (int i=0; i<N; i++) {
   1445                 WindowState win = dialogs.get(i);
   1446                 win.mTargetAppToken = targetAppToken;
   1447                 pos = reAddWindowLocked(pos, win);
   1448             }
   1449             if (DEBUG_INPUT_METHOD) {
   1450                 Slog.v(TAG, "Final window list:");
   1451                 logWindowList(windows, "  ");
   1452             }
   1453             return;
   1454         }
   1455         for (int i=0; i<N; i++) {
   1456             WindowState win = dialogs.get(i);
   1457             win.mTargetAppToken = null;
   1458             reAddWindowToListInOrderLocked(win);
   1459             if (DEBUG_INPUT_METHOD) {
   1460                 Slog.v(TAG, "No IM target, final list:");
   1461                 logWindowList(windows, "  ");
   1462             }
   1463         }
   1464     }
   1465 
   1466     boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
   1467         final WindowState imWin = mInputMethodWindow;
   1468         final int DN = mInputMethodDialogs.size();
   1469         if (imWin == null && DN == 0) {
   1470             return false;
   1471         }
   1472 
   1473         // TODO(multidisplay): IMEs are only supported on the default display.
   1474         WindowList windows = getDefaultWindowListLocked();
   1475 
   1476         int imPos = findDesiredInputMethodWindowIndexLocked(true);
   1477         if (imPos >= 0) {
   1478             // In this case, the input method windows are to be placed
   1479             // immediately above the window they are targeting.
   1480 
   1481             // First check to see if the input method windows are already
   1482             // located here, and contiguous.
   1483             final int N = windows.size();
   1484             WindowState firstImWin = imPos < N
   1485                     ? windows.get(imPos) : null;
   1486 
   1487             // Figure out the actual input method window that should be
   1488             // at the bottom of their stack.
   1489             WindowState baseImWin = imWin != null
   1490                     ? imWin : mInputMethodDialogs.get(0);
   1491             if (baseImWin.mChildWindows.size() > 0) {
   1492                 WindowState cw = baseImWin.mChildWindows.get(0);
   1493                 if (cw.mSubLayer < 0) baseImWin = cw;
   1494             }
   1495 
   1496             if (firstImWin == baseImWin) {
   1497                 // The windows haven't moved...  but are they still contiguous?
   1498                 // First find the top IM window.
   1499                 int pos = imPos+1;
   1500                 while (pos < N) {
   1501                     if (!(windows.get(pos)).mIsImWindow) {
   1502                         break;
   1503                     }
   1504                     pos++;
   1505                 }
   1506                 pos++;
   1507                 // Now there should be no more input method windows above.
   1508                 while (pos < N) {
   1509                     if ((windows.get(pos)).mIsImWindow) {
   1510                         break;
   1511                     }
   1512                     pos++;
   1513                 }
   1514                 if (pos >= N) {
   1515                     // Z order is good.
   1516                     // The IM target window may be changed, so update the mTargetAppToken.
   1517                     if (imWin != null) {
   1518                         imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
   1519                     }
   1520                     return false;
   1521                 }
   1522             }
   1523 
   1524             if (imWin != null) {
   1525                 if (DEBUG_INPUT_METHOD) {
   1526                     Slog.v(TAG, "Moving IM from " + imPos);
   1527                     logWindowList(windows, "  ");
   1528                 }
   1529                 imPos = tmpRemoveWindowLocked(imPos, imWin);
   1530                 if (DEBUG_INPUT_METHOD) {
   1531                     Slog.v(TAG, "List after removing with new pos " + imPos + ":");
   1532                     logWindowList(windows, "  ");
   1533                 }
   1534                 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
   1535                 reAddWindowLocked(imPos, imWin);
   1536                 if (DEBUG_INPUT_METHOD) {
   1537                     Slog.v(TAG, "List after moving IM to " + imPos + ":");
   1538                     logWindowList(windows, "  ");
   1539                 }
   1540                 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
   1541             } else {
   1542                 moveInputMethodDialogsLocked(imPos);
   1543             }
   1544 
   1545         } else {
   1546             // In this case, the input method windows go in a fixed layer,
   1547             // because they aren't currently associated with a focus window.
   1548 
   1549             if (imWin != null) {
   1550                 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos);
   1551                 tmpRemoveWindowLocked(0, imWin);
   1552                 imWin.mTargetAppToken = null;
   1553                 reAddWindowToListInOrderLocked(imWin);
   1554                 if (DEBUG_INPUT_METHOD) {
   1555                     Slog.v(TAG, "List with no IM target:");
   1556                     logWindowList(windows, "  ");
   1557                 }
   1558                 if (DN > 0) moveInputMethodDialogsLocked(-1);
   1559             } else {
   1560                 moveInputMethodDialogsLocked(-1);
   1561             }
   1562 
   1563         }
   1564 
   1565         if (needAssignLayers) {
   1566             assignLayersLocked(windows);
   1567         }
   1568 
   1569         return true;
   1570     }
   1571 
   1572     final boolean isWallpaperVisible(WindowState wallpaperTarget) {
   1573         if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
   1574                 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
   1575                 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
   1576                         ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
   1577                 + " upper=" + mUpperWallpaperTarget
   1578                 + " lower=" + mLowerWallpaperTarget);
   1579         return (wallpaperTarget != null
   1580                         && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
   1581                                 && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
   1582                 || mUpperWallpaperTarget != null
   1583                 || mLowerWallpaperTarget != null;
   1584     }
   1585 
   1586     static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
   1587     static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
   1588 
   1589     int adjustWallpaperWindowsLocked() {
   1590         mInnerFields.mWallpaperMayChange = false;
   1591         boolean targetChanged = false;
   1592 
   1593         // TODO(multidisplay): Wallpapers on main screen only.
   1594         final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo();
   1595         final int dw = displayInfo.logicalWidth;
   1596         final int dh = displayInfo.logicalHeight;
   1597 
   1598         // First find top-most window that has asked to be on top of the
   1599         // wallpaper; all wallpapers go behind it.
   1600         final WindowList windows = getDefaultWindowListLocked();
   1601         int N = windows.size();
   1602         WindowState w = null;
   1603         WindowState foundW = null;
   1604         int foundI = 0;
   1605         WindowState topCurW = null;
   1606         int topCurI = 0;
   1607         int windowDetachedI = -1;
   1608         int i = N;
   1609         while (i > 0) {
   1610             i--;
   1611             w = windows.get(i);
   1612             if ((w.mAttrs.type == TYPE_WALLPAPER)) {
   1613                 if (topCurW == null) {
   1614                     topCurW = w;
   1615                     topCurI = i;
   1616                 }
   1617                 continue;
   1618             }
   1619             topCurW = null;
   1620             if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
   1621                 // If this window's app token is hidden and not animating,
   1622                 // it is of no interest to us.
   1623                 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
   1624                     if (DEBUG_WALLPAPER) Slog.v(TAG,
   1625                             "Skipping hidden and not animating token: " + w);
   1626                     continue;
   1627                 }
   1628             }
   1629             if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
   1630                     + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
   1631             if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isOnScreen()
   1632                     && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
   1633                 if (DEBUG_WALLPAPER) Slog.v(TAG,
   1634                         "Found wallpaper target: #" + i + "=" + w);
   1635                 foundW = w;
   1636                 foundI = i;
   1637                 if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) {
   1638                     // The current wallpaper target is animating, so we'll
   1639                     // look behind it for another possible target and figure
   1640                     // out what is going on below.
   1641                     if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
   1642                             + ": token animating, looking behind.");
   1643                     continue;
   1644                 }
   1645                 break;
   1646             } else if (w == mAnimator.mWindowDetachedWallpaper) {
   1647                 windowDetachedI = i;
   1648             }
   1649         }
   1650 
   1651         if (foundW == null && windowDetachedI >= 0) {
   1652             if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
   1653                     "Found animating detached wallpaper activity: #" + i + "=" + w);
   1654             foundW = w;
   1655             foundI = windowDetachedI;
   1656         }
   1657 
   1658         if (mWallpaperTarget != foundW
   1659                 && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) {
   1660             if (DEBUG_WALLPAPER_LIGHT) {
   1661                 Slog.v(TAG, "New wallpaper target: " + foundW
   1662                         + " oldTarget: " + mWallpaperTarget);
   1663             }
   1664 
   1665             mLowerWallpaperTarget = null;
   1666             mUpperWallpaperTarget = null;
   1667 
   1668             WindowState oldW = mWallpaperTarget;
   1669             mWallpaperTarget = foundW;
   1670             targetChanged = true;
   1671 
   1672             // Now what is happening...  if the current and new targets are
   1673             // animating, then we are in our super special mode!
   1674             if (foundW != null && oldW != null) {
   1675                 boolean oldAnim = oldW.isAnimatingLw();
   1676                 boolean foundAnim = foundW.isAnimatingLw();
   1677                 if (DEBUG_WALLPAPER_LIGHT) {
   1678                     Slog.v(TAG, "New animation: " + foundAnim
   1679                             + " old animation: " + oldAnim);
   1680                 }
   1681                 if (foundAnim && oldAnim) {
   1682                     int oldI = windows.indexOf(oldW);
   1683                     if (DEBUG_WALLPAPER_LIGHT) {
   1684                         Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
   1685                     }
   1686                     if (oldI >= 0) {
   1687                         if (DEBUG_WALLPAPER_LIGHT) {
   1688                             Slog.v(TAG, "Animating wallpapers: old#" + oldI
   1689                                     + "=" + oldW + "; new#" + foundI
   1690                                     + "=" + foundW);
   1691                         }
   1692 
   1693                         // Set the new target correctly.
   1694                         if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
   1695                             if (DEBUG_WALLPAPER_LIGHT) {
   1696                                 Slog.v(TAG, "Old wallpaper still the target.");
   1697                             }
   1698                             mWallpaperTarget = oldW;
   1699                             foundW = oldW;
   1700                             foundI = oldI;
   1701                         }
   1702                         // Now set the upper and lower wallpaper targets
   1703                         // correctly, and make sure that we are positioning
   1704                         // the wallpaper below the lower.
   1705                         else if (foundI > oldI) {
   1706                             // The new target is on top of the old one.
   1707                             if (DEBUG_WALLPAPER_LIGHT) {
   1708                                 Slog.v(TAG, "Found target above old target.");
   1709                             }
   1710                             mUpperWallpaperTarget = foundW;
   1711                             mLowerWallpaperTarget = oldW;
   1712                             foundW = oldW;
   1713                             foundI = oldI;
   1714                         } else {
   1715                             // The new target is below the old one.
   1716                             if (DEBUG_WALLPAPER_LIGHT) {
   1717                                 Slog.v(TAG, "Found target below old target.");
   1718                             }
   1719                             mUpperWallpaperTarget = oldW;
   1720                             mLowerWallpaperTarget = foundW;
   1721                         }
   1722                     }
   1723                 }
   1724             }
   1725 
   1726         } else if (mLowerWallpaperTarget != null) {
   1727             // Is it time to stop animating?
   1728             if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
   1729                 if (DEBUG_WALLPAPER_LIGHT) {
   1730                     Slog.v(TAG, "No longer animating wallpaper targets!");
   1731                 }
   1732                 mLowerWallpaperTarget = null;
   1733                 mUpperWallpaperTarget = null;
   1734                 mWallpaperTarget = foundW;
   1735                 targetChanged = true;
   1736             }
   1737         }
   1738 
   1739         boolean visible = foundW != null;
   1740         if (visible) {
   1741             // The window is visible to the compositor...  but is it visible
   1742             // to the user?  That is what the wallpaper cares about.
   1743             visible = isWallpaperVisible(foundW);
   1744             if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
   1745 
   1746             // If the wallpaper target is animating, we may need to copy
   1747             // its layer adjustment.  Only do this if we are not transfering
   1748             // between two wallpaper targets.
   1749             mWallpaperAnimLayerAdjustment =
   1750                     (mLowerWallpaperTarget == null && foundW.mAppToken != null)
   1751                     ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0;
   1752 
   1753             final int maxLayer = mPolicy.getMaxWallpaperLayer()
   1754                     * TYPE_LAYER_MULTIPLIER
   1755                     + TYPE_LAYER_OFFSET;
   1756 
   1757             // Now w is the window we are supposed to be behind...  but we
   1758             // need to be sure to also be behind any of its attached windows,
   1759             // AND any starting window associated with it, AND below the
   1760             // maximum layer the policy allows for wallpapers.
   1761             while (foundI > 0) {
   1762                 WindowState wb = windows.get(foundI-1);
   1763                 if (wb.mBaseLayer < maxLayer &&
   1764                         wb.mAttachedWindow != foundW &&
   1765                         (foundW.mAttachedWindow == null ||
   1766                                 wb.mAttachedWindow != foundW.mAttachedWindow) &&
   1767                         (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
   1768                                 foundW.mToken == null || wb.mToken != foundW.mToken)) {
   1769                     // This window is not related to the previous one in any
   1770                     // interesting way, so stop here.
   1771                     break;
   1772                 }
   1773                 foundW = wb;
   1774                 foundI--;
   1775             }
   1776         } else {
   1777             if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
   1778         }
   1779 
   1780         if (foundW == null && topCurW != null) {
   1781             // There is no wallpaper target, so it goes at the bottom.
   1782             // We will assume it is the same place as last time, if known.
   1783             foundW = topCurW;
   1784             foundI = topCurI+1;
   1785         } else {
   1786             // Okay i is the position immediately above the wallpaper.  Look at
   1787             // what is below it for later.
   1788             foundW = foundI > 0 ? windows.get(foundI-1) : null;
   1789         }
   1790 
   1791         if (visible) {
   1792             if (mWallpaperTarget.mWallpaperX >= 0) {
   1793                 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
   1794                 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
   1795             }
   1796             if (mWallpaperTarget.mWallpaperY >= 0) {
   1797                 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
   1798                 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
   1799             }
   1800         }
   1801 
   1802         // Start stepping backwards from here, ensuring that our wallpaper windows
   1803         // are correctly placed.
   1804         int changed = 0;
   1805         int curTokenIndex = mWallpaperTokens.size();
   1806         while (curTokenIndex > 0) {
   1807             curTokenIndex--;
   1808             WindowToken token = mWallpaperTokens.get(curTokenIndex);
   1809             if (token.hidden == visible) {
   1810                 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
   1811                         "Wallpaper token " + token + " hidden=" + !visible);
   1812                 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
   1813                 token.hidden = !visible;
   1814                 // Need to do a layout to ensure the wallpaper now has the
   1815                 // correct size.
   1816                 getDefaultDisplayContentLocked().layoutNeeded = true;
   1817             }
   1818 
   1819             int curWallpaperIndex = token.windows.size();
   1820             while (curWallpaperIndex > 0) {
   1821                 curWallpaperIndex--;
   1822                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
   1823 
   1824                 if (visible) {
   1825                     updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
   1826                 }
   1827 
   1828                 // First, make sure the client has the current visibility
   1829                 // state.
   1830                 dispatchWallpaperVisibility(wallpaper, visible);
   1831 
   1832                 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
   1833                 if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
   1834                         + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
   1835 
   1836                 // First, if this window is at the current index, then all
   1837                 // is well.
   1838                 if (wallpaper == foundW) {
   1839                     foundI--;
   1840                     foundW = foundI > 0
   1841                             ? windows.get(foundI-1) : null;
   1842                     continue;
   1843                 }
   1844 
   1845                 // The window didn't match...  the current wallpaper window,
   1846                 // wherever it is, is in the wrong place, so make sure it is
   1847                 // not in the list.
   1848                 int oldIndex = windows.indexOf(wallpaper);
   1849                 if (oldIndex >= 0) {
   1850                     if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
   1851                             + oldIndex + ": " + wallpaper);
   1852                     windows.remove(oldIndex);
   1853                     mWindowsChanged = true;
   1854                     if (oldIndex < foundI) {
   1855                         foundI--;
   1856                     }
   1857                 }
   1858 
   1859                 // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
   1860                 // layer. For keyguard over wallpaper put the wallpaper under the keyguard.
   1861                 int insertionIndex = 0;
   1862                 if (visible && foundW != null) {
   1863                     final int type = foundW.mAttrs.type;
   1864                     if (type == TYPE_KEYGUARD || type == TYPE_KEYGUARD_SCRIM) {
   1865                         insertionIndex = windows.indexOf(foundW);
   1866                     }
   1867                 }
   1868                 if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
   1869                     Slog.v(TAG, "Moving wallpaper " + wallpaper
   1870                             + " from " + oldIndex + " to " + insertionIndex);
   1871                 }
   1872 
   1873                 windows.add(insertionIndex, wallpaper);
   1874                 mWindowsChanged = true;
   1875                 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
   1876             }
   1877         }
   1878 
   1879         /*
   1880         final TaskStack targetStack =
   1881                 mWallpaperTarget == null ? null : mWallpaperTarget.getStack();
   1882         if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 &&
   1883                 targetStack != null && !targetStack.isHomeStack()) {
   1884             // If the wallpaper target is not on the home stack then make sure that all windows
   1885             // from other non-home stacks are above the wallpaper.
   1886             for (i = foundI - 1; i >= 0; --i) {
   1887                 WindowState win = windows.get(i);
   1888                 if (!win.isVisibleLw()) {
   1889                     continue;
   1890                 }
   1891                 final TaskStack winStack = win.getStack();
   1892                 if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) {
   1893                     windows.remove(i);
   1894                     windows.add(foundI + 1, win);
   1895                 }
   1896             }
   1897         }
   1898         */
   1899 
   1900         if (targetChanged && DEBUG_WALLPAPER_LIGHT) {
   1901             Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget
   1902                     + " lower=" + mLowerWallpaperTarget + " upper="
   1903                     + mUpperWallpaperTarget);
   1904         }
   1905 
   1906         return changed;
   1907     }
   1908 
   1909     void setWallpaperAnimLayerAdjustmentLocked(int adj) {
   1910         if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
   1911                 "Setting wallpaper layer adj to " + adj);
   1912         mWallpaperAnimLayerAdjustment = adj;
   1913         int curTokenIndex = mWallpaperTokens.size();
   1914         while (curTokenIndex > 0) {
   1915             curTokenIndex--;
   1916             WindowToken token = mWallpaperTokens.get(curTokenIndex);
   1917             int curWallpaperIndex = token.windows.size();
   1918             while (curWallpaperIndex > 0) {
   1919                 curWallpaperIndex--;
   1920                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
   1921                 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj;
   1922                 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win "
   1923                         + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
   1924             }
   1925         }
   1926     }
   1927 
   1928     boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
   1929             boolean sync) {
   1930         boolean changed = false;
   1931         boolean rawChanged = false;
   1932         float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
   1933         float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
   1934         int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
   1935         int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
   1936         changed = wallpaperWin.mXOffset != offset;
   1937         if (changed) {
   1938             if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
   1939                     + wallpaperWin + " x: " + offset);
   1940             wallpaperWin.mXOffset = offset;
   1941         }
   1942         if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
   1943             wallpaperWin.mWallpaperX = wpx;
   1944             wallpaperWin.mWallpaperXStep = wpxs;
   1945             rawChanged = true;
   1946         }
   1947 
   1948         float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
   1949         float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
   1950         int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
   1951         offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
   1952         if (wallpaperWin.mYOffset != offset) {
   1953             if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
   1954                     + wallpaperWin + " y: " + offset);
   1955             changed = true;
   1956             wallpaperWin.mYOffset = offset;
   1957         }
   1958         if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
   1959             wallpaperWin.mWallpaperY = wpy;
   1960             wallpaperWin.mWallpaperYStep = wpys;
   1961             rawChanged = true;
   1962         }
   1963 
   1964         if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
   1965                     WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
   1966             try {
   1967                 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
   1968                         + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
   1969                         + " y=" + wallpaperWin.mWallpaperY);
   1970                 if (sync) {
   1971                     mWaitingOnWallpaper = wallpaperWin;
   1972                 }
   1973                 wallpaperWin.mClient.dispatchWallpaperOffsets(
   1974                         wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
   1975                         wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
   1976                 if (sync) {
   1977                     if (mWaitingOnWallpaper != null) {
   1978                         long start = SystemClock.uptimeMillis();
   1979                         if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
   1980                                 < start) {
   1981                             try {
   1982                                 if (DEBUG_WALLPAPER) Slog.v(TAG,
   1983                                         "Waiting for offset complete...");
   1984                                 mWindowMap.wait(WALLPAPER_TIMEOUT);
   1985                             } catch (InterruptedException e) {
   1986                             }
   1987                             if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
   1988                             if ((start+WALLPAPER_TIMEOUT)
   1989                                     < SystemClock.uptimeMillis()) {
   1990                                 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
   1991                                         + wallpaperWin);
   1992                                 mLastWallpaperTimeoutTime = start;
   1993                             }
   1994                         }
   1995                         mWaitingOnWallpaper = null;
   1996                     }
   1997                 }
   1998             } catch (RemoteException e) {
   1999             }
   2000         }
   2001 
   2002         return changed;
   2003     }
   2004 
   2005     void wallpaperOffsetsComplete(IBinder window) {
   2006         synchronized (mWindowMap) {
   2007             if (mWaitingOnWallpaper != null &&
   2008                     mWaitingOnWallpaper.mClient.asBinder() == window) {
   2009                 mWaitingOnWallpaper = null;
   2010                 mWindowMap.notifyAll();
   2011             }
   2012         }
   2013     }
   2014 
   2015     void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
   2016         final DisplayContent displayContent = changingTarget.mDisplayContent;
   2017         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
   2018         final int dw = displayInfo.logicalWidth;
   2019         final int dh = displayInfo.logicalHeight;
   2020 
   2021         WindowState target = mWallpaperTarget;
   2022         if (target != null) {
   2023             if (target.mWallpaperX >= 0) {
   2024                 mLastWallpaperX = target.mWallpaperX;
   2025             } else if (changingTarget.mWallpaperX >= 0) {
   2026                 mLastWallpaperX = changingTarget.mWallpaperX;
   2027             }
   2028             if (target.mWallpaperY >= 0) {
   2029                 mLastWallpaperY = target.mWallpaperY;
   2030             } else if (changingTarget.mWallpaperY >= 0) {
   2031                 mLastWallpaperY = changingTarget.mWallpaperY;
   2032             }
   2033         }
   2034 
   2035         int curTokenIndex = mWallpaperTokens.size();
   2036         while (curTokenIndex > 0) {
   2037             curTokenIndex--;
   2038             WindowToken token = mWallpaperTokens.get(curTokenIndex);
   2039             int curWallpaperIndex = token.windows.size();
   2040             while (curWallpaperIndex > 0) {
   2041                 curWallpaperIndex--;
   2042                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
   2043                 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
   2044                     WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
   2045                     winAnimator.computeShownFrameLocked();
   2046                     // No need to lay out the windows - we can just set the wallpaper position
   2047                     // directly.
   2048                     winAnimator.setWallpaperOffset(wallpaper.mShownFrame);
   2049                     // We only want to be synchronous with one wallpaper.
   2050                     sync = false;
   2051                 }
   2052             }
   2053         }
   2054     }
   2055 
   2056     /**
   2057      * Check wallpaper for visiblity change and notify window if so.
   2058      * @param wallpaper The wallpaper to test and notify.
   2059      * @param visible Current visibility.
   2060      */
   2061     void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) {
   2062         if (wallpaper.mWallpaperVisible != visible) {
   2063             wallpaper.mWallpaperVisible = visible;
   2064             try {
   2065                 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
   2066                         "Updating vis of wallpaper " + wallpaper
   2067                         + ": " + visible + " from:\n" + Debug.getCallers(4, "  "));
   2068                 wallpaper.mClient.dispatchAppVisibility(visible);
   2069             } catch (RemoteException e) {
   2070             }
   2071         }
   2072     }
   2073 
   2074     void updateWallpaperVisibilityLocked() {
   2075         final boolean visible = isWallpaperVisible(mWallpaperTarget);
   2076         final DisplayContent displayContent = mWallpaperTarget.mDisplayContent;
   2077         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
   2078         final int dw = displayInfo.logicalWidth;
   2079         final int dh = displayInfo.logicalHeight;
   2080 
   2081         int curTokenIndex = mWallpaperTokens.size();
   2082         while (curTokenIndex > 0) {
   2083             curTokenIndex--;
   2084             WindowToken token = mWallpaperTokens.get(curTokenIndex);
   2085             if (token.hidden == visible) {
   2086                 token.hidden = !visible;
   2087                 // Need to do a layout to ensure the wallpaper now has the
   2088                 // correct size.
   2089                 getDefaultDisplayContentLocked().layoutNeeded = true;
   2090             }
   2091 
   2092             int curWallpaperIndex = token.windows.size();
   2093             while (curWallpaperIndex > 0) {
   2094                 curWallpaperIndex--;
   2095                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
   2096                 if (visible) {
   2097                     updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
   2098                 }
   2099 
   2100                 dispatchWallpaperVisibility(wallpaper, visible);
   2101             }
   2102         }
   2103     }
   2104 
   2105     public int addWindow(Session session, IWindow client, int seq,
   2106             WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
   2107             Rect outContentInsets, InputChannel outInputChannel) {
   2108         int[] appOp = new int[1];
   2109         int res = mPolicy.checkAddPermission(attrs, appOp);
   2110         if (res != WindowManagerGlobal.ADD_OKAY) {
   2111             return res;
   2112         }
   2113 
   2114         boolean reportNewConfig = false;
   2115         WindowState attachedWindow = null;
   2116         WindowState win = null;
   2117         long origId;
   2118         final int type = attrs.type;
   2119 
   2120         synchronized(mWindowMap) {
   2121             if (!mDisplayReady) {
   2122                 throw new IllegalStateException("Display has not been initialialized");
   2123             }
   2124 
   2125             final DisplayContent displayContent = getDisplayContentLocked(displayId);
   2126             if (displayContent == null) {
   2127                 Slog.w(TAG, "Attempted to add window to a display that does not exist: "
   2128                         + displayId + ".  Aborting.");
   2129                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
   2130             }
   2131             if (!displayContent.hasAccess(session.mUid)) {
   2132                 Slog.w(TAG, "Attempted to add window to a display for which the application "
   2133                         + "does not have access: " + displayId + ".  Aborting.");
   2134                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
   2135             }
   2136 
   2137             if (mWindowMap.containsKey(client.asBinder())) {
   2138                 Slog.w(TAG, "Window " + client + " is already added");
   2139                 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
   2140             }
   2141 
   2142             if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
   2143                 attachedWindow = windowForClientLocked(null, attrs.token, false);
   2144                 if (attachedWindow == null) {
   2145                     Slog.w(TAG, "Attempted to add window with token that is not a window: "
   2146                           + attrs.token + ".  Aborting.");
   2147                     return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
   2148                 }
   2149                 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
   2150                         && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
   2151                     Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
   2152                             + attrs.token + ".  Aborting.");
   2153                     return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
   2154                 }
   2155             }
   2156 
   2157             if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
   2158                 Slog.w(TAG, "Attempted to add private presentation window to a non-private display.  Aborting.");
   2159                 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
   2160             }
   2161 
   2162             boolean addToken = false;
   2163             WindowToken token = mTokenMap.get(attrs.token);
   2164             if (token == null) {
   2165                 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
   2166                     Slog.w(TAG, "Attempted to add application window with unknown token "
   2167                           + attrs.token + ".  Aborting.");
   2168                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2169                 }
   2170                 if (type == TYPE_INPUT_METHOD) {
   2171                     Slog.w(TAG, "Attempted to add input method window with unknown token "
   2172                           + attrs.token + ".  Aborting.");
   2173                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2174                 }
   2175                 if (type == TYPE_WALLPAPER) {
   2176                     Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
   2177                           + attrs.token + ".  Aborting.");
   2178                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2179                 }
   2180                 if (type == TYPE_DREAM) {
   2181                     Slog.w(TAG, "Attempted to add Dream window with unknown token "
   2182                           + attrs.token + ".  Aborting.");
   2183                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2184                 }
   2185                 token = new WindowToken(this, attrs.token, -1, false);
   2186                 addToken = true;
   2187             } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
   2188                 AppWindowToken atoken = token.appWindowToken;
   2189                 if (atoken == null) {
   2190                     Slog.w(TAG, "Attempted to add window with non-application token "
   2191                           + token + ".  Aborting.");
   2192                     return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
   2193                 } else if (atoken.removed) {
   2194                     Slog.w(TAG, "Attempted to add window with exiting application token "
   2195                           + token + ".  Aborting.");
   2196                     return WindowManagerGlobal.ADD_APP_EXITING;
   2197                 }
   2198                 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
   2199                     // No need for this guy!
   2200                     if (localLOGV) Slog.v(
   2201                             TAG, "**** NO NEED TO START: " + attrs.getTitle());
   2202                     return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
   2203                 }
   2204             } else if (type == TYPE_INPUT_METHOD) {
   2205                 if (token.windowType != TYPE_INPUT_METHOD) {
   2206                     Slog.w(TAG, "Attempted to add input method window with bad token "
   2207                             + attrs.token + ".  Aborting.");
   2208                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2209                 }
   2210             } else if (type == TYPE_WALLPAPER) {
   2211                 if (token.windowType != TYPE_WALLPAPER) {
   2212                     Slog.w(TAG, "Attempted to add wallpaper window with bad token "
   2213                             + attrs.token + ".  Aborting.");
   2214                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2215                 }
   2216             } else if (type == TYPE_DREAM) {
   2217                 if (token.windowType != TYPE_DREAM) {
   2218                     Slog.w(TAG, "Attempted to add Dream window with bad token "
   2219                             + attrs.token + ".  Aborting.");
   2220                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2221                 }
   2222             }
   2223 
   2224             win = new WindowState(this, session, client, token,
   2225                     attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
   2226             if (win.mDeathRecipient == null) {
   2227                 // Client has apparently died, so there is no reason to
   2228                 // continue.
   2229                 Slog.w(TAG, "Adding window client " + client.asBinder()
   2230                         + " that is dead, aborting.");
   2231                 return WindowManagerGlobal.ADD_APP_EXITING;
   2232             }
   2233 
   2234             mPolicy.adjustWindowParamsLw(win.mAttrs);
   2235             win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
   2236 
   2237             res = mPolicy.prepareAddWindowLw(win, attrs);
   2238             if (res != WindowManagerGlobal.ADD_OKAY) {
   2239                 return res;
   2240             }
   2241 
   2242             if (outInputChannel != null && (attrs.inputFeatures
   2243                     & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
   2244                 String name = win.makeInputChannelName();
   2245                 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
   2246                 win.setInputChannel(inputChannels[0]);
   2247                 inputChannels[1].transferTo(outInputChannel);
   2248 
   2249                 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
   2250             }
   2251 
   2252             // From now on, no exceptions or errors allowed!
   2253 
   2254             res = WindowManagerGlobal.ADD_OKAY;
   2255 
   2256             origId = Binder.clearCallingIdentity();
   2257 
   2258             if (addToken) {
   2259                 mTokenMap.put(attrs.token, token);
   2260             }
   2261             win.attach();
   2262             mWindowMap.put(client.asBinder(), win);
   2263             if (win.mAppOp != AppOpsManager.OP_NONE) {
   2264                 if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage())
   2265                         != AppOpsManager.MODE_ALLOWED) {
   2266                     win.setAppOpVisibilityLw(false);
   2267                 }
   2268             }
   2269 
   2270             if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
   2271                 token.appWindowToken.startingWindow = win;
   2272                 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken
   2273                         + " startingWindow=" + win);
   2274                 Message m = mH.obtainMessage(H.REMOVE_STARTING_TIMEOUT, token.appWindowToken);
   2275                 mH.sendMessageDelayed(m, STARTING_WINDOW_TIMEOUT_DURATION);
   2276             }
   2277 
   2278             boolean imMayMove = true;
   2279 
   2280             if (type == TYPE_INPUT_METHOD) {
   2281                 win.mGivenInsetsPending = true;
   2282                 mInputMethodWindow = win;
   2283                 addInputMethodWindowToListLocked(win);
   2284                 imMayMove = false;
   2285             } else if (type == TYPE_INPUT_METHOD_DIALOG) {
   2286                 mInputMethodDialogs.add(win);
   2287                 addWindowToListInOrderLocked(win, true);
   2288                 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
   2289                 imMayMove = false;
   2290             } else {
   2291                 addWindowToListInOrderLocked(win, true);
   2292                 if (type == TYPE_WALLPAPER) {
   2293                     mLastWallpaperTimeoutTime = 0;
   2294                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
   2295                 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
   2296                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
   2297                 } else if (mWallpaperTarget != null
   2298                         && mWallpaperTarget.mLayer >= win.mBaseLayer) {
   2299                     // If there is currently a wallpaper being shown, and
   2300                     // the base layer of the new window is below the current
   2301                     // layer of the target window, then adjust the wallpaper.
   2302                     // This is to avoid a new window being placed between the
   2303                     // wallpaper and its target.
   2304                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
   2305                 }
   2306             }
   2307 
   2308             win.mWinAnimator.mEnterAnimationPending = true;
   2309 
   2310             if (displayContent.isDefaultDisplay) {
   2311                 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
   2312             } else {
   2313                 outContentInsets.setEmpty();
   2314             }
   2315 
   2316             if (mInTouchMode) {
   2317                 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
   2318             }
   2319             if (win.mAppToken == null || !win.mAppToken.clientHidden) {
   2320                 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
   2321             }
   2322 
   2323             mInputMonitor.setUpdateInputWindowsNeededLw();
   2324 
   2325             boolean focusChanged = false;
   2326             if (win.canReceiveKeys()) {
   2327                 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
   2328                         false /*updateInputWindows*/);
   2329                 if (focusChanged) {
   2330                     imMayMove = false;
   2331                 }
   2332             }
   2333 
   2334             if (imMayMove) {
   2335                 moveInputMethodWindowsIfNeededLocked(false);
   2336             }
   2337 
   2338             assignLayersLocked(displayContent.getWindowList());
   2339             // Don't do layout here, the window must call
   2340             // relayout to be displayed, so we'll do it there.
   2341 
   2342             if (focusChanged) {
   2343                 finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/);
   2344             }
   2345             mInputMonitor.updateInputWindowsLw(false /*force*/);
   2346 
   2347             if (localLOGV) Slog.v(
   2348                 TAG, "New client " + client.asBinder()
   2349                 + ": window=" + win);
   2350 
   2351             if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
   2352                 reportNewConfig = true;
   2353             }
   2354         }
   2355 
   2356         if (reportNewConfig) {
   2357             sendNewConfiguration();
   2358         }
   2359 
   2360         Binder.restoreCallingIdentity(origId);
   2361 
   2362         return res;
   2363     }
   2364 
   2365     public void removeWindow(Session session, IWindow client) {
   2366         synchronized(mWindowMap) {
   2367             WindowState win = windowForClientLocked(session, client, false);
   2368             if (win == null) {
   2369                 return;
   2370             }
   2371             removeWindowLocked(session, win);
   2372         }
   2373     }
   2374 
   2375     public void removeWindowLocked(Session session, WindowState win) {
   2376         if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
   2377             if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win);
   2378             removeStartingWindowTimeout(win.mAppToken);
   2379         }
   2380 
   2381         if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v(
   2382                 TAG, "Remove " + win + " client="
   2383                 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder()))
   2384                 + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers="
   2385                 + Debug.getCallers(4));
   2386 
   2387         final long origId = Binder.clearCallingIdentity();
   2388 
   2389         win.disposeInputChannel();
   2390 
   2391         if (DEBUG_APP_TRANSITIONS) Slog.v(
   2392                 TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl
   2393                 + " mExiting=" + win.mExiting
   2394                 + " isAnimating=" + win.mWinAnimator.isAnimating()
   2395                 + " app-animation="
   2396                 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
   2397                 + " inPendingTransaction="
   2398                 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
   2399                 + " mDisplayFrozen=" + mDisplayFrozen);
   2400         // Visibility of the removed window. Will be used later to update orientation later on.
   2401         boolean wasVisible = false;
   2402         // First, see if we need to run an animation.  If we do, we have
   2403         // to hold off on removing the window until the animation is done.
   2404         // If the display is frozen, just remove immediately, since the
   2405         // animation wouldn't be seen.
   2406         if (win.mHasSurface && okToDisplay()) {
   2407             // If we are not currently running the exit animation, we
   2408             // need to see about starting one.
   2409             wasVisible = win.isWinVisibleLw();
   2410             if (wasVisible) {
   2411 
   2412                 int transit = WindowManagerPolicy.TRANSIT_EXIT;
   2413                 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
   2414                     transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
   2415                 }
   2416                 // Try starting an animation.
   2417                 if (win.mWinAnimator.applyAnimationLocked(transit, false)) {
   2418                     win.mExiting = true;
   2419                 }
   2420                 //TODO (multidisplay): Magnification is supported only for the default display.
   2421                 if (mDisplayMagnifier != null
   2422                         && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
   2423                     mDisplayMagnifier.onWindowTransitionLocked(win, transit);
   2424                 }
   2425             }
   2426             if (win.mExiting || win.mWinAnimator.isAnimating()) {
   2427                 // The exit animation is running... wait for it!
   2428                 //Slog.i(TAG, "*** Running exit animation...");
   2429                 win.mExiting = true;
   2430                 win.mRemoveOnExit = true;
   2431                 win.mDisplayContent.layoutNeeded = true;
   2432                 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
   2433                         false /*updateInputWindows*/);
   2434                 performLayoutAndPlaceSurfacesLocked();
   2435                 if (win.mAppToken != null) {
   2436                     win.mAppToken.updateReportedVisibilityLocked();
   2437                 }
   2438                 //dump();
   2439                 Binder.restoreCallingIdentity(origId);
   2440                 return;
   2441             }
   2442         }
   2443 
   2444         removeWindowInnerLocked(session, win);
   2445         // Removing a visible window will effect the computed orientation
   2446         // So just update orientation if needed.
   2447         if (wasVisible && updateOrientationFromAppTokensLocked(false)) {
   2448             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
   2449         }
   2450         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
   2451         Binder.restoreCallingIdentity(origId);
   2452     }
   2453 
   2454     private void removeWindowInnerLocked(Session session, WindowState win) {
   2455         if (win.mRemoved) {
   2456             // Nothing to do.
   2457             return;
   2458         }
   2459 
   2460         for (int i=win.mChildWindows.size()-1; i>=0; i--) {
   2461             WindowState cwin = win.mChildWindows.get(i);
   2462             Slog.w(TAG, "Force-removing child win " + cwin + " from container "
   2463                     + win);
   2464             removeWindowInnerLocked(cwin.mSession, cwin);
   2465         }
   2466 
   2467         win.mRemoved = true;
   2468 
   2469         if (mInputMethodTarget == win) {
   2470             moveInputMethodWindowsIfNeededLocked(false);
   2471         }
   2472 
   2473         if (false) {
   2474             RuntimeException e = new RuntimeException("here");
   2475             e.fillInStackTrace();
   2476             Slog.w(TAG, "Removing window " + win, e);
   2477         }
   2478 
   2479         mPolicy.removeWindowLw(win);
   2480         win.removeLocked();
   2481 
   2482         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win);
   2483         mWindowMap.remove(win.mClient.asBinder());
   2484         if (win.mAppOp != AppOpsManager.OP_NONE) {
   2485             mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
   2486         }
   2487 
   2488         final WindowList windows = win.getWindowList();
   2489         windows.remove(win);
   2490         mPendingRemove.remove(win);
   2491         mResizingWindows.remove(win);
   2492         mWindowsChanged = true;
   2493         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
   2494 
   2495         if (mInputMethodWindow == win) {
   2496             mInputMethodWindow = null;
   2497         } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
   2498             mInputMethodDialogs.remove(win);
   2499         }
   2500 
   2501         final WindowToken token = win.mToken;
   2502         final AppWindowToken atoken = win.mAppToken;
   2503         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token);
   2504         token.windows.remove(win);
   2505         if (atoken != null) {
   2506             atoken.allAppWindows.remove(win);
   2507         }
   2508         if (localLOGV) Slog.v(
   2509                 TAG, "**** Removing window " + win + ": count="
   2510                 + token.windows.size());
   2511         if (token.windows.size() == 0) {
   2512             if (!token.explicit) {
   2513                 mTokenMap.remove(token.token);
   2514             } else if (atoken != null) {
   2515                 atoken.firstWindowDrawn = false;
   2516             }
   2517         }
   2518 
   2519         if (atoken != null) {
   2520             if (atoken.startingWindow == win) {
   2521                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling startingWindow " + win);
   2522                 removeStartingWindowTimeout(atoken);
   2523                 atoken.startingWindow = null;
   2524             } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
   2525                 // If this is the last window and we had requested a starting
   2526                 // transition window, well there is no point now.
   2527                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling last startingWindow");
   2528                 atoken.startingData = null;
   2529             } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
   2530                 // If this is the last window except for a starting transition
   2531                 // window, we need to get rid of the starting transition.
   2532                 scheduleRemoveStartingWindow(atoken);
   2533             }
   2534         }
   2535 
   2536         if (win.mAttrs.type == TYPE_WALLPAPER) {
   2537             mLastWallpaperTimeoutTime = 0;
   2538             getDefaultDisplayContentLocked().pendingLayoutChanges |=
   2539                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
   2540         } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
   2541             getDefaultDisplayContentLocked().pendingLayoutChanges |=
   2542                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
   2543         }
   2544 
   2545         if (!mInLayout) {
   2546             assignLayersLocked(windows);
   2547             win.mDisplayContent.layoutNeeded = true;
   2548             performLayoutAndPlaceSurfacesLocked();
   2549             if (win.mAppToken != null) {
   2550                 win.mAppToken.updateReportedVisibilityLocked();
   2551             }
   2552         }
   2553 
   2554         mInputMonitor.updateInputWindowsLw(true /*force*/);
   2555     }
   2556 
   2557     public void updateAppOpsState() {
   2558         synchronized(mWindowMap) {
   2559             final int numDisplays = mDisplayContents.size();
   2560             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   2561                 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
   2562                 final int numWindows = windows.size();
   2563                 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
   2564                     final WindowState win = windows.get(winNdx);
   2565                     if (win.mAppOp != AppOpsManager.OP_NONE) {
   2566                         final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
   2567                                 win.getOwningPackage());
   2568                         win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED);
   2569                     }
   2570                 }
   2571             }
   2572         }
   2573     }
   2574 
   2575     static void logSurface(WindowState w, String msg, RuntimeException where) {
   2576         String str = "  SURFACE " + msg + ": " + w;
   2577         if (where != null) {
   2578             Slog.i(TAG, str, where);
   2579         } else {
   2580             Slog.i(TAG, str);
   2581         }
   2582     }
   2583 
   2584     static void logSurface(SurfaceControl s, String title, String msg, RuntimeException where) {
   2585         String str = "  SURFACE " + s + ": " + msg + " / " + title;
   2586         if (where != null) {
   2587             Slog.i(TAG, str, where);
   2588         } else {
   2589             Slog.i(TAG, str);
   2590         }
   2591     }
   2592 
   2593     void setTransparentRegionWindow(Session session, IWindow client, Region region) {
   2594         long origId = Binder.clearCallingIdentity();
   2595         try {
   2596             synchronized (mWindowMap) {
   2597                 WindowState w = windowForClientLocked(session, client, false);
   2598                 if ((w != null) && w.mHasSurface) {
   2599                     w.mWinAnimator.setTransparentRegionHintLocked(region);
   2600                 }
   2601             }
   2602         } finally {
   2603             Binder.restoreCallingIdentity(origId);
   2604         }
   2605     }
   2606 
   2607     void setInsetsWindow(Session session, IWindow client,
   2608             int touchableInsets, Rect contentInsets,
   2609             Rect visibleInsets, Region touchableRegion) {
   2610         long origId = Binder.clearCallingIdentity();
   2611         try {
   2612             synchronized (mWindowMap) {
   2613                 WindowState w = windowForClientLocked(session, client, false);
   2614                 if (w != null) {
   2615                     w.mGivenInsetsPending = false;
   2616                     w.mGivenContentInsets.set(contentInsets);
   2617                     w.mGivenVisibleInsets.set(visibleInsets);
   2618                     w.mGivenTouchableRegion.set(touchableRegion);
   2619                     w.mTouchableInsets = touchableInsets;
   2620                     if (w.mGlobalScale != 1) {
   2621                         w.mGivenContentInsets.scale(w.mGlobalScale);
   2622                         w.mGivenVisibleInsets.scale(w.mGlobalScale);
   2623                         w.mGivenTouchableRegion.scale(w.mGlobalScale);
   2624                     }
   2625                     w.mDisplayContent.layoutNeeded = true;
   2626                     performLayoutAndPlaceSurfacesLocked();
   2627                 }
   2628             }
   2629         } finally {
   2630             Binder.restoreCallingIdentity(origId);
   2631         }
   2632     }
   2633 
   2634     public void getWindowDisplayFrame(Session session, IWindow client,
   2635             Rect outDisplayFrame) {
   2636         synchronized(mWindowMap) {
   2637             WindowState win = windowForClientLocked(session, client, false);
   2638             if (win == null) {
   2639                 outDisplayFrame.setEmpty();
   2640                 return;
   2641             }
   2642             outDisplayFrame.set(win.mDisplayFrame);
   2643         }
   2644     }
   2645 
   2646     public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
   2647             float xStep, float yStep) {
   2648         if (window.mWallpaperX != x || window.mWallpaperY != y)  {
   2649             window.mWallpaperX = x;
   2650             window.mWallpaperY = y;
   2651             window.mWallpaperXStep = xStep;
   2652             window.mWallpaperYStep = yStep;
   2653             updateWallpaperOffsetLocked(window, true);
   2654         }
   2655     }
   2656 
   2657     void wallpaperCommandComplete(IBinder window, Bundle result) {
   2658         synchronized (mWindowMap) {
   2659             if (mWaitingOnWallpaper != null &&
   2660                     mWaitingOnWallpaper.mClient.asBinder() == window) {
   2661                 mWaitingOnWallpaper = null;
   2662                 mWindowMap.notifyAll();
   2663             }
   2664         }
   2665     }
   2666 
   2667     public Bundle sendWindowWallpaperCommandLocked(WindowState window,
   2668             String action, int x, int y, int z, Bundle extras, boolean sync) {
   2669         if (window == mWallpaperTarget || window == mLowerWallpaperTarget
   2670                 || window == mUpperWallpaperTarget) {
   2671             boolean doWait = sync;
   2672             int curTokenIndex = mWallpaperTokens.size();
   2673             while (curTokenIndex > 0) {
   2674                 curTokenIndex--;
   2675                 WindowToken token = mWallpaperTokens.get(curTokenIndex);
   2676                 int curWallpaperIndex = token.windows.size();
   2677                 while (curWallpaperIndex > 0) {
   2678                     curWallpaperIndex--;
   2679                     WindowState wallpaper = token.windows.get(curWallpaperIndex);
   2680                     try {
   2681                         wallpaper.mClient.dispatchWallpaperCommand(action,
   2682                                 x, y, z, extras, sync);
   2683                         // We only want to be synchronous with one wallpaper.
   2684                         sync = false;
   2685                     } catch (RemoteException e) {
   2686                     }
   2687                 }
   2688             }
   2689 
   2690             if (doWait) {
   2691                 // XXX Need to wait for result.
   2692             }
   2693         }
   2694 
   2695         return null;
   2696     }
   2697 
   2698     public void setUniverseTransformLocked(WindowState window, float alpha,
   2699             float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) {
   2700         Transformation transform = window.mWinAnimator.mUniverseTransform;
   2701         transform.setAlpha(alpha);
   2702         Matrix matrix = transform.getMatrix();
   2703         matrix.getValues(mTmpFloats);
   2704         mTmpFloats[Matrix.MTRANS_X] = offx;
   2705         mTmpFloats[Matrix.MTRANS_Y] = offy;
   2706         mTmpFloats[Matrix.MSCALE_X] = dsdx;
   2707         mTmpFloats[Matrix.MSKEW_Y] = dtdx;
   2708         mTmpFloats[Matrix.MSKEW_X] = dsdy;
   2709         mTmpFloats[Matrix.MSCALE_Y] = dtdy;
   2710         matrix.setValues(mTmpFloats);
   2711         final DisplayInfo displayInfo = window.mDisplayContent.getDisplayInfo();
   2712         final RectF dispRect = new RectF(0, 0,
   2713                 displayInfo.logicalWidth, displayInfo.logicalHeight);
   2714         matrix.mapRect(dispRect);
   2715         window.mGivenTouchableRegion.set(0, 0,
   2716                 displayInfo.logicalWidth, displayInfo.logicalHeight);
   2717         window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top,
   2718                 (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE);
   2719         window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
   2720         window.mDisplayContent.layoutNeeded = true;
   2721         performLayoutAndPlaceSurfacesLocked();
   2722     }
   2723 
   2724     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle, boolean immediate) {
   2725         synchronized (mWindowMap) {
   2726             if (mDisplayMagnifier != null) {
   2727                 WindowState window = mWindowMap.get(token);
   2728                 //TODO (multidisplay): Magnification is supported only for the default display.
   2729                 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
   2730                     mDisplayMagnifier.onRectangleOnScreenRequestedLocked(rectangle, immediate);
   2731                 }
   2732             }
   2733         }
   2734     }
   2735 
   2736     public IWindowId getWindowId(IBinder token) {
   2737         synchronized (mWindowMap) {
   2738             WindowState window = mWindowMap.get(token);
   2739             return window != null ? window.mWindowId : null;
   2740         }
   2741     }
   2742 
   2743     public int relayoutWindow(Session session, IWindow client, int seq,
   2744             WindowManager.LayoutParams attrs, int requestedWidth,
   2745             int requestedHeight, int viewVisibility, int flags,
   2746             Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
   2747             Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
   2748         boolean toBeDisplayed = false;
   2749         boolean inTouchMode;
   2750         boolean configChanged;
   2751         boolean surfaceChanged = false;
   2752         boolean animating;
   2753 
   2754         // if they don't have this permission, mask out the status bar bits
   2755         int systemUiVisibility = 0;
   2756         if (attrs != null) {
   2757             systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility);
   2758             if ((systemUiVisibility & StatusBarManager.DISABLE_MASK) != 0) {
   2759                 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
   2760                         != PackageManager.PERMISSION_GRANTED) {
   2761                     systemUiVisibility &= ~StatusBarManager.DISABLE_MASK;
   2762                 }
   2763             }
   2764         }
   2765         long origId = Binder.clearCallingIdentity();
   2766 
   2767         synchronized(mWindowMap) {
   2768             WindowState win = windowForClientLocked(session, client, false);
   2769             if (win == null) {
   2770                 return 0;
   2771             }
   2772             WindowStateAnimator winAnimator = win.mWinAnimator;
   2773             if (win.mRequestedWidth != requestedWidth
   2774                     || win.mRequestedHeight != requestedHeight) {
   2775                 win.mLayoutNeeded = true;
   2776                 win.mRequestedWidth = requestedWidth;
   2777                 win.mRequestedHeight = requestedHeight;
   2778             }
   2779             if (attrs != null && seq == win.mSeq) {
   2780                 win.mSystemUiVisibility = systemUiVisibility;
   2781             }
   2782 
   2783             if (attrs != null) {
   2784                 mPolicy.adjustWindowParamsLw(attrs);
   2785             }
   2786 
   2787             winAnimator.mSurfaceDestroyDeferred =
   2788                     (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
   2789 
   2790             int attrChanges = 0;
   2791             int flagChanges = 0;
   2792             if (attrs != null) {
   2793                 if (win.mAttrs.type != attrs.type) {
   2794                     throw new IllegalArgumentException(
   2795                             "Window type can not be changed after the window is added.");
   2796                 }
   2797                 flagChanges = win.mAttrs.flags ^= attrs.flags;
   2798                 attrChanges = win.mAttrs.copyFrom(attrs);
   2799                 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
   2800                         | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
   2801                     win.mLayoutNeeded = true;
   2802                 }
   2803             }
   2804 
   2805             if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
   2806                     + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
   2807 
   2808             win.mEnforceSizeCompat =
   2809                     (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
   2810 
   2811             if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
   2812                 winAnimator.mAlpha = attrs.alpha;
   2813             }
   2814 
   2815             final boolean scaledWindow =
   2816                 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
   2817 
   2818             if (scaledWindow) {
   2819                 // requested{Width|Height} Surface's physical size
   2820                 // attrs.{width|height} Size on screen
   2821                 win.mHScale = (attrs.width  != requestedWidth)  ?
   2822                         (attrs.width  / (float)requestedWidth) : 1.0f;
   2823                 win.mVScale = (attrs.height != requestedHeight) ?
   2824                         (attrs.height / (float)requestedHeight) : 1.0f;
   2825             } else {
   2826                 win.mHScale = win.mVScale = 1;
   2827             }
   2828 
   2829             boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
   2830 
   2831             final boolean isDefaultDisplay = win.isDefaultDisplay();
   2832             boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
   2833                     || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
   2834                     || (!win.mRelayoutCalled));
   2835 
   2836             boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
   2837                     && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
   2838             wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
   2839 
   2840             win.mRelayoutCalled = true;
   2841             final int oldVisibility = win.mViewVisibility;
   2842             win.mViewVisibility = viewVisibility;
   2843             if (DEBUG_SCREEN_ON) {
   2844                 RuntimeException stack = new RuntimeException();
   2845                 stack.fillInStackTrace();
   2846                 Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility
   2847                         + " newVis=" + viewVisibility, stack);
   2848             }
   2849             if (viewVisibility == View.VISIBLE &&
   2850                     (win.mAppToken == null || !win.mAppToken.clientHidden)) {
   2851                 toBeDisplayed = !win.isVisibleLw();
   2852                 if (win.mExiting) {
   2853                     winAnimator.cancelExitAnimationForNextAnimationLocked();
   2854                     win.mExiting = false;
   2855                 }
   2856                 if (win.mDestroying) {
   2857                     win.mDestroying = false;
   2858                     mDestroySurface.remove(win);
   2859                 }
   2860                 if (oldVisibility == View.GONE) {
   2861                     winAnimator.mEnterAnimationPending = true;
   2862                 }
   2863                 if (toBeDisplayed) {
   2864                     if (win.isDrawnLw() && okToDisplay()) {
   2865                         winAnimator.applyEnterAnimationLocked();
   2866                     }
   2867                     if ((win.mAttrs.flags
   2868                             & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
   2869                         if (DEBUG_VISIBILITY) Slog.v(TAG,
   2870                                 "Relayout window turning screen on: " + win);
   2871                         win.mTurnOnScreen = true;
   2872                     }
   2873                     if (win.isConfigChanged()) {
   2874                         if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win
   2875                                 + " visible with new config: " + mCurConfiguration);
   2876                         outConfig.setTo(mCurConfiguration);
   2877                     }
   2878                 }
   2879                 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
   2880                     // To change the format, we need to re-build the surface.
   2881                     winAnimator.destroySurfaceLocked();
   2882                     toBeDisplayed = true;
   2883                     surfaceChanged = true;
   2884                 }
   2885                 try {
   2886                     if (!win.mHasSurface) {
   2887                         surfaceChanged = true;
   2888                     }
   2889                     SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
   2890                     if (surfaceControl != null) {
   2891                         outSurface.copyFrom(surfaceControl);
   2892                         if (SHOW_TRANSACTIONS) Slog.i(TAG,
   2893                                 "  OUT SURFACE " + outSurface + ": copied");
   2894                     } else {
   2895                         // For some reason there isn't a surface.  Clear the
   2896                         // caller's object so they see the same state.
   2897                         outSurface.release();
   2898                     }
   2899                 } catch (Exception e) {
   2900                     mInputMonitor.updateInputWindowsLw(true /*force*/);
   2901 
   2902                     Slog.w(TAG, "Exception thrown when creating surface for client "
   2903                              + client + " (" + win.mAttrs.getTitle() + ")",
   2904                              e);
   2905                     Binder.restoreCallingIdentity(origId);
   2906                     return 0;
   2907                 }
   2908                 if (toBeDisplayed) {
   2909                     focusMayChange = isDefaultDisplay;
   2910                 }
   2911                 if (win.mAttrs.type == TYPE_INPUT_METHOD
   2912                         && mInputMethodWindow == null) {
   2913                     mInputMethodWindow = win;
   2914                     imMayMove = true;
   2915                 }
   2916                 if (win.mAttrs.type == TYPE_BASE_APPLICATION
   2917                         && win.mAppToken != null
   2918                         && win.mAppToken.startingWindow != null) {
   2919                     // Special handling of starting window over the base
   2920                     // window of the app: propagate lock screen flags to it,
   2921                     // to provide the correct semantics while starting.
   2922                     final int mask =
   2923                         WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
   2924                         | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
   2925                         | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
   2926                     WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
   2927                     sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
   2928                 }
   2929             } else {
   2930                 winAnimator.mEnterAnimationPending = false;
   2931                 if (winAnimator.mSurfaceControl != null) {
   2932                     if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
   2933                             + ": mExiting=" + win.mExiting);
   2934                     // If we are not currently running the exit animation, we
   2935                     // need to see about starting one.
   2936                     if (!win.mExiting) {
   2937                         surfaceChanged = true;
   2938                         // Try starting an animation; if there isn't one, we
   2939                         // can destroy the surface right away.
   2940                         int transit = WindowManagerPolicy.TRANSIT_EXIT;
   2941                         if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
   2942                             transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
   2943                         }
   2944                         if (win.isWinVisibleLw() &&
   2945                                 winAnimator.applyAnimationLocked(transit, false)) {
   2946                             focusMayChange = isDefaultDisplay;
   2947                             win.mExiting = true;
   2948                         } else if (win.mWinAnimator.isAnimating()) {
   2949                             // Currently in a hide animation... turn this into
   2950                             // an exit.
   2951                             win.mExiting = true;
   2952                         } else if (win == mWallpaperTarget) {
   2953                             // If the wallpaper is currently behind this
   2954                             // window, we need to change both of them inside
   2955                             // of a transaction to avoid artifacts.
   2956                             win.mExiting = true;
   2957                             win.mWinAnimator.mAnimating = true;
   2958                         } else {
   2959                             if (mInputMethodWindow == win) {
   2960                                 mInputMethodWindow = null;
   2961                             }
   2962                             winAnimator.destroySurfaceLocked();
   2963                         }
   2964                         //TODO (multidisplay): Magnification is supported only for the default
   2965                         if (mDisplayMagnifier != null
   2966                                 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
   2967                             mDisplayMagnifier.onWindowTransitionLocked(win, transit);
   2968                         }
   2969                     }
   2970                 }
   2971 
   2972                 outSurface.release();
   2973                 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
   2974             }
   2975 
   2976             if (focusMayChange) {
   2977                 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
   2978                 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
   2979                         false /*updateInputWindows*/)) {
   2980                     imMayMove = false;
   2981                 }
   2982                 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
   2983             }
   2984 
   2985             // updateFocusedWindowLocked() already assigned layers so we only need to
   2986             // reassign them at this point if the IM window state gets shuffled
   2987             if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) {
   2988                 // Little hack here -- we -should- be able to rely on the
   2989                 // function to return true if the IME has moved and needs
   2990                 // its layer recomputed.  However, if the IME was hidden
   2991                 // and isn't actually moved in the list, its layer may be
   2992                 // out of data so we make sure to recompute it.
   2993                 assignLayersLocked(win.getWindowList());
   2994             }
   2995 
   2996             if (wallpaperMayMove) {
   2997                 getDefaultDisplayContentLocked().pendingLayoutChanges |=
   2998                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
   2999             }
   3000 
   3001             win.mDisplayContent.layoutNeeded = true;
   3002             win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
   3003             configChanged = updateOrientationFromAppTokensLocked(false);
   3004             performLayoutAndPlaceSurfacesLocked();
   3005             if (toBeDisplayed && win.mIsWallpaper) {
   3006                 DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
   3007                 updateWallpaperOffsetLocked(win,
   3008                         displayInfo.logicalWidth, displayInfo.logicalHeight, false);
   3009             }
   3010             if (win.mAppToken != null) {
   3011                 win.mAppToken.updateReportedVisibilityLocked();
   3012             }
   3013             outFrame.set(win.mCompatFrame);
   3014             outOverscanInsets.set(win.mOverscanInsets);
   3015             outContentInsets.set(win.mContentInsets);
   3016             outVisibleInsets.set(win.mVisibleInsets);
   3017             if (localLOGV) Slog.v(
   3018                 TAG, "Relayout given client " + client.asBinder()
   3019                 + ", requestedWidth=" + requestedWidth
   3020                 + ", requestedHeight=" + requestedHeight
   3021                 + ", viewVisibility=" + viewVisibility
   3022                 + "\nRelayout returning frame=" + outFrame
   3023                 + ", surface=" + outSurface);
   3024 
   3025             if (localLOGV || DEBUG_FOCUS) Slog.v(
   3026                 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
   3027 
   3028             inTouchMode = mInTouchMode;
   3029             animating = mAnimator.mAnimating && win.mWinAnimator.isAnimating();
   3030             if (animating && !mRelayoutWhileAnimating.contains(win)) {
   3031                 mRelayoutWhileAnimating.add(win);
   3032             }
   3033 
   3034             mInputMonitor.updateInputWindowsLw(true /*force*/);
   3035 
   3036             if (DEBUG_LAYOUT) {
   3037                 Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
   3038             }
   3039         }
   3040 
   3041         if (configChanged) {
   3042             sendNewConfiguration();
   3043         }
   3044 
   3045         Binder.restoreCallingIdentity(origId);
   3046 
   3047         return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0)
   3048                 | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0)
   3049                 | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0)
   3050                 | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0);
   3051     }
   3052 
   3053     public void performDeferredDestroyWindow(Session session, IWindow client) {
   3054         long origId = Binder.clearCallingIdentity();
   3055 
   3056         try {
   3057             synchronized (mWindowMap) {
   3058                 WindowState win = windowForClientLocked(session, client, false);
   3059                 if (win == null) {
   3060                     return;
   3061                 }
   3062                 win.mWinAnimator.destroyDeferredSurfaceLocked();
   3063             }
   3064         } finally {
   3065             Binder.restoreCallingIdentity(origId);
   3066         }
   3067     }
   3068 
   3069     public boolean outOfMemoryWindow(Session session, IWindow client) {
   3070         long origId = Binder.clearCallingIdentity();
   3071 
   3072         try {
   3073             synchronized (mWindowMap) {
   3074                 WindowState win = windowForClientLocked(session, client, false);
   3075                 if (win == null) {
   3076                     return false;
   3077                 }
   3078                 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false);
   3079             }
   3080         } finally {
   3081             Binder.restoreCallingIdentity(origId);
   3082         }
   3083     }
   3084 
   3085     public void finishDrawingWindow(Session session, IWindow client) {
   3086         final long origId = Binder.clearCallingIdentity();
   3087         try {
   3088             synchronized (mWindowMap) {
   3089                 WindowState win = windowForClientLocked(session, client, false);
   3090                 if (win != null && win.mWinAnimator.finishDrawingLocked()) {
   3091                     if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
   3092                         getDefaultDisplayContentLocked().pendingLayoutChanges |=
   3093                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
   3094                     }
   3095                     win.mDisplayContent.layoutNeeded = true;
   3096                     requestTraversalLocked();
   3097                 }
   3098             }
   3099         } finally {
   3100             Binder.restoreCallingIdentity(origId);
   3101         }
   3102     }
   3103 
   3104     @Override
   3105     public void getWindowFrame(IBinder token, Rect outBounds) {
   3106         if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
   3107                 "getWindowInfo()")) {
   3108             throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
   3109         }
   3110         synchronized (mWindowMap) {
   3111             WindowState windowState = mWindowMap.get(token);
   3112             if (windowState != null) {
   3113                 outBounds.set(windowState.mFrame);
   3114             } else {
   3115                 outBounds.setEmpty();
   3116             }
   3117         }
   3118     }
   3119 
   3120     @Override
   3121     public void setMagnificationSpec(MagnificationSpec spec) {
   3122         if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
   3123                 "setMagnificationSpec()")) {
   3124             throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
   3125         }
   3126         synchronized (mWindowMap) {
   3127             if (mDisplayMagnifier != null) {
   3128                 mDisplayMagnifier.setMagnificationSpecLocked(spec);
   3129             } else {
   3130                 throw new IllegalStateException("Magnification callbacks not set!");
   3131             }
   3132         }
   3133         if (Binder.getCallingPid() != android.os.Process.myPid()) {
   3134             spec.recycle();
   3135         }
   3136     }
   3137 
   3138     @Override
   3139     public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
   3140         if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
   3141                 "getCompatibleMagnificationSpecForWindow()")) {
   3142             throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
   3143         }
   3144         synchronized (mWindowMap) {
   3145             WindowState windowState = mWindowMap.get(windowToken);
   3146             if (windowState == null) {
   3147                 return null;
   3148             }
   3149             MagnificationSpec spec = null;
   3150             if (mDisplayMagnifier != null) {
   3151                 spec = mDisplayMagnifier.getMagnificationSpecForWindowLocked(windowState);
   3152             }
   3153             if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
   3154                 return null;
   3155             }
   3156             spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
   3157             spec.scale *= windowState.mGlobalScale;
   3158             return spec;
   3159         }
   3160     }
   3161 
   3162     @Override
   3163     public void setMagnificationCallbacks(IMagnificationCallbacks callbacks) {
   3164         if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
   3165                 "setMagnificationCallbacks()")) {
   3166             throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
   3167         }
   3168         synchronized (mWindowMap) {
   3169             if (mDisplayMagnifier == null) {
   3170                 mDisplayMagnifier = new DisplayMagnifier(this, callbacks);
   3171             } else {
   3172                 if (callbacks == null) {
   3173                     if (mDisplayMagnifier != null) {
   3174                         mDisplayMagnifier.destroyLocked();
   3175                         mDisplayMagnifier = null;
   3176                     }
   3177                 } else {
   3178                     throw new IllegalStateException("Magnification callbacks already set!");
   3179                 }
   3180             }
   3181         }
   3182     }
   3183 
   3184     private boolean applyAnimationLocked(AppWindowToken atoken,
   3185             WindowManager.LayoutParams lp, int transit, boolean enter) {
   3186         // Only apply an animation if the display isn't frozen.  If it is
   3187         // frozen, there is no reason to animate and it can cause strange
   3188         // artifacts when we unfreeze the display if some different animation
   3189         // is running.
   3190         if (okToDisplay()) {
   3191             DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
   3192             final int width = displayInfo.appWidth;
   3193             final int height = displayInfo.appHeight;
   3194             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken="
   3195                     + atoken);
   3196             Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height);
   3197             if (a != null) {
   3198                 if (DEBUG_ANIM) {
   3199                     RuntimeException e = null;
   3200                     if (!HIDE_STACK_CRAWLS) {
   3201                         e = new RuntimeException();
   3202                         e.fillInStackTrace();
   3203                     }
   3204                     Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e);
   3205                 }
   3206                 atoken.mAppAnimator.setAnimation(a, width, height);
   3207             }
   3208         } else {
   3209             atoken.mAppAnimator.clearAnimation();
   3210         }
   3211 
   3212         return atoken.mAppAnimator.animation != null;
   3213     }
   3214 
   3215     // -------------------------------------------------------------
   3216     // Application Window Tokens
   3217     // -------------------------------------------------------------
   3218 
   3219     public void validateAppTokens(int stackId, List<TaskGroup> tasks) {
   3220         synchronized (mWindowMap) {
   3221             int t = tasks.size() - 1;
   3222             if (t < 0) {
   3223                 Slog.w(TAG, "validateAppTokens: empty task list");
   3224                 return;
   3225             }
   3226 
   3227             TaskGroup task = tasks.get(0);
   3228             int taskId = task.taskId;
   3229             Task targetTask = mTaskIdToTask.get(taskId);
   3230             DisplayContent displayContent = targetTask.getDisplayContent();
   3231             if (displayContent == null) {
   3232                 Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId);
   3233                 return;
   3234             }
   3235 
   3236             final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks();
   3237             int taskNdx;
   3238             for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) {
   3239                 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens;
   3240                 task = tasks.get(t);
   3241                 List<IApplicationToken> tokens = task.tokens;
   3242 
   3243                 DisplayContent lastDisplayContent = displayContent;
   3244                 displayContent = mTaskIdToTask.get(taskId).getDisplayContent();
   3245                 if (displayContent != lastDisplayContent) {
   3246                     Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!");
   3247                     return;
   3248                 }
   3249 
   3250                 int tokenNdx;
   3251                 int v;
   3252                 for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1;
   3253                         tokenNdx >= 0 && v >= 0; ) {
   3254                     final AppWindowToken atoken = localTokens.get(tokenNdx);
   3255                     if (atoken.removed) {
   3256                         --tokenNdx;
   3257                         continue;
   3258                     }
   3259                     if (tokens.get(v) != atoken.token) {
   3260                         break;
   3261                     }
   3262                     --tokenNdx;
   3263                     v--;
   3264                 }
   3265 
   3266                 if (tokenNdx >= 0 || v >= 0) {
   3267                     break;
   3268                 }
   3269             }
   3270 
   3271             if (taskNdx >= 0 || t >= 0) {
   3272                 Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks);
   3273                 Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + localTasks);
   3274                 Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4));
   3275             }
   3276         }
   3277     }
   3278 
   3279     public void validateStackOrder(Integer[] remoteStackIds) {
   3280         // TODO:
   3281     }
   3282 
   3283     boolean checkCallingPermission(String permission, String func) {
   3284         // Quick check: if the calling permission is me, it's all okay.
   3285         if (Binder.getCallingPid() == Process.myPid()) {
   3286             return true;
   3287         }
   3288 
   3289         if (mContext.checkCallingPermission(permission)
   3290                 == PackageManager.PERMISSION_GRANTED) {
   3291             return true;
   3292         }
   3293         String msg = "Permission Denial: " + func + " from pid="
   3294                 + Binder.getCallingPid()
   3295                 + ", uid=" + Binder.getCallingUid()
   3296                 + " requires " + permission;
   3297         Slog.w(TAG, msg);
   3298         return false;
   3299     }
   3300 
   3301     boolean okToDisplay() {
   3302         return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully();
   3303     }
   3304 
   3305     AppWindowToken findAppWindowToken(IBinder token) {
   3306         WindowToken wtoken = mTokenMap.get(token);
   3307         if (wtoken == null) {
   3308             return null;
   3309         }
   3310         return wtoken.appWindowToken;
   3311     }
   3312 
   3313     @Override
   3314     public void addWindowToken(IBinder token, int type) {
   3315         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3316                 "addWindowToken()")) {
   3317             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3318         }
   3319 
   3320         synchronized(mWindowMap) {
   3321             WindowToken wtoken = mTokenMap.get(token);
   3322             if (wtoken != null) {
   3323                 Slog.w(TAG, "Attempted to add existing input method token: " + token);
   3324                 return;
   3325             }
   3326             wtoken = new WindowToken(this, token, type, true);
   3327             mTokenMap.put(token, wtoken);
   3328             if (type == TYPE_WALLPAPER) {
   3329                 mWallpaperTokens.add(wtoken);
   3330             }
   3331         }
   3332     }
   3333 
   3334     @Override
   3335     public void removeWindowToken(IBinder token) {
   3336         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3337                 "removeWindowToken()")) {
   3338             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3339         }
   3340 
   3341         final long origId = Binder.clearCallingIdentity();
   3342         synchronized(mWindowMap) {
   3343             DisplayContent displayContent = null;
   3344             WindowToken wtoken = mTokenMap.remove(token);
   3345             if (wtoken != null) {
   3346                 boolean delayed = false;
   3347                 if (!wtoken.hidden) {
   3348                     final int N = wtoken.windows.size();
   3349                     boolean changed = false;
   3350 
   3351                     for (int i=0; i<N; i++) {
   3352                         WindowState win = wtoken.windows.get(i);
   3353                         displayContent = win.mDisplayContent;
   3354 
   3355                         if (win.mWinAnimator.isAnimating()) {
   3356                             delayed = true;
   3357                         }
   3358 
   3359                         if (win.isVisibleNow()) {
   3360                             win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
   3361                                     false);
   3362                             //TODO (multidisplay): Magnification is supported only for the default
   3363                             if (mDisplayMagnifier != null && win.isDefaultDisplay()) {
   3364                                 mDisplayMagnifier.onWindowTransitionLocked(win,
   3365                                         WindowManagerPolicy.TRANSIT_EXIT);
   3366                             }
   3367                             changed = true;
   3368                             displayContent.layoutNeeded = true;
   3369                         }
   3370                     }
   3371 
   3372                     wtoken.hidden = true;
   3373 
   3374                     if (changed) {
   3375                         performLayoutAndPlaceSurfacesLocked();
   3376                         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
   3377                                 false /*updateInputWindows*/);
   3378                     }
   3379 
   3380                     if (delayed) {
   3381                         displayContent.mExitingTokens.add(wtoken);
   3382                     } else if (wtoken.windowType == TYPE_WALLPAPER) {
   3383                         mWallpaperTokens.remove(wtoken);
   3384                     }
   3385                 }
   3386 
   3387                 mInputMonitor.updateInputWindowsLw(true /*force*/);
   3388             } else {
   3389                 Slog.w(TAG, "Attempted to remove non-existing token: " + token);
   3390             }
   3391         }
   3392         Binder.restoreCallingIdentity(origId);
   3393     }
   3394 
   3395     private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) {
   3396         final TaskStack stack = mStackIdToStack.get(stackId);
   3397         if (stack == null) {
   3398             throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
   3399         }
   3400         EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
   3401         Task task = new Task(atoken, stack, userId);
   3402         mTaskIdToTask.put(taskId, task);
   3403         stack.addTask(task, true);
   3404         return task;
   3405     }
   3406 
   3407     @Override
   3408     public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
   3409             int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
   3410             int configChanges) {
   3411         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3412                 "addAppToken()")) {
   3413             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3414         }
   3415 
   3416         // Get the dispatching timeout here while we are not holding any locks so that it
   3417         // can be cached by the AppWindowToken.  The timeout value is used later by the
   3418         // input dispatcher in code that does hold locks.  If we did not cache the value
   3419         // here we would run the chance of introducing a deadlock between the window manager
   3420         // (which holds locks while updating the input dispatcher state) and the activity manager
   3421         // (which holds locks while querying the application token).
   3422         long inputDispatchingTimeoutNanos;
   3423         try {
   3424             inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
   3425         } catch (RemoteException ex) {
   3426             Slog.w(TAG, "Could not get dispatching timeout.", ex);
   3427             inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
   3428         }
   3429 
   3430         synchronized(mWindowMap) {
   3431             AppWindowToken atoken = findAppWindowToken(token.asBinder());
   3432             if (atoken != null) {
   3433                 Slog.w(TAG, "Attempted to add existing app token: " + token);
   3434                 return;
   3435             }
   3436             atoken = new AppWindowToken(this, token);
   3437             atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
   3438             atoken.groupId = taskId;
   3439             atoken.appFullscreen = fullscreen;
   3440             atoken.showWhenLocked = showWhenLocked;
   3441             atoken.requestedOrientation = requestedOrientation;
   3442             atoken.layoutConfigChanges = (configChanges &
   3443                     (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
   3444             if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
   3445                     + " to stack=" + stackId + " task=" + taskId + " at " + addPos);
   3446 
   3447             Task task = mTaskIdToTask.get(taskId);
   3448             if (task == null) {
   3449                 task = createTask(taskId, stackId, userId, atoken);
   3450             } else {
   3451                 task.addAppToken(addPos, atoken);
   3452             }
   3453 
   3454             mTokenMap.put(token.asBinder(), atoken);
   3455 
   3456             // Application tokens start out hidden.
   3457             atoken.hidden = true;
   3458             atoken.hiddenRequested = true;
   3459 
   3460             //dump();
   3461         }
   3462     }
   3463 
   3464     @Override
   3465     public void setAppGroupId(IBinder token, int groupId) {
   3466         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3467                 "setAppGroupId()")) {
   3468             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3469         }
   3470 
   3471         synchronized(mWindowMap) {
   3472             final AppWindowToken atoken = findAppWindowToken(token);
   3473             if (atoken == null) {
   3474                 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
   3475                 return;
   3476             }
   3477             Task oldTask = mTaskIdToTask.get(atoken.groupId);
   3478             oldTask.removeAppToken(atoken);
   3479 
   3480             atoken.groupId = groupId;
   3481             Task newTask = mTaskIdToTask.get(groupId);
   3482             if (newTask == null) {
   3483                 newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken);
   3484             }
   3485             newTask.mAppTokens.add(atoken);
   3486         }
   3487     }
   3488 
   3489     public int getOrientationFromWindowsLocked() {
   3490         if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
   3491             // If the display is frozen, some activities may be in the middle
   3492             // of restarting, and thus have removed their old window.  If the
   3493             // window has the flag to hide the lock screen, then the lock screen
   3494             // can re-appear and inflict its own orientation on us.  Keep the
   3495             // orientation stable until this all settles down.
   3496             return mLastWindowForcedOrientation;
   3497         }
   3498 
   3499         // TODO(multidisplay): Change to the correct display.
   3500         final WindowList windows = getDefaultWindowListLocked();
   3501         int pos = windows.size() - 1;
   3502         while (pos >= 0) {
   3503             WindowState win = windows.get(pos);
   3504             pos--;
   3505             if (win.mAppToken != null) {
   3506                 // We hit an application window. so the orientation will be determined by the
   3507                 // app window. No point in continuing further.
   3508                 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
   3509             }
   3510             if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
   3511                 continue;
   3512             }
   3513             int req = win.mAttrs.screenOrientation;
   3514             if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
   3515                     (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
   3516                 continue;
   3517             }
   3518 
   3519             if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req);
   3520             return (mLastWindowForcedOrientation=req);
   3521         }
   3522         return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
   3523     }
   3524 
   3525     public int getOrientationFromAppTokensLocked() {
   3526         int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
   3527         boolean findingBehind = false;
   3528         boolean lastFullscreen = false;
   3529         // TODO: Multi window.
   3530         DisplayContent displayContent = getDefaultDisplayContentLocked();
   3531         final ArrayList<Task> tasks = displayContent.getTasks();
   3532         for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
   3533             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
   3534             final int firstToken = tokens.size() - 1;
   3535             for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) {
   3536                 final AppWindowToken atoken = tokens.get(tokenNdx);
   3537 
   3538                 if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
   3539 
   3540                 // if we're about to tear down this window and not seek for
   3541                 // the behind activity, don't use it for orientation
   3542                 if (!findingBehind
   3543                         && (!atoken.hidden && atoken.hiddenRequested)) {
   3544                     if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
   3545                             + " -- going to hide");
   3546                     continue;
   3547                 }
   3548 
   3549                 if (tokenNdx == firstToken) {
   3550                     // If we have hit a new Task, and the bottom
   3551                     // of the previous group didn't explicitly say to use
   3552                     // the orientation behind it, and the last app was
   3553                     // full screen, then we'll stick with the
   3554                     // user's orientation.
   3555                     if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
   3556                             && lastFullscreen) {
   3557                         if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
   3558                                 + " -- end of group, return " + lastOrientation);
   3559                         return lastOrientation;
   3560                     }
   3561                 }
   3562 
   3563                 // We ignore any hidden applications on the top.
   3564                 if (atoken.hiddenRequested || atoken.willBeHidden) {
   3565                     if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
   3566                             + " -- hidden on top");
   3567                     continue;
   3568                 }
   3569 
   3570                 if (tokenNdx == 0) {
   3571                     // Last token in this task.
   3572                     lastOrientation = atoken.requestedOrientation;
   3573                 }
   3574 
   3575                 int or = atoken.requestedOrientation;
   3576                 // If this application is fullscreen, and didn't explicitly say
   3577                 // to use the orientation behind it, then just take whatever
   3578                 // orientation it has and ignores whatever is under it.
   3579                 lastFullscreen = atoken.appFullscreen;
   3580                 if (lastFullscreen
   3581                         && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
   3582                     if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
   3583                             + " -- full screen, return " + or);
   3584                     return or;
   3585                 }
   3586                 // If this application has requested an explicit orientation,
   3587                 // then use it.
   3588                 if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
   3589                         && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
   3590                     if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
   3591                             + " -- explicitly set, return " + or);
   3592                     return or;
   3593                 }
   3594                 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
   3595             }
   3596         }
   3597         if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation");
   3598         return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
   3599     }
   3600 
   3601     @Override
   3602     public Configuration updateOrientationFromAppTokens(
   3603             Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
   3604         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3605                 "updateOrientationFromAppTokens()")) {
   3606             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3607         }
   3608 
   3609         Configuration config = null;
   3610         long ident = Binder.clearCallingIdentity();
   3611 
   3612         synchronized(mWindowMap) {
   3613             config = updateOrientationFromAppTokensLocked(currentConfig,
   3614                     freezeThisOneIfNeeded);
   3615         }
   3616 
   3617         Binder.restoreCallingIdentity(ident);
   3618         return config;
   3619     }
   3620 
   3621     private Configuration updateOrientationFromAppTokensLocked(
   3622             Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
   3623         Configuration config = null;
   3624 
   3625         if (updateOrientationFromAppTokensLocked(false)) {
   3626             if (freezeThisOneIfNeeded != null) {
   3627                 AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
   3628                 if (atoken != null) {
   3629                     startAppFreezingScreenLocked(atoken, ActivityInfo.CONFIG_ORIENTATION);
   3630                 }
   3631             }
   3632             config = computeNewConfigurationLocked();
   3633 
   3634         } else if (currentConfig != null) {
   3635             // No obvious action we need to take, but if our current
   3636             // state mismatches the activity manager's, update it,
   3637             // disregarding font scale, which should remain set to
   3638             // the value of the previous configuration.
   3639             mTempConfiguration.setToDefaults();
   3640             mTempConfiguration.fontScale = currentConfig.fontScale;
   3641             if (computeScreenConfigurationLocked(mTempConfiguration)) {
   3642                 if (currentConfig.diff(mTempConfiguration) != 0) {
   3643                     mWaitingForConfig = true;
   3644                     final DisplayContent displayContent = getDefaultDisplayContentLocked();
   3645                     displayContent.layoutNeeded = true;
   3646                     int anim[] = new int[2];
   3647                     if (displayContent.isDimming()) {
   3648                         anim[0] = anim[1] = 0;
   3649                     } else {
   3650                         mPolicy.selectRotationAnimationLw(anim);
   3651                     }
   3652                     startFreezingDisplayLocked(false, anim[0], anim[1]);
   3653                     config = new Configuration(mTempConfiguration);
   3654                 }
   3655             }
   3656         }
   3657 
   3658         return config;
   3659     }
   3660 
   3661     /*
   3662      * Determine the new desired orientation of the display, returning
   3663      * a non-null new Configuration if it has changed from the current
   3664      * orientation.  IF TRUE IS RETURNED SOMEONE MUST CALL
   3665      * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
   3666      * SCREEN.  This will typically be done for you if you call
   3667      * sendNewConfiguration().
   3668      *
   3669      * The orientation is computed from non-application windows first. If none of
   3670      * the non-application windows specify orientation, the orientation is computed from
   3671      * application tokens.
   3672      * @see android.view.IWindowManager#updateOrientationFromAppTokens(
   3673      * android.os.IBinder)
   3674      */
   3675     boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
   3676         long ident = Binder.clearCallingIdentity();
   3677         try {
   3678             int req = getOrientationFromWindowsLocked();
   3679             if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
   3680                 req = getOrientationFromAppTokensLocked();
   3681             }
   3682 
   3683             if (req != mForcedAppOrientation) {
   3684                 mForcedAppOrientation = req;
   3685                 //send a message to Policy indicating orientation change to take
   3686                 //action like disabling/enabling sensors etc.,
   3687                 mPolicy.setCurrentOrientationLw(req);
   3688                 if (updateRotationUncheckedLocked(inTransaction)) {
   3689                     // changed
   3690                     return true;
   3691                 }
   3692             }
   3693 
   3694             return false;
   3695         } finally {
   3696             Binder.restoreCallingIdentity(ident);
   3697         }
   3698     }
   3699 
   3700     @Override
   3701     public void setNewConfiguration(Configuration config) {
   3702         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3703                 "setNewConfiguration()")) {
   3704             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3705         }
   3706 
   3707         synchronized(mWindowMap) {
   3708             mCurConfiguration = new Configuration(config);
   3709             if (mWaitingForConfig) {
   3710                 mWaitingForConfig = false;
   3711                 mLastFinishedFreezeSource = "new-config";
   3712             }
   3713             performLayoutAndPlaceSurfacesLocked();
   3714         }
   3715     }
   3716 
   3717     @Override
   3718     public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
   3719         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3720                 "setAppOrientation()")) {
   3721             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3722         }
   3723 
   3724         synchronized(mWindowMap) {
   3725             AppWindowToken atoken = findAppWindowToken(token.asBinder());
   3726             if (atoken == null) {
   3727                 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
   3728                 return;
   3729             }
   3730 
   3731             atoken.requestedOrientation = requestedOrientation;
   3732         }
   3733     }
   3734 
   3735     @Override
   3736     public int getAppOrientation(IApplicationToken token) {
   3737         synchronized(mWindowMap) {
   3738             AppWindowToken wtoken = findAppWindowToken(token.asBinder());
   3739             if (wtoken == null) {
   3740                 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
   3741             }
   3742 
   3743             return wtoken.requestedOrientation;
   3744         }
   3745     }
   3746 
   3747     /** Call while in a Surface transaction. */
   3748     void setFocusedStackLayer() {
   3749         mFocusedStackLayer = 0;
   3750         if (mFocusedApp != null) {
   3751             final WindowList windows = mFocusedApp.allAppWindows;
   3752             for (int i = windows.size() - 1; i >= 0; --i) {
   3753                 final WindowState win = windows.get(i);
   3754                 final int animLayer = win.mWinAnimator.mAnimLayer;
   3755                 if (win.mAttachedWindow == null && win.isVisibleLw() &&
   3756                         animLayer > mFocusedStackLayer) {
   3757                     mFocusedStackLayer = animLayer + LAYER_OFFSET_FOCUSED_STACK;
   3758                 }
   3759             }
   3760         }
   3761         if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedStackFrame to layer=" +
   3762                 mFocusedStackLayer);
   3763         mFocusedStackFrame.setLayer(mFocusedStackLayer);
   3764     }
   3765 
   3766     void setFocusedStackFrame() {
   3767         final TaskStack stack;
   3768         if (mFocusedApp != null) {
   3769             Task task = mTaskIdToTask.get(mFocusedApp.groupId);
   3770             stack = task.mStack;
   3771             task.getDisplayContent().setTouchExcludeRegion(stack);
   3772         } else {
   3773             stack = null;
   3774         }
   3775         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame");
   3776         SurfaceControl.openTransaction();
   3777         try {
   3778             if (stack == null) {
   3779                 mFocusedStackFrame.setVisibility(false);
   3780             } else {
   3781                 final StackBox box = stack.mStackBox;
   3782                 final Rect bounds = box.mBounds;
   3783                 final boolean multipleStacks = box.mParent != null;
   3784                 mFocusedStackFrame.setBounds(bounds);
   3785                 mFocusedStackFrame.setVisibility(multipleStacks);
   3786             }
   3787         } finally {
   3788             SurfaceControl.closeTransaction();
   3789             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame");
   3790         }
   3791     }
   3792 
   3793     @Override
   3794     public void setFocusedApp(IBinder token, boolean moveFocusNow) {
   3795         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3796                 "setFocusedApp()")) {
   3797             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3798         }
   3799 
   3800         synchronized(mWindowMap) {
   3801             boolean changed = false;
   3802             if (token == null) {
   3803                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
   3804                 changed = mFocusedApp != null;
   3805                 mFocusedApp = null;
   3806                 if (changed) {
   3807                     mInputMonitor.setFocusedAppLw(null);
   3808                 }
   3809             } else {
   3810                 AppWindowToken newFocus = findAppWindowToken(token);
   3811                 if (newFocus == null) {
   3812                     Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
   3813                     return;
   3814                 }
   3815                 changed = mFocusedApp != newFocus;
   3816                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus
   3817                         + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
   3818                 mFocusedApp = newFocus;
   3819                 if (changed) {
   3820                     mInputMonitor.setFocusedAppLw(newFocus);
   3821                 }
   3822             }
   3823 
   3824             if (moveFocusNow && changed) {
   3825                 final long origId = Binder.clearCallingIdentity();
   3826                 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
   3827                 Binder.restoreCallingIdentity(origId);
   3828             }
   3829         }
   3830     }
   3831 
   3832     @Override
   3833     public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
   3834         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3835                 "prepareAppTransition()")) {
   3836             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3837         }
   3838 
   3839         synchronized(mWindowMap) {
   3840             if (DEBUG_APP_TRANSITIONS) Slog.v(
   3841                     TAG, "Prepare app transition: transit=" + transit
   3842                     + " " + mAppTransition
   3843                     + " alwaysKeepCurrent=" + alwaysKeepCurrent
   3844                     + " Callers=" + Debug.getCallers(3));
   3845             if (okToDisplay()) {
   3846                 if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) {
   3847                     mAppTransition.setAppTransition(transit);
   3848                 } else if (!alwaysKeepCurrent) {
   3849                     if (transit == AppTransition.TRANSIT_TASK_OPEN
   3850                             && mAppTransition.isTransitionEqual(
   3851                                     AppTransition.TRANSIT_TASK_CLOSE)) {
   3852                         // Opening a new task always supersedes a close for the anim.
   3853                         mAppTransition.setAppTransition(transit);
   3854                     } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN
   3855                             && mAppTransition.isTransitionEqual(
   3856                                 AppTransition.TRANSIT_ACTIVITY_CLOSE)) {
   3857                         // Opening a new activity always supersedes a close for the anim.
   3858                         mAppTransition.setAppTransition(transit);
   3859                     }
   3860                 }
   3861                 mAppTransition.prepare();
   3862                 mStartingIconInTransition = false;
   3863                 mSkipAppTransitionAnimation = false;
   3864                 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
   3865                 mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000);
   3866             }
   3867         }
   3868     }
   3869 
   3870     @Override
   3871     public int getPendingAppTransition() {
   3872         return mAppTransition.getAppTransition();
   3873     }
   3874 
   3875     @Override
   3876     public void overridePendingAppTransition(String packageName,
   3877             int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
   3878         synchronized(mWindowMap) {
   3879             mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,
   3880                     startedCallback);
   3881         }
   3882     }
   3883 
   3884     @Override
   3885     public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
   3886             int startHeight) {
   3887         synchronized(mWindowMap) {
   3888             mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth,
   3889                     startHeight);
   3890         }
   3891     }
   3892 
   3893     @Override
   3894     public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
   3895             int startY, IRemoteCallback startedCallback, boolean scaleUp) {
   3896         synchronized(mWindowMap) {
   3897             mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
   3898                     startedCallback, scaleUp);
   3899         }
   3900     }
   3901 
   3902     @Override
   3903     public void executeAppTransition() {
   3904         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3905                 "executeAppTransition()")) {
   3906             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3907         }
   3908 
   3909         synchronized(mWindowMap) {
   3910             if (DEBUG_APP_TRANSITIONS) {
   3911                 RuntimeException e = new RuntimeException("here");
   3912                 e.fillInStackTrace();
   3913                 Slog.w(TAG, "Execute app transition: " + mAppTransition, e);
   3914             }
   3915             if (mAppTransition.isTransitionSet()) {
   3916                 mAppTransition.setReady();
   3917                 final long origId = Binder.clearCallingIdentity();
   3918                 performLayoutAndPlaceSurfacesLocked();
   3919                 Binder.restoreCallingIdentity(origId);
   3920             }
   3921         }
   3922     }
   3923 
   3924     @Override
   3925     public void setAppStartingWindow(IBinder token, String pkg,
   3926             int theme, CompatibilityInfo compatInfo,
   3927             CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
   3928             int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
   3929         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3930                 "setAppStartingWindow()")) {
   3931             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3932         }
   3933 
   3934         synchronized(mWindowMap) {
   3935             if (DEBUG_STARTING_WINDOW) Slog.v(
   3936                     TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg
   3937                     + " transferFrom=" + transferFrom);
   3938 
   3939             AppWindowToken wtoken = findAppWindowToken(token);
   3940             if (wtoken == null) {
   3941                 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
   3942                 return;
   3943             }
   3944 
   3945             // If the display is frozen, we won't do anything until the
   3946             // actual window is displayed so there is no reason to put in
   3947             // the starting window.
   3948             if (!okToDisplay()) {
   3949                 return;
   3950             }
   3951 
   3952             if (wtoken.startingData != null) {
   3953                 return;
   3954             }
   3955 
   3956             if (transferFrom != null) {
   3957                 AppWindowToken ttoken = findAppWindowToken(transferFrom);
   3958                 if (ttoken != null) {
   3959                     WindowState startingWindow = ttoken.startingWindow;
   3960                     if (startingWindow != null) {
   3961                         if (mStartingIconInTransition) {
   3962                             // In this case, the starting icon has already
   3963                             // been displayed, so start letting windows get
   3964                             // shown immediately without any more transitions.
   3965                             mSkipAppTransitionAnimation = true;
   3966                         }
   3967                         if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
   3968                                 "Moving existing starting " + startingWindow + " from " + ttoken
   3969                                 + " to " + wtoken);
   3970                         final long origId = Binder.clearCallingIdentity();
   3971 
   3972                         // Transfer the starting window over to the new
   3973                         // token.
   3974                         wtoken.startingData = ttoken.startingData;
   3975                         wtoken.startingView = ttoken.startingView;
   3976                         wtoken.startingDisplayed = ttoken.startingDisplayed;
   3977                         ttoken.startingDisplayed = false;
   3978                         wtoken.startingWindow = startingWindow;
   3979                         wtoken.reportedVisible = ttoken.reportedVisible;
   3980                         ttoken.startingData = null;
   3981                         ttoken.startingView = null;
   3982                         ttoken.startingWindow = null;
   3983                         ttoken.startingMoved = true;
   3984                         startingWindow.mToken = wtoken;
   3985                         startingWindow.mRootToken = wtoken;
   3986                         startingWindow.mAppToken = wtoken;
   3987                         startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator;
   3988 
   3989                         if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
   3990                             Slog.v(TAG, "Removing starting window: " + startingWindow);
   3991                         }
   3992                         removeStartingWindowTimeout(ttoken);
   3993                         startingWindow.getWindowList().remove(startingWindow);
   3994                         mWindowsChanged = true;
   3995                         if (DEBUG_ADD_REMOVE) Slog.v(TAG,
   3996                                 "Removing starting " + startingWindow + " from " + ttoken);
   3997                         ttoken.windows.remove(startingWindow);
   3998                         ttoken.allAppWindows.remove(startingWindow);
   3999                         addWindowToListInOrderLocked(startingWindow, true);
   4000 
   4001                         // Propagate other interesting state between the
   4002                         // tokens.  If the old token is displayed, we should
   4003                         // immediately force the new one to be displayed.  If
   4004                         // it is animating, we need to move that animation to
   4005                         // the new one.
   4006                         if (ttoken.allDrawn) {
   4007                             wtoken.allDrawn = true;
   4008                             wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn;
   4009                         }
   4010                         if (ttoken.firstWindowDrawn) {
   4011                             wtoken.firstWindowDrawn = true;
   4012                         }
   4013                         if (!ttoken.hidden) {
   4014                             wtoken.hidden = false;
   4015                             wtoken.hiddenRequested = false;
   4016                             wtoken.willBeHidden = false;
   4017                         }
   4018                         if (wtoken.clientHidden != ttoken.clientHidden) {
   4019                             wtoken.clientHidden = ttoken.clientHidden;
   4020                             wtoken.sendAppVisibilityToClients();
   4021                         }
   4022                         final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
   4023                         final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
   4024                         if (tAppAnimator.animation != null) {
   4025                             wAppAnimator.animation = tAppAnimator.animation;
   4026                             wAppAnimator.animating = tAppAnimator.animating;
   4027                             wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment;
   4028                             tAppAnimator.animation = null;
   4029                             tAppAnimator.animLayerAdjustment = 0;
   4030                             wAppAnimator.updateLayers();
   4031                             tAppAnimator.updateLayers();
   4032                         }
   4033 
   4034                         updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
   4035                                 true /*updateInputWindows*/);
   4036                         getDefaultDisplayContentLocked().layoutNeeded = true;
   4037                         performLayoutAndPlaceSurfacesLocked();
   4038                         Binder.restoreCallingIdentity(origId);
   4039                         return;
   4040                     } else if (ttoken.startingData != null) {
   4041                         // The previous app was getting ready to show a
   4042                         // starting window, but hasn't yet done so.  Steal it!
   4043                         if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
   4044                                 "Moving pending starting from " + ttoken
   4045                                 + " to " + wtoken);
   4046                         wtoken.startingData = ttoken.startingData;
   4047                         ttoken.startingData = null;
   4048                         ttoken.startingMoved = true;
   4049                         Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
   4050                         // Note: we really want to do sendMessageAtFrontOfQueue() because we
   4051                         // want to process the message ASAP, before any other queued
   4052                         // messages.
   4053                         mH.sendMessageAtFrontOfQueue(m);
   4054                         return;
   4055                     }
   4056                     final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
   4057                     final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
   4058                     if (tAppAnimator.thumbnail != null) {
   4059                         // The old token is animating with a thumbnail, transfer
   4060                         // that to the new token.
   4061                         if (wAppAnimator.thumbnail != null) {
   4062                             wAppAnimator.thumbnail.destroy();
   4063                         }
   4064                         wAppAnimator.thumbnail = tAppAnimator.thumbnail;
   4065                         wAppAnimator.thumbnailX = tAppAnimator.thumbnailX;
   4066                         wAppAnimator.thumbnailY = tAppAnimator.thumbnailY;
   4067                         wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
   4068                         wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
   4069                         tAppAnimator.thumbnail = null;
   4070                     }
   4071                 }
   4072             }
   4073 
   4074             // There is no existing starting window, and the caller doesn't
   4075             // want us to create one, so that's it!
   4076             if (!createIfNeeded) {
   4077                 return;
   4078             }
   4079 
   4080             // If this is a translucent window, then don't
   4081             // show a starting window -- the current effect (a full-screen
   4082             // opaque starting window that fades away to the real contents
   4083             // when it is ready) does not work for this.
   4084             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x"
   4085                     + Integer.toHexString(theme));
   4086             if (theme != 0) {
   4087                 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
   4088                         com.android.internal.R.styleable.Window, mCurrentUserId);
   4089                 if (ent == null) {
   4090                     // Whoops!  App doesn't exist.  Um.  Okay.  We'll just
   4091                     // pretend like we didn't see that.
   4092                     return;
   4093                 }
   4094                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent="
   4095                         + ent.array.getBoolean(
   4096                                 com.android.internal.R.styleable.Window_windowIsTranslucent, false)
   4097                         + " Floating="
   4098                         + ent.array.getBoolean(
   4099                                 com.android.internal.R.styleable.Window_windowIsFloating, false)
   4100                         + " ShowWallpaper="
   4101                         + ent.array.getBoolean(
   4102                                 com.android.internal.R.styleable.Window_windowShowWallpaper, false));
   4103                 if (ent.array.getBoolean(
   4104                         com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
   4105                     return;
   4106                 }
   4107                 if (ent.array.getBoolean(
   4108                         com.android.internal.R.styleable.Window_windowIsFloating, false)) {
   4109                     return;
   4110                 }
   4111                 if (ent.array.getBoolean(
   4112                         com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
   4113                     if (mWallpaperTarget == null) {
   4114                         // If this theme is requesting a wallpaper, and the wallpaper
   4115                         // is not curently visible, then this effectively serves as
   4116                         // an opaque window and our starting window transition animation
   4117                         // can still work.  We just need to make sure the starting window
   4118                         // is also showing the wallpaper.
   4119                         windowFlags |= FLAG_SHOW_WALLPAPER;
   4120                     } else {
   4121                         return;
   4122                     }
   4123                 }
   4124             }
   4125 
   4126             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData");
   4127             mStartingIconInTransition = true;
   4128             wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
   4129                     labelRes, icon, logo, windowFlags);
   4130             Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
   4131             // Note: we really want to do sendMessageAtFrontOfQueue() because we
   4132             // want to process the message ASAP, before any other queued
   4133             // messages.
   4134             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
   4135             mH.sendMessageAtFrontOfQueue(m);
   4136         }
   4137     }
   4138 
   4139     @Override
   4140     public void setAppWillBeHidden(IBinder token) {
   4141         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   4142                 "setAppWillBeHidden()")) {
   4143             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   4144         }
   4145 
   4146         AppWindowToken wtoken;
   4147 
   4148         synchronized(mWindowMap) {
   4149             wtoken = findAppWindowToken(token);
   4150             if (wtoken == null) {
   4151                 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
   4152                 return;
   4153             }
   4154             wtoken.willBeHidden = true;
   4155         }
   4156     }
   4157 
   4158     public void setAppFullscreen(IBinder token, boolean toOpaque) {
   4159         AppWindowToken atoken = findAppWindowToken(token);
   4160         if (atoken != null) {
   4161             atoken.appFullscreen = toOpaque;
   4162             requestTraversal();
   4163         }
   4164     }
   4165 
   4166     boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
   4167             boolean visible, int transit, boolean performLayout) {
   4168         boolean delayed = false;
   4169 
   4170         if (wtoken.clientHidden == visible) {
   4171             wtoken.clientHidden = !visible;
   4172             wtoken.sendAppVisibilityToClients();
   4173         }
   4174 
   4175         wtoken.willBeHidden = false;
   4176         if (wtoken.hidden == visible) {
   4177             boolean changed = false;
   4178             if (DEBUG_APP_TRANSITIONS) Slog.v(
   4179                 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
   4180                 + " performLayout=" + performLayout);
   4181 
   4182             boolean runningAppAnimation = false;
   4183 
   4184             if (transit != AppTransition.TRANSIT_UNSET) {
   4185                 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
   4186                     wtoken.mAppAnimator.animation = null;
   4187                 }
   4188                 if (applyAnimationLocked(wtoken, lp, transit, visible)) {
   4189                     delayed = runningAppAnimation = true;
   4190                 }
   4191                 WindowState window = wtoken.findMainWindow();
   4192                 //TODO (multidisplay): Magnification is supported only for the default display.
   4193                 if (window != null && mDisplayMagnifier != null
   4194                         && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
   4195                     mDisplayMagnifier.onAppWindowTransitionLocked(window, transit);
   4196                 }
   4197                 changed = true;
   4198             }
   4199 
   4200             final int N = wtoken.allAppWindows.size();
   4201             for (int i=0; i<N; i++) {
   4202                 WindowState win = wtoken.allAppWindows.get(i);
   4203                 if (win == wtoken.startingWindow) {
   4204                     continue;
   4205                 }
   4206 
   4207                 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
   4208                 //win.dump("  ");
   4209                 if (visible) {
   4210                     if (!win.isVisibleNow()) {
   4211                         if (!runningAppAnimation) {
   4212                             win.mWinAnimator.applyAnimationLocked(
   4213                                     WindowManagerPolicy.TRANSIT_ENTER, true);
   4214                             //TODO (multidisplay): Magnification is supported only for the default
   4215                             if (mDisplayMagnifier != null
   4216                                     && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
   4217                                 mDisplayMagnifier.onWindowTransitionLocked(win,
   4218                                         WindowManagerPolicy.TRANSIT_ENTER);
   4219                             }
   4220                         }
   4221                         changed = true;
   4222                         win.mDisplayContent.layoutNeeded = true;
   4223                     }
   4224                 } else if (win.isVisibleNow()) {
   4225                     if (!runningAppAnimation) {
   4226                         win.mWinAnimator.applyAnimationLocked(
   4227                                 WindowManagerPolicy.TRANSIT_EXIT, false);
   4228                         //TODO (multidisplay): Magnification is supported only for the default
   4229                         if (mDisplayMagnifier != null
   4230                                 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
   4231                             mDisplayMagnifier.onWindowTransitionLocked(win,
   4232                                     WindowManagerPolicy.TRANSIT_EXIT);
   4233                         }
   4234                     }
   4235                     changed = true;
   4236                     win.mDisplayContent.layoutNeeded = true;
   4237                 }
   4238             }
   4239 
   4240             wtoken.hidden = wtoken.hiddenRequested = !visible;
   4241             if (!visible) {
   4242                 unsetAppFreezingScreenLocked(wtoken, true, true);
   4243             } else {
   4244                 // If we are being set visible, and the starting window is
   4245                 // not yet displayed, then make sure it doesn't get displayed.
   4246                 WindowState swin = wtoken.startingWindow;
   4247                 if (swin != null && !swin.isDrawnLw()) {
   4248                     swin.mPolicyVisibility = false;
   4249                     swin.mPolicyVisibilityAfterAnim = false;
   4250                  }
   4251             }
   4252 
   4253             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
   4254                       + ": hidden=" + wtoken.hidden + " hiddenRequested="
   4255                       + wtoken.hiddenRequested);
   4256 
   4257             if (changed) {
   4258                 mInputMonitor.setUpdateInputWindowsNeededLw();
   4259                 if (performLayout) {
   4260                     updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
   4261                             false /*updateInputWindows*/);
   4262                     performLayoutAndPlaceSurfacesLocked();
   4263                 }
   4264                 mInputMonitor.updateInputWindowsLw(false /*force*/);
   4265             }
   4266         }
   4267 
   4268         if (wtoken.mAppAnimator.animation != null) {
   4269             delayed = true;
   4270         }
   4271 
   4272         for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
   4273             if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) {
   4274                 delayed = true;
   4275             }
   4276         }
   4277 
   4278         return delayed;
   4279     }
   4280 
   4281     @Override
   4282     public void setAppVisibility(IBinder token, boolean visible) {
   4283         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   4284                 "setAppVisibility()")) {
   4285             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   4286         }
   4287 
   4288         AppWindowToken wtoken;
   4289 
   4290         synchronized(mWindowMap) {
   4291             wtoken = findAppWindowToken(token);
   4292             if (wtoken == null) {
   4293                 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
   4294                 return;
   4295             }
   4296 
   4297             if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
   4298                 RuntimeException e = null;
   4299                 if (!HIDE_STACK_CRAWLS) {
   4300                     e = new RuntimeException();
   4301                     e.fillInStackTrace();
   4302                 }
   4303                 Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible
   4304                         + "): " + mAppTransition
   4305                         + " hidden=" + wtoken.hidden
   4306                         + " hiddenRequested=" + wtoken.hiddenRequested, e);
   4307             }
   4308 
   4309             // If we are preparing an app transition, then delay changing
   4310             // the visibility of this token until we execute that transition.
   4311             if (okToDisplay() && mAppTransition.isTransitionSet()) {
   4312                 wtoken.hiddenRequested = !visible;
   4313 
   4314                 if (!wtoken.startingDisplayed) {
   4315                     if (DEBUG_APP_TRANSITIONS) Slog.v(
   4316                             TAG, "Setting dummy animation on: " + wtoken);
   4317                     wtoken.mAppAnimator.setDummyAnimation();
   4318                 }
   4319                 mOpeningApps.remove(wtoken);
   4320                 mClosingApps.remove(wtoken);
   4321                 wtoken.waitingToShow = wtoken.waitingToHide = false;
   4322                 wtoken.inPendingTransaction = true;
   4323                 if (visible) {
   4324                     mOpeningApps.add(wtoken);
   4325                     wtoken.startingMoved = false;
   4326 
   4327                     // If the token is currently hidden (should be the
   4328                     // common case), then we need to set up to wait for
   4329                     // its windows to be ready.
   4330                     if (wtoken.hidden) {
   4331                         wtoken.allDrawn = false;
   4332                         wtoken.deferClearAllDrawn = false;
   4333                         wtoken.waitingToShow = true;
   4334 
   4335                         if (wtoken.clientHidden) {
   4336                             // In the case where we are making an app visible
   4337                             // but holding off for a transition, we still need
   4338                             // to tell the client to make its windows visible so
   4339                             // they get drawn.  Otherwise, we will wait on
   4340                             // performing the transition until all windows have
   4341                             // been drawn, they never will be, and we are sad.
   4342                             wtoken.clientHidden = false;
   4343                             wtoken.sendAppVisibilityToClients();
   4344                         }
   4345                     }
   4346                 } else {
   4347                     mClosingApps.add(wtoken);
   4348 
   4349                     // If the token is currently visible (should be the
   4350                     // common case), then set up to wait for it to be hidden.
   4351                     if (!wtoken.hidden) {
   4352                         wtoken.waitingToHide = true;
   4353                     }
   4354                 }
   4355                 return;
   4356             }
   4357 
   4358             final long origId = Binder.clearCallingIdentity();
   4359             setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
   4360                     true);
   4361             wtoken.updateReportedVisibilityLocked();
   4362             Binder.restoreCallingIdentity(origId);
   4363         }
   4364     }
   4365 
   4366     void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
   4367             boolean unfreezeSurfaceNow, boolean force) {
   4368         if (wtoken.mAppAnimator.freezingScreen) {
   4369             if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
   4370                     + " force=" + force);
   4371             final int N = wtoken.allAppWindows.size();
   4372             boolean unfrozeWindows = false;
   4373             for (int i=0; i<N; i++) {
   4374                 WindowState w = wtoken.allAppWindows.get(i);
   4375                 if (w.mAppFreezing) {
   4376                     w.mAppFreezing = false;
   4377                     if (w.mHasSurface && !w.mOrientationChanging) {
   4378                         if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w);
   4379                         w.mOrientationChanging = true;
   4380                         mInnerFields.mOrientationChangeComplete = false;
   4381                     }
   4382                     w.mLastFreezeDuration = 0;
   4383                     unfrozeWindows = true;
   4384                     w.mDisplayContent.layoutNeeded = true;
   4385                 }
   4386             }
   4387             if (force || unfrozeWindows) {
   4388                 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
   4389                 wtoken.mAppAnimator.freezingScreen = false;
   4390                 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime()
   4391                         - mDisplayFreezeTime);
   4392                 mAppsFreezingScreen--;
   4393                 mLastFinishedFreezeSource = wtoken;
   4394             }
   4395             if (unfreezeSurfaceNow) {
   4396                 if (unfrozeWindows) {
   4397                     performLayoutAndPlaceSurfacesLocked();
   4398                 }
   4399                 stopFreezingDisplayLocked();
   4400             }
   4401         }
   4402     }
   4403 
   4404     public void startAppFreezingScreenLocked(AppWindowToken wtoken,
   4405             int configChanges) {
   4406         if (DEBUG_ORIENTATION) {
   4407             RuntimeException e = null;
   4408             if (!HIDE_STACK_CRAWLS) {
   4409                 e = new RuntimeException();
   4410                 e.fillInStackTrace();
   4411             }
   4412             Slog.i(TAG, "Set freezing of " + wtoken.appToken
   4413                     + ": hidden=" + wtoken.hidden + " freezing="
   4414                     + wtoken.mAppAnimator.freezingScreen, e);
   4415         }
   4416         if (!wtoken.hiddenRequested) {
   4417             if (!wtoken.mAppAnimator.freezingScreen) {
   4418                 wtoken.mAppAnimator.freezingScreen = true;
   4419                 wtoken.mAppAnimator.lastFreezeDuration = 0;
   4420                 mAppsFreezingScreen++;
   4421                 if (mAppsFreezingScreen == 1) {
   4422                     startFreezingDisplayLocked(false, 0, 0);
   4423                     mH.removeMessages(H.APP_FREEZE_TIMEOUT);
   4424                     mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000);
   4425                 }
   4426             }
   4427             final int N = wtoken.allAppWindows.size();
   4428             for (int i=0; i<N; i++) {
   4429                 WindowState w = wtoken.allAppWindows.get(i);
   4430                 w.mAppFreezing = true;
   4431             }
   4432         }
   4433     }
   4434 
   4435     @Override
   4436     public void startAppFreezingScreen(IBinder token, int configChanges) {
   4437         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   4438                 "setAppFreezingScreen()")) {
   4439             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   4440         }
   4441 
   4442         synchronized(mWindowMap) {
   4443             if (configChanges == 0 && okToDisplay()) {
   4444                 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
   4445                 return;
   4446             }
   4447 
   4448             AppWindowToken wtoken = findAppWindowToken(token);
   4449             if (wtoken == null || wtoken.appToken == null) {
   4450                 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
   4451                 return;
   4452             }
   4453             final long origId = Binder.clearCallingIdentity();
   4454             startAppFreezingScreenLocked(wtoken, configChanges);
   4455             Binder.restoreCallingIdentity(origId);
   4456         }
   4457     }
   4458 
   4459     @Override
   4460     public void stopAppFreezingScreen(IBinder token, boolean force) {
   4461         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   4462                 "setAppFreezingScreen()")) {
   4463             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   4464         }
   4465 
   4466         synchronized(mWindowMap) {
   4467             AppWindowToken wtoken = findAppWindowToken(token);
   4468             if (wtoken == null || wtoken.appToken == null) {
   4469                 return;
   4470             }
   4471             final long origId = Binder.clearCallingIdentity();
   4472             if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
   4473                     + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
   4474             unsetAppFreezingScreenLocked(wtoken, true, force);
   4475             Binder.restoreCallingIdentity(origId);
   4476         }
   4477     }
   4478 
   4479     @Override
   4480     public void removeAppToken(IBinder token) {
   4481         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   4482                 "removeAppToken()")) {
   4483             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   4484         }
   4485 
   4486         AppWindowToken wtoken = null;
   4487         AppWindowToken startingToken = null;
   4488         boolean delayed = false;
   4489 
   4490         final long origId = Binder.clearCallingIdentity();
   4491         synchronized(mWindowMap) {
   4492             WindowToken basewtoken = mTokenMap.remove(token);
   4493             if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
   4494                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
   4495                 delayed = setTokenVisibilityLocked(wtoken, null, false,
   4496                         AppTransition.TRANSIT_UNSET, true);
   4497                 wtoken.inPendingTransaction = false;
   4498                 mOpeningApps.remove(wtoken);
   4499                 wtoken.waitingToShow = false;
   4500                 if (mClosingApps.contains(wtoken)) {
   4501                     delayed = true;
   4502                 } else if (mAppTransition.isTransitionSet()) {
   4503                     mClosingApps.add(wtoken);
   4504                     wtoken.waitingToHide = true;
   4505                     delayed = true;
   4506                 }
   4507                 if (DEBUG_APP_TRANSITIONS) Slog.v(
   4508                         TAG, "Removing app " + wtoken + " delayed=" + delayed
   4509                         + " animation=" + wtoken.mAppAnimator.animation
   4510                         + " animating=" + wtoken.mAppAnimator.animating);
   4511                 final Task task = mTaskIdToTask.get(wtoken.groupId);
   4512                 DisplayContent displayContent = task.getDisplayContent();
   4513                 if (delayed) {
   4514                     // set the token aside because it has an active animation to be finished
   4515                     if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
   4516                             "removeAppToken make exiting: " + wtoken);
   4517                     displayContent.mExitingAppTokens.add(wtoken);
   4518                 } else {
   4519                     // Make sure there is no animation running on this token,
   4520                     // so any windows associated with it will be removed as
   4521                     // soon as their animations are complete
   4522                     wtoken.mAppAnimator.clearAnimation();
   4523                     wtoken.mAppAnimator.animating = false;
   4524                 }
   4525                 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
   4526                         "removeAppToken: " + wtoken);
   4527 
   4528                 if (task.removeAppToken(wtoken)) {
   4529                     mTaskIdToTask.delete(wtoken.groupId);
   4530                 }
   4531                 wtoken.removed = true;
   4532                 if (wtoken.startingData != null) {
   4533                     startingToken = wtoken;
   4534                 }
   4535                 unsetAppFreezingScreenLocked(wtoken, true, true);
   4536                 if (mFocusedApp == wtoken) {
   4537                     if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken);
   4538                     mFocusedApp = null;
   4539                     updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
   4540                     mInputMonitor.setFocusedAppLw(null);
   4541                 }
   4542             } else {
   4543                 Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
   4544             }
   4545 
   4546             if (!delayed && wtoken != null) {
   4547                 wtoken.updateReportedVisibilityLocked();
   4548             }
   4549         }
   4550         Binder.restoreCallingIdentity(origId);
   4551 
   4552         // Will only remove if startingToken non null.
   4553         scheduleRemoveStartingWindow(startingToken);
   4554     }
   4555 
   4556     void removeStartingWindowTimeout(AppWindowToken wtoken) {
   4557         if (wtoken != null) {
   4558             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
   4559                     ": Remove starting window timeout " + wtoken + (wtoken != null ?
   4560                     " startingWindow=" + wtoken.startingWindow : ""));
   4561             mH.removeMessages(H.REMOVE_STARTING_TIMEOUT, wtoken);
   4562         }
   4563     }
   4564 
   4565     void scheduleRemoveStartingWindow(AppWindowToken wtoken) {
   4566         if (wtoken != null && wtoken.startingWindow != null) {
   4567             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
   4568                     ": Schedule remove starting " + wtoken + (wtoken != null ?
   4569                     " startingWindow=" + wtoken.startingWindow : ""));
   4570             removeStartingWindowTimeout(wtoken);
   4571             Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
   4572             mH.sendMessage(m);
   4573         }
   4574     }
   4575     private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
   4576         final int NW = token.windows.size();
   4577         if (NW > 0) {
   4578             mWindowsChanged = true;
   4579         }
   4580         for (int i=0; i<NW; i++) {
   4581             WindowState win = token.windows.get(i);
   4582             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
   4583             win.getWindowList().remove(win);
   4584             int j = win.mChildWindows.size();
   4585             while (j > 0) {
   4586                 j--;
   4587                 WindowState cwin = win.mChildWindows.get(j);
   4588                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
   4589                         "Tmp removing child window " + cwin);
   4590                 cwin.getWindowList().remove(cwin);
   4591             }
   4592         }
   4593         return NW > 0;
   4594     }
   4595 
   4596     void dumpAppTokensLocked() {
   4597         final int numDisplays = mDisplayContents.size();
   4598         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   4599             final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
   4600             Slog.v(TAG, "  Display " + displayContent.getDisplayId());
   4601             final ArrayList<Task> tasks = displayContent.getTasks();
   4602             int i = displayContent.numTokens();
   4603             for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
   4604                 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
   4605                 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
   4606                     final AppWindowToken wtoken = tokens.get(tokenNdx);
   4607                     Slog.v(TAG, "  #" + --i + ": " + wtoken.token);
   4608                 }
   4609             }
   4610         }
   4611     }
   4612 
   4613     void dumpWindowsLocked() {
   4614         int i = 0;
   4615         final int numDisplays = mDisplayContents.size();
   4616         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   4617             final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
   4618             for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
   4619                 Slog.v(TAG, "  #" + i++ + ": " + windows.get(winNdx));
   4620             }
   4621         }
   4622     }
   4623 
   4624     private int findAppWindowInsertionPointLocked(AppWindowToken target) {
   4625         final int taskId = target.groupId;
   4626         Task targetTask = mTaskIdToTask.get(taskId);
   4627         if (targetTask == null) {
   4628             Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId="
   4629                     + taskId);
   4630             return 0;
   4631         }
   4632         DisplayContent displayContent = targetTask.getDisplayContent();
   4633         if (displayContent == null) {
   4634             Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target);
   4635             return 0;
   4636         }
   4637         final WindowList windows = displayContent.getWindowList();
   4638         final int NW = windows.size();
   4639 
   4640         boolean found = false;
   4641         final ArrayList<Task> tasks = displayContent.getTasks();
   4642         for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
   4643             final Task task = tasks.get(taskNdx);
   4644             if (!found && task.taskId != taskId) {
   4645                 continue;
   4646             }
   4647             AppTokenList tokens = task.mAppTokens;
   4648             for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
   4649                 final AppWindowToken wtoken = tokens.get(tokenNdx);
   4650                 if (!found && wtoken == target) {
   4651                     found = true;
   4652                 }
   4653                 if (found) {
   4654                     // Find the first app token below the new position that has
   4655                     // a window displayed.
   4656                     if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token);
   4657                     if (wtoken.sendingToBottom) {
   4658                         if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom");
   4659                         continue;
   4660                     }
   4661                     for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
   4662                         WindowState win = wtoken.windows.get(i);
   4663                         for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
   4664                             WindowState cwin = win.mChildWindows.get(j);
   4665                             if (cwin.mSubLayer >= 0) {
   4666                                 for (int pos = NW - 1; pos >= 0; pos--) {
   4667                                     if (windows.get(pos) == cwin) {
   4668                                         if (DEBUG_REORDER) Slog.v(TAG,
   4669                                                 "Found child win @" + (pos + 1));
   4670                                         return pos + 1;
   4671                                     }
   4672                                 }
   4673                             }
   4674                         }
   4675                         for (int pos = NW - 1; pos >= 0; pos--) {
   4676                             if (windows.get(pos) == win) {
   4677                                 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1));
   4678                                 return pos + 1;
   4679                             }
   4680                         }
   4681                     }
   4682                 }
   4683             }
   4684         }
   4685         // Never put an app window underneath wallpaper.
   4686         for (int pos = NW - 1; pos >= 0; pos--) {
   4687             if (windows.get(pos).mIsWallpaper) {
   4688                 if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos);
   4689                 return pos + 1;
   4690             }
   4691         }
   4692         return 0;
   4693     }
   4694 
   4695     private final int reAddWindowLocked(int index, WindowState win) {
   4696         final WindowList windows = win.getWindowList();
   4697         final int NCW = win.mChildWindows.size();
   4698         boolean added = false;
   4699         for (int j=0; j<NCW; j++) {
   4700             WindowState cwin = win.mChildWindows.get(j);
   4701             if (!added && cwin.mSubLayer >= 0) {
   4702                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
   4703                         + index + ": " + cwin);
   4704                 win.mRebuilding = false;
   4705                 windows.add(index, win);
   4706                 index++;
   4707                 added = true;
   4708             }
   4709             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
   4710                     + index + ": " + cwin);
   4711             cwin.mRebuilding = false;
   4712             windows.add(index, cwin);
   4713             index++;
   4714         }
   4715         if (!added) {
   4716             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
   4717                     + index + ": " + win);
   4718             win.mRebuilding = false;
   4719             windows.add(index, win);
   4720             index++;
   4721         }
   4722         mWindowsChanged = true;
   4723         return index;
   4724     }
   4725 
   4726     private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index,
   4727                                             WindowToken token) {
   4728         final int NW = token.windows.size();
   4729         for (int i=0; i<NW; i++) {
   4730             final WindowState win = token.windows.get(i);
   4731             if (win.mDisplayContent == displayContent) {
   4732                 index = reAddWindowLocked(index, win);
   4733             }
   4734         }
   4735         return index;
   4736     }
   4737 
   4738     void moveStackWindowsLocked(DisplayContent displayContent) {
   4739         // First remove all of the windows from the list.
   4740         final ArrayList<Task> tasks = displayContent.getTasks();
   4741         final int numTasks = tasks.size();
   4742         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
   4743             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
   4744             final int numTokens = tokens.size();
   4745             for (int tokenNdx = numTokens - 1; tokenNdx >= 0; --tokenNdx) {
   4746                 tmpRemoveAppWindowsLocked(tokens.get(tokenNdx));
   4747             }
   4748         }
   4749 
   4750         // And now add them back at the correct place.
   4751         // Where to start adding?
   4752         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
   4753             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
   4754             int pos = findAppWindowInsertionPointLocked(tokens.get(0));
   4755             final int numTokens = tokens.size();
   4756             for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
   4757                 final AppWindowToken wtoken = tokens.get(tokenNdx);
   4758                 if (wtoken != null) {
   4759                     final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
   4760                     if (newPos != pos) {
   4761                         displayContent.layoutNeeded = true;
   4762                     }
   4763                     pos = newPos;
   4764                 }
   4765             }
   4766         }
   4767 
   4768         if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
   4769                 false /*updateInputWindows*/)) {
   4770             assignLayersLocked(displayContent.getWindowList());
   4771         }
   4772 
   4773         mInputMonitor.setUpdateInputWindowsNeededLw();
   4774         performLayoutAndPlaceSurfacesLocked();
   4775         mInputMonitor.updateInputWindowsLw(false /*force*/);
   4776 
   4777         //dump();
   4778     }
   4779 
   4780     public void moveTaskToTop(int taskId) {
   4781         final long origId = Binder.clearCallingIdentity();
   4782         try {
   4783             synchronized(mWindowMap) {
   4784                 Task task = mTaskIdToTask.get(taskId);
   4785                 if (task == null) {
   4786                     // Normal behavior, addAppToken will be called next and task will be created.
   4787                     return;
   4788                 }
   4789                 final TaskStack stack = task.mStack;
   4790                 final DisplayContent displayContent = task.getDisplayContent();
   4791                 final boolean isHomeStackTask = stack.isHomeStack();
   4792                 if (isHomeStackTask != displayContent.homeOnTop()) {
   4793                     // First move the stack itself.
   4794                     displayContent.moveHomeStackBox(isHomeStackTask);
   4795                 }
   4796                 stack.moveTaskToTop(task);
   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.getDisplayContent());
   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                     performLayoutAndPlaceSurfacesLocked();
   4851                     return;
   4852                 }
   4853             }
   4854             Slog.e(TAG, "createStack: Unable to find relativeStackBoxId=" + relativeStackBoxId);
   4855         }
   4856     }
   4857 
   4858     public int removeStack(int stackId) {
   4859         synchronized (mWindowMap) {
   4860             final TaskStack stack = mStackIdToStack.get(stackId);
   4861             if (stack != null) {
   4862                 mStackIdToStack.delete(stackId);
   4863                 int nextStackId = stack.remove();
   4864                 stack.getDisplayContent().layoutNeeded = true;
   4865                 requestTraversalLocked();
   4866                 return nextStackId;
   4867             }
   4868             if (DEBUG_STACK) Slog.i(TAG, "removeStack: could not find stackId=" + stackId);
   4869         }
   4870         return HOME_STACK_ID;
   4871     }
   4872 
   4873     public void removeTask(int taskId) {
   4874         synchronized (mWindowMap) {
   4875             Task task = mTaskIdToTask.get(taskId);
   4876             if (task == null) {
   4877                 if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId);
   4878                 return;
   4879             }
   4880             final TaskStack stack = task.mStack;
   4881             EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask");
   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 (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         final long ident = Binder.clearCallingIdentity();
   7640         try {
   7641             synchronized(mWindowMap) {
   7642                 // Set some sort of reasonable bounds on the size of the display that we
   7643                 // will try to emulate.
   7644                 final int MIN_WIDTH = 200;
   7645                 final int MIN_HEIGHT = 200;
   7646                 final int MAX_SCALE = 2;
   7647                 final DisplayContent displayContent = getDisplayContentLocked(displayId);
   7648                 if (displayContent != null) {
   7649                     width = Math.min(Math.max(width, MIN_WIDTH),
   7650                             displayContent.mInitialDisplayWidth * MAX_SCALE);
   7651                     height = Math.min(Math.max(height, MIN_HEIGHT),
   7652                             displayContent.mInitialDisplayHeight * MAX_SCALE);
   7653                     setForcedDisplaySizeLocked(displayContent, width, height);
   7654                     Settings.Global.putString(mContext.getContentResolver(),
   7655                             Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
   7656                 }
   7657             }
   7658         } finally {
   7659             Binder.restoreCallingIdentity(ident);
   7660         }
   7661     }
   7662 
   7663     private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
   7664         String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
   7665                 Settings.Global.DISPLAY_SIZE_FORCED);
   7666         if (sizeStr == null || sizeStr.length() == 0) {
   7667             sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
   7668         }
   7669         if (sizeStr != null && sizeStr.length() > 0) {
   7670             final int pos = sizeStr.indexOf(',');
   7671             if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
   7672                 int width, height;
   7673                 try {
   7674                     width = Integer.parseInt(sizeStr.substring(0, pos));
   7675                     height = Integer.parseInt(sizeStr.substring(pos+1));
   7676                     synchronized(displayContent.mDisplaySizeLock) {
   7677                         if (displayContent.mBaseDisplayWidth != width
   7678                                 || displayContent.mBaseDisplayHeight != height) {
   7679                             Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
   7680                             displayContent.mBaseDisplayWidth = width;
   7681                             displayContent.mBaseDisplayHeight = height;
   7682                         }
   7683                     }
   7684                 } catch (NumberFormatException ex) {
   7685                 }
   7686             }
   7687         }
   7688         String densityStr = Settings.Global.getString(mContext.getContentResolver(),
   7689                 Settings.Global.DISPLAY_DENSITY_FORCED);
   7690         if (densityStr == null || densityStr.length() == 0) {
   7691             densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
   7692         }
   7693         if (densityStr != null && densityStr.length() > 0) {
   7694             int density;
   7695             try {
   7696                 density = Integer.parseInt(densityStr);
   7697                 synchronized(displayContent.mDisplaySizeLock) {
   7698                     if (displayContent.mBaseDisplayDensity != density) {
   7699                         Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
   7700                         displayContent.mBaseDisplayDensity = density;
   7701                     }
   7702                 }
   7703             } catch (NumberFormatException ex) {
   7704             }
   7705         }
   7706     }
   7707 
   7708     // displayContent must not be null
   7709     private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
   7710         Slog.i(TAG, "Using new display size: " + width + "x" + height);
   7711 
   7712         synchronized(displayContent.mDisplaySizeLock) {
   7713             displayContent.mBaseDisplayWidth = width;
   7714             displayContent.mBaseDisplayHeight = height;
   7715         }
   7716         reconfigureDisplayLocked(displayContent);
   7717     }
   7718 
   7719     @Override
   7720     public void clearForcedDisplaySize(int displayId) {
   7721         if (mContext.checkCallingOrSelfPermission(
   7722                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
   7723                 PackageManager.PERMISSION_GRANTED) {
   7724             throw new SecurityException("Must hold permission " +
   7725                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
   7726         }
   7727         if (displayId != Display.DEFAULT_DISPLAY) {
   7728             throw new IllegalArgumentException("Can only set the default display");
   7729         }
   7730         final long ident = Binder.clearCallingIdentity();
   7731         try {
   7732             synchronized(mWindowMap) {
   7733                 final DisplayContent displayContent = getDisplayContentLocked(displayId);
   7734                 if (displayContent != null) {
   7735                     setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
   7736                             displayContent.mInitialDisplayHeight);
   7737                     Settings.Global.putString(mContext.getContentResolver(),
   7738                             Settings.Global.DISPLAY_SIZE_FORCED, "");
   7739                 }
   7740             }
   7741         } finally {
   7742             Binder.restoreCallingIdentity(ident);
   7743         }
   7744     }
   7745 
   7746     @Override
   7747     public int getInitialDisplayDensity(int displayId) {
   7748         synchronized (mWindowMap) {
   7749             final DisplayContent displayContent = getDisplayContentLocked(displayId);
   7750             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
   7751                 synchronized(displayContent.mDisplaySizeLock) {
   7752                     return displayContent.mInitialDisplayDensity;
   7753                 }
   7754             }
   7755         }
   7756         return -1;
   7757     }
   7758 
   7759     @Override
   7760     public int getBaseDisplayDensity(int displayId) {
   7761         synchronized (mWindowMap) {
   7762             final DisplayContent displayContent = getDisplayContentLocked(displayId);
   7763             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
   7764                 synchronized(displayContent.mDisplaySizeLock) {
   7765                     return displayContent.mBaseDisplayDensity;
   7766                 }
   7767             }
   7768         }
   7769         return -1;
   7770     }
   7771 
   7772     @Override
   7773     public void setForcedDisplayDensity(int displayId, int density) {
   7774         if (mContext.checkCallingOrSelfPermission(
   7775                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
   7776                 PackageManager.PERMISSION_GRANTED) {
   7777             throw new SecurityException("Must hold permission " +
   7778                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
   7779         }
   7780         if (displayId != Display.DEFAULT_DISPLAY) {
   7781             throw new IllegalArgumentException("Can only set the default display");
   7782         }
   7783         final long ident = Binder.clearCallingIdentity();
   7784         try {
   7785             synchronized(mWindowMap) {
   7786                 final DisplayContent displayContent = getDisplayContentLocked(displayId);
   7787                 if (displayContent != null) {
   7788                     setForcedDisplayDensityLocked(displayContent, density);
   7789                     Settings.Global.putString(mContext.getContentResolver(),
   7790                             Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
   7791                 }
   7792             }
   7793         } finally {
   7794             Binder.restoreCallingIdentity(ident);
   7795         }
   7796     }
   7797 
   7798     // displayContent must not be null
   7799     private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
   7800         Slog.i(TAG, "Using new display density: " + density);
   7801 
   7802         synchronized(displayContent.mDisplaySizeLock) {
   7803             displayContent.mBaseDisplayDensity = density;
   7804         }
   7805         reconfigureDisplayLocked(displayContent);
   7806     }
   7807 
   7808     @Override
   7809     public void clearForcedDisplayDensity(int displayId) {
   7810         if (mContext.checkCallingOrSelfPermission(
   7811                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
   7812                 PackageManager.PERMISSION_GRANTED) {
   7813             throw new SecurityException("Must hold permission " +
   7814                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
   7815         }
   7816         if (displayId != Display.DEFAULT_DISPLAY) {
   7817             throw new IllegalArgumentException("Can only set the default display");
   7818         }
   7819         final long ident = Binder.clearCallingIdentity();
   7820         try {
   7821             synchronized(mWindowMap) {
   7822                 final DisplayContent displayContent = getDisplayContentLocked(displayId);
   7823                 if (displayContent != null) {
   7824                     setForcedDisplayDensityLocked(displayContent,
   7825                             displayContent.mInitialDisplayDensity);
   7826                     Settings.Global.putString(mContext.getContentResolver(),
   7827                             Settings.Global.DISPLAY_DENSITY_FORCED, "");
   7828                 }
   7829             }
   7830         } finally {
   7831             Binder.restoreCallingIdentity(ident);
   7832         }
   7833     }
   7834 
   7835     // displayContent must not be null
   7836     private void reconfigureDisplayLocked(DisplayContent displayContent) {
   7837         // TODO: Multidisplay: for now only use with default display.
   7838         configureDisplayPolicyLocked(displayContent);
   7839         displayContent.layoutNeeded = true;
   7840 
   7841         boolean configChanged = updateOrientationFromAppTokensLocked(false);
   7842         mTempConfiguration.setToDefaults();
   7843         mTempConfiguration.fontScale = mCurConfiguration.fontScale;
   7844         if (computeScreenConfigurationLocked(mTempConfiguration)) {
   7845             if (mCurConfiguration.diff(mTempConfiguration) != 0) {
   7846                 configChanged = true;
   7847             }
   7848         }
   7849 
   7850         if (configChanged) {
   7851             mWaitingForConfig = true;
   7852             startFreezingDisplayLocked(false, 0, 0);
   7853             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
   7854         }
   7855 
   7856         performLayoutAndPlaceSurfacesLocked();
   7857     }
   7858 
   7859     private void configureDisplayPolicyLocked(DisplayContent displayContent) {
   7860         mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
   7861                 displayContent.mBaseDisplayWidth,
   7862                 displayContent.mBaseDisplayHeight,
   7863                 displayContent.mBaseDisplayDensity);
   7864 
   7865         DisplayInfo displayInfo = displayContent.getDisplayInfo();
   7866         mPolicy.setDisplayOverscan(displayContent.getDisplay(),
   7867                 displayInfo.overscanLeft, displayInfo.overscanTop,
   7868                 displayInfo.overscanRight, displayInfo.overscanBottom);
   7869     }
   7870 
   7871     @Override
   7872     public void setOverscan(int displayId, int left, int top, int right, int bottom) {
   7873         if (mContext.checkCallingOrSelfPermission(
   7874                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
   7875                 PackageManager.PERMISSION_GRANTED) {
   7876             throw new SecurityException("Must hold permission " +
   7877                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
   7878         }
   7879         final long ident = Binder.clearCallingIdentity();
   7880         try {
   7881             synchronized(mWindowMap) {
   7882                 DisplayContent displayContent = getDisplayContentLocked(displayId);
   7883                 if (displayContent != null) {
   7884                     setOverscanLocked(displayContent, left, top, right, bottom);
   7885                 }
   7886             }
   7887         } finally {
   7888             Binder.restoreCallingIdentity(ident);
   7889         }
   7890     }
   7891 
   7892     private void setOverscanLocked(DisplayContent displayContent,
   7893             int left, int top, int right, int bottom) {
   7894         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
   7895         synchronized (displayContent.mDisplaySizeLock) {
   7896             displayInfo.overscanLeft = left;
   7897             displayInfo.overscanTop = top;
   7898             displayInfo.overscanRight = right;
   7899             displayInfo.overscanBottom = bottom;
   7900         }
   7901 
   7902         mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom);
   7903         mDisplaySettings.writeSettingsLocked();
   7904 
   7905         reconfigureDisplayLocked(displayContent);
   7906     }
   7907 
   7908     // -------------------------------------------------------------
   7909     // Internals
   7910     // -------------------------------------------------------------
   7911 
   7912     final WindowState windowForClientLocked(Session session, IWindow client,
   7913             boolean throwOnError) {
   7914         return windowForClientLocked(session, client.asBinder(), throwOnError);
   7915     }
   7916 
   7917     final WindowState windowForClientLocked(Session session, IBinder client,
   7918             boolean throwOnError) {
   7919         WindowState win = mWindowMap.get(client);
   7920         if (localLOGV) Slog.v(
   7921             TAG, "Looking up client " + client + ": " + win);
   7922         if (win == null) {
   7923             RuntimeException ex = new IllegalArgumentException(
   7924                     "Requested window " + client + " does not exist");
   7925             if (throwOnError) {
   7926                 throw ex;
   7927             }
   7928             Slog.w(TAG, "Failed looking up window", ex);
   7929             return null;
   7930         }
   7931         if (session != null && win.mSession != session) {
   7932             RuntimeException ex = new IllegalArgumentException(
   7933                     "Requested window " + client + " is in session " +
   7934                     win.mSession + ", not " + session);
   7935             if (throwOnError) {
   7936                 throw ex;
   7937             }
   7938             Slog.w(TAG, "Failed looking up window", ex);
   7939             return null;
   7940         }
   7941 
   7942         return win;
   7943     }
   7944 
   7945     final void rebuildAppWindowListLocked() {
   7946         // TODO: Multidisplay, when ActivityStacks and tasks exist on more than one display.
   7947         rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
   7948     }
   7949 
   7950     private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
   7951         final WindowList windows = displayContent.getWindowList();
   7952         int NW = windows.size();
   7953         int i;
   7954         int lastBelow = -1;
   7955         int numRemoved = 0;
   7956 
   7957         if (mRebuildTmp.length < NW) {
   7958             mRebuildTmp = new WindowState[NW+10];
   7959         }
   7960 
   7961         // First remove all existing app windows.
   7962         i=0;
   7963         while (i < NW) {
   7964             WindowState w = windows.get(i);
   7965             if (w.mAppToken != null) {
   7966                 WindowState win = windows.remove(i);
   7967                 win.mRebuilding = true;
   7968                 mRebuildTmp[numRemoved] = win;
   7969                 mWindowsChanged = true;
   7970                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win);
   7971                 NW--;
   7972                 numRemoved++;
   7973                 continue;
   7974             } else if (lastBelow == i-1) {
   7975                 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
   7976                     lastBelow = i;
   7977                 }
   7978             }
   7979             i++;
   7980         }
   7981 
   7982         // Keep whatever windows were below the app windows still below,
   7983         // by skipping them.
   7984         lastBelow++;
   7985         i = lastBelow;
   7986 
   7987         // First add all of the exiting app tokens...  these are no longer
   7988         // in the main app list, but still have windows shown.  We put them
   7989         // in the back because now that the animation is over we no longer
   7990         // will care about them.
   7991         AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
   7992         int NT = exitingAppTokens.size();
   7993         for (int j=0; j<NT; j++) {
   7994             i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
   7995         }
   7996 
   7997         // And add in the still active app tokens in Z order.
   7998         final ArrayList<Task> tasks = displayContent.getTasks();
   7999         final int numTasks = tasks.size();
   8000         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
   8001             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
   8002             final int numTokens = tokens.size();
   8003             for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
   8004                 final AppWindowToken wtoken = tokens.get(tokenNdx);
   8005                 i = reAddAppWindowsLocked(displayContent, i, wtoken);
   8006             }
   8007         }
   8008 
   8009         i -= lastBelow;
   8010         if (i != numRemoved) {
   8011             Slog.w(TAG, "Rebuild removed " + numRemoved + " windows but added " + i,
   8012                     new RuntimeException("here").fillInStackTrace());
   8013             for (i=0; i<numRemoved; i++) {
   8014                 WindowState ws = mRebuildTmp[i];
   8015                 if (ws.mRebuilding) {
   8016                     StringWriter sw = new StringWriter();
   8017                     PrintWriter pw = new FastPrintWriter(sw, false, 1024);
   8018                     ws.dump(pw, "", true);
   8019                     pw.flush();
   8020                     Slog.w(TAG, "This window was lost: " + ws);
   8021                     Slog.w(TAG, sw.toString());
   8022                     ws.mWinAnimator.destroySurfaceLocked();
   8023                 }
   8024             }
   8025             Slog.w(TAG, "Current app token list:");
   8026             dumpAppTokensLocked();
   8027             Slog.w(TAG, "Final window list:");
   8028             dumpWindowsLocked();
   8029         }
   8030     }
   8031 
   8032     private final void assignLayersLocked(WindowList windows) {
   8033         int N = windows.size();
   8034         int curBaseLayer = 0;
   8035         int curLayer = 0;
   8036         int i;
   8037 
   8038         if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows,
   8039                 new RuntimeException("here").fillInStackTrace());
   8040 
   8041         boolean anyLayerChanged = false;
   8042 
   8043         for (i=0; i<N; i++) {
   8044             final WindowState w = windows.get(i);
   8045             final WindowStateAnimator winAnimator = w.mWinAnimator;
   8046             boolean layerChanged = false;
   8047             int oldLayer = w.mLayer;
   8048             if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
   8049                     || (i > 0 && w.mIsWallpaper)) {
   8050                 curLayer += WINDOW_LAYER_MULTIPLIER;
   8051                 w.mLayer = curLayer;
   8052             } else {
   8053                 curBaseLayer = curLayer = w.mBaseLayer;
   8054                 w.mLayer = curLayer;
   8055             }
   8056             if (w.mLayer != oldLayer) {
   8057                 layerChanged = true;
   8058                 anyLayerChanged = true;
   8059             }
   8060             final AppWindowToken wtoken = w.mAppToken;
   8061             oldLayer = winAnimator.mAnimLayer;
   8062             if (w.mTargetAppToken != null) {
   8063                 winAnimator.mAnimLayer =
   8064                         w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
   8065             } else if (wtoken != null) {
   8066                 winAnimator.mAnimLayer =
   8067                         w.mLayer + wtoken.mAppAnimator.animLayerAdjustment;
   8068             } else {
   8069                 winAnimator.mAnimLayer = w.mLayer;
   8070             }
   8071             if (w.mIsImWindow) {
   8072                 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
   8073             } else if (w.mIsWallpaper) {
   8074                 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
   8075             }
   8076             if (winAnimator.mAnimLayer != oldLayer) {
   8077                 layerChanged = true;
   8078                 anyLayerChanged = true;
   8079             }
   8080             if (layerChanged && w.getStack().isDimming(winAnimator)) {
   8081                 // Force an animation pass just to update the mDimLayer layer.
   8082                 scheduleAnimationLocked();
   8083             }
   8084             if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
   8085                     + "mBase=" + w.mBaseLayer
   8086                     + " mLayer=" + w.mLayer
   8087                     + (wtoken == null ?
   8088                             "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment)
   8089                     + " =mAnimLayer=" + winAnimator.mAnimLayer);
   8090             //System.out.println(
   8091             //    "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
   8092         }
   8093 
   8094         //TODO (multidisplay): Magnification is supported only for the default display.
   8095         if (mDisplayMagnifier != null && anyLayerChanged
   8096                 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
   8097             mDisplayMagnifier.onWindowLayersChangedLocked();
   8098         }
   8099     }
   8100 
   8101     private final void performLayoutAndPlaceSurfacesLocked() {
   8102         int loopCount = 6;
   8103         do {
   8104             mTraversalScheduled = false;
   8105             performLayoutAndPlaceSurfacesLockedLoop();
   8106             mH.removeMessages(H.DO_TRAVERSAL);
   8107             loopCount--;
   8108         } while (mTraversalScheduled && loopCount > 0);
   8109         mInnerFields.mWallpaperActionPending = false;
   8110     }
   8111 
   8112     private boolean mInLayout = false;
   8113     private final void performLayoutAndPlaceSurfacesLockedLoop() {
   8114         if (mInLayout) {
   8115             if (DEBUG) {
   8116                 throw new RuntimeException("Recursive call!");
   8117             }
   8118             Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
   8119                     + Debug.getCallers(3));
   8120             return;
   8121         }
   8122 
   8123         if (mWaitingForConfig) {
   8124             // Our configuration has changed (most likely rotation), but we
   8125             // don't yet have the complete configuration to report to
   8126             // applications.  Don't do any window layout until we have it.
   8127             return;
   8128         }
   8129 
   8130         if (!mDisplayReady) {
   8131             // Not yet initialized, nothing to do.
   8132             return;
   8133         }
   8134 
   8135         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
   8136         mInLayout = true;
   8137         boolean recoveringMemory = false;
   8138 
   8139         try {
   8140             if (mForceRemoves != null) {
   8141                 recoveringMemory = true;
   8142                 // Wait a little bit for things to settle down, and off we go.
   8143                 for (int i=0; i<mForceRemoves.size(); i++) {
   8144                     WindowState ws = mForceRemoves.get(i);
   8145                     Slog.i(TAG, "Force removing: " + ws);
   8146                     removeWindowInnerLocked(ws.mSession, ws);
   8147                 }
   8148                 mForceRemoves = null;
   8149                 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
   8150                 Object tmp = new Object();
   8151                 synchronized (tmp) {
   8152                     try {
   8153                         tmp.wait(250);
   8154                     } catch (InterruptedException e) {
   8155                     }
   8156                 }
   8157             }
   8158         } catch (RuntimeException e) {
   8159             Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
   8160         }
   8161 
   8162         try {
   8163             performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
   8164 
   8165             mInLayout = false;
   8166 
   8167             if (needsLayout()) {
   8168                 if (++mLayoutRepeatCount < 6) {
   8169                     requestTraversalLocked();
   8170                 } else {
   8171                     Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
   8172                     mLayoutRepeatCount = 0;
   8173                 }
   8174             } else {
   8175                 mLayoutRepeatCount = 0;
   8176             }
   8177 
   8178             if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
   8179                 mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
   8180                 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE);
   8181             }
   8182         } catch (RuntimeException e) {
   8183             mInLayout = false;
   8184             Log.wtf(TAG, "Unhandled exception while laying out windows", e);
   8185         }
   8186 
   8187         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
   8188     }
   8189 
   8190     private final void performLayoutLockedInner(final DisplayContent displayContent,
   8191                                     boolean initial, boolean updateInputWindows) {
   8192         if (!displayContent.layoutNeeded) {
   8193             return;
   8194         }
   8195         displayContent.layoutNeeded = false;
   8196         WindowList windows = displayContent.getWindowList();
   8197         boolean isDefaultDisplay = displayContent.isDefaultDisplay;
   8198 
   8199         DisplayInfo displayInfo = displayContent.getDisplayInfo();
   8200         final int dw = displayInfo.logicalWidth;
   8201         final int dh = displayInfo.logicalHeight;
   8202 
   8203         final int NFW = mFakeWindows.size();
   8204         for (int i=0; i<NFW; i++) {
   8205             mFakeWindows.get(i).layout(dw, dh);
   8206         }
   8207 
   8208         final int N = windows.size();
   8209         int i;
   8210 
   8211         if (DEBUG_LAYOUT) {
   8212             Slog.v(TAG, "-------------------------------------");
   8213             Slog.v(TAG, "performLayout: needed="
   8214                     + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
   8215         }
   8216 
   8217         WindowStateAnimator universeBackground = null;
   8218 
   8219         mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
   8220         if (isDefaultDisplay) {
   8221             // Not needed on non-default displays.
   8222             mSystemDecorLayer = mPolicy.getSystemDecorLayerLw();
   8223             mScreenRect.set(0, 0, dw, dh);
   8224         }
   8225 
   8226         mPolicy.getContentRectLw(mTmpContentRect);
   8227         displayContent.setStackBoxSize(mTmpContentRect);
   8228 
   8229         int seq = mLayoutSeq+1;
   8230         if (seq < 0) seq = 0;
   8231         mLayoutSeq = seq;
   8232 
   8233         boolean behindDream = false;
   8234 
   8235         // First perform layout of any root windows (not attached
   8236         // to another window).
   8237         int topAttached = -1;
   8238         for (i = N-1; i >= 0; i--) {
   8239             final WindowState win = windows.get(i);
   8240 
   8241             // Don't do layout of a window if it is not visible, or
   8242             // soon won't be visible, to avoid wasting time and funky
   8243             // changes while a window is animating away.
   8244             final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
   8245                     || win.isGoneForLayoutLw();
   8246 
   8247             if (DEBUG_LAYOUT && !win.mLayoutAttached) {
   8248                 Slog.v(TAG, "1ST PASS " + win
   8249                         + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
   8250                         + " mLayoutAttached=" + win.mLayoutAttached
   8251                         + " screen changed=" + win.isConfigChanged());
   8252                 final AppWindowToken atoken = win.mAppToken;
   8253                 if (gone) Slog.v(TAG, "  GONE: mViewVisibility="
   8254                         + win.mViewVisibility + " mRelayoutCalled="
   8255                         + win.mRelayoutCalled + " hidden="
   8256                         + win.mRootToken.hidden + " hiddenRequested="
   8257                         + (atoken != null && atoken.hiddenRequested)
   8258                         + " mAttachedHidden=" + win.mAttachedHidden);
   8259                 else Slog.v(TAG, "  VIS: mViewVisibility="
   8260                         + win.mViewVisibility + " mRelayoutCalled="
   8261                         + win.mRelayoutCalled + " hidden="
   8262                         + win.mRootToken.hidden + " hiddenRequested="
   8263                         + (atoken != null && atoken.hiddenRequested)
   8264                         + " mAttachedHidden=" + win.mAttachedHidden);
   8265             }
   8266 
   8267             // If this view is GONE, then skip it -- keep the current
   8268             // frame, and let the caller know so they can ignore it
   8269             // if they want.  (We do the normal layout for INVISIBLE
   8270             // windows, since that means "perform layout as normal,
   8271             // just don't display").
   8272             if (!gone || !win.mHaveFrame || win.mLayoutNeeded
   8273                     || ((win.isConfigChanged() || win.setInsetsChanged()) &&
   8274                             (win.mAttrs.type == TYPE_KEYGUARD ||
   8275                             win.mAppToken != null && win.mAppToken.layoutConfigChanges))
   8276                     || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
   8277                 if (!win.mLayoutAttached) {
   8278                     if (initial) {
   8279                         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
   8280                         win.mContentChanged = false;
   8281                     }
   8282                     if (win.mAttrs.type == TYPE_DREAM) {
   8283                         // Don't layout windows behind a dream, so that if it
   8284                         // does stuff like hide the status bar we won't get a
   8285                         // bad transition when it goes away.
   8286                         behindDream = true;
   8287                     }
   8288                     win.mLayoutNeeded = false;
   8289                     win.prelayout();
   8290                     mPolicy.layoutWindowLw(win, win.mAttrs, null);
   8291                     win.mLayoutSeq = seq;
   8292                     if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
   8293                             + win.mFrame + " mContainingFrame="
   8294                             + win.mContainingFrame + " mDisplayFrame="
   8295                             + win.mDisplayFrame);
   8296                 } else {
   8297                     if (topAttached < 0) topAttached = i;
   8298                 }
   8299             }
   8300             if (win.mViewVisibility == View.VISIBLE
   8301                     && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
   8302                     && universeBackground == null) {
   8303                 universeBackground = win.mWinAnimator;
   8304             }
   8305         }
   8306 
   8307         if (mAnimator.mUniverseBackground  != universeBackground) {
   8308             mFocusMayChange = true;
   8309             mAnimator.mUniverseBackground = universeBackground;
   8310         }
   8311 
   8312         boolean attachedBehindDream = false;
   8313 
   8314         // Now perform layout of attached windows, which usually
   8315         // depend on the position of the window they are attached to.
   8316         // XXX does not deal with windows that are attached to windows
   8317         // that are themselves attached.
   8318         for (i = topAttached; i >= 0; i--) {
   8319             final WindowState win = windows.get(i);
   8320 
   8321             if (win.mLayoutAttached) {
   8322                 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
   8323                         + " mHaveFrame=" + win.mHaveFrame
   8324                         + " mViewVisibility=" + win.mViewVisibility
   8325                         + " mRelayoutCalled=" + win.mRelayoutCalled);
   8326                 // If this view is GONE, then skip it -- keep the current
   8327                 // frame, and let the caller know so they can ignore it
   8328                 // if they want.  (We do the normal layout for INVISIBLE
   8329                 // windows, since that means "perform layout as normal,
   8330                 // just don't display").
   8331                 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
   8332                     continue;
   8333                 }
   8334                 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
   8335                         || !win.mHaveFrame || win.mLayoutNeeded) {
   8336                     if (initial) {
   8337                         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
   8338                         win.mContentChanged = false;
   8339                     }
   8340                     win.mLayoutNeeded = false;
   8341                     win.prelayout();
   8342                     mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
   8343                     win.mLayoutSeq = seq;
   8344                     if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
   8345                             + win.mFrame + " mContainingFrame="
   8346                             + win.mContainingFrame + " mDisplayFrame="
   8347                             + win.mDisplayFrame);
   8348                 }
   8349             } else if (win.mAttrs.type == TYPE_DREAM) {
   8350                 // Don't layout windows behind a dream, so that if it
   8351                 // does stuff like hide the status bar we won't get a
   8352                 // bad transition when it goes away.
   8353                 attachedBehindDream = behindDream;
   8354             }
   8355         }
   8356 
   8357         // Window frames may have changed.  Tell the input dispatcher about it.
   8358         mInputMonitor.setUpdateInputWindowsNeededLw();
   8359         if (updateInputWindows) {
   8360             mInputMonitor.updateInputWindowsLw(false /*force*/);
   8361         }
   8362 
   8363         mPolicy.finishLayoutLw();
   8364     }
   8365 
   8366     void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
   8367         // If the screen is currently frozen or off, then keep
   8368         // it frozen/off until this window draws at its new
   8369         // orientation.
   8370         if (!okToDisplay()) {
   8371             if (DEBUG_ORIENTATION) Slog.v(TAG,
   8372                     "Changing surface while display frozen: " + w);
   8373             w.mOrientationChanging = true;
   8374             w.mLastFreezeDuration = 0;
   8375             mInnerFields.mOrientationChangeComplete = false;
   8376             if (!mWindowsFreezingScreen) {
   8377                 mWindowsFreezingScreen = true;
   8378                 // XXX should probably keep timeout from
   8379                 // when we first froze the display.
   8380                 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
   8381                 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
   8382                         WINDOW_FREEZE_TIMEOUT_DURATION);
   8383             }
   8384         }
   8385     }
   8386 
   8387     /**
   8388      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
   8389      * @param windows List of windows on default display.
   8390      * @return bitmap indicating if another pass through layout must be made.
   8391      */
   8392     public int handleAppTransitionReadyLocked(WindowList windows) {
   8393         int changes = 0;
   8394         int i;
   8395         int NN = mOpeningApps.size();
   8396         boolean goodToGo = true;
   8397         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8398                 "Checking " + NN + " opening apps (frozen="
   8399                 + mDisplayFrozen + " timeout="
   8400                 + mAppTransition.isTimeout() + ")...");
   8401         if (!mDisplayFrozen && !mAppTransition.isTimeout()) {
   8402             // If the display isn't frozen, wait to do anything until
   8403             // all of the apps are ready.  Otherwise just go because
   8404             // we'll unfreeze the display when everyone is ready.
   8405             for (i=0; i<NN && goodToGo; i++) {
   8406                 AppWindowToken wtoken = mOpeningApps.get(i);
   8407                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8408                         "Check opening app=" + wtoken + ": allDrawn="
   8409                         + wtoken.allDrawn + " startingDisplayed="
   8410                         + wtoken.startingDisplayed + " startingMoved="
   8411                         + wtoken.startingMoved);
   8412                 if (!wtoken.allDrawn && !wtoken.startingDisplayed
   8413                         && !wtoken.startingMoved) {
   8414                     goodToGo = false;
   8415                 }
   8416             }
   8417         }
   8418         if (goodToGo) {
   8419             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
   8420             int transit = mAppTransition.getAppTransition();
   8421             if (mSkipAppTransitionAnimation) {
   8422                 transit = AppTransition.TRANSIT_UNSET;
   8423             }
   8424             mAppTransition.goodToGo();
   8425             mStartingIconInTransition = false;
   8426             mSkipAppTransitionAnimation = false;
   8427 
   8428             mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
   8429 
   8430             rebuildAppWindowListLocked();
   8431 
   8432             // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
   8433             WindowState oldWallpaper =
   8434                     mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
   8435                         && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
   8436                     ? null : mWallpaperTarget;
   8437 
   8438             mInnerFields.mWallpaperMayChange = false;
   8439 
   8440             // The top-most window will supply the layout params,
   8441             // and we will determine it below.
   8442             LayoutParams animLp = null;
   8443             int bestAnimLayer = -1;
   8444             boolean fullscreenAnim = false;
   8445 
   8446             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8447                     "New wallpaper target=" + mWallpaperTarget
   8448                     + ", oldWallpaper=" + oldWallpaper
   8449                     + ", lower target=" + mLowerWallpaperTarget
   8450                     + ", upper target=" + mUpperWallpaperTarget);
   8451 
   8452             boolean openingAppHasWallpaper = false;
   8453             boolean closingAppHasWallpaper = false;
   8454             final AppWindowToken lowerWallpaperAppToken;
   8455             final AppWindowToken upperWallpaperAppToken;
   8456             if (mLowerWallpaperTarget == null) {
   8457                 lowerWallpaperAppToken = upperWallpaperAppToken = null;
   8458             } else {
   8459                 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
   8460                 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
   8461             }
   8462 
   8463             // Do a first pass through the tokens for two
   8464             // things:
   8465             // (1) Determine if both the closing and opening
   8466             // app token sets are wallpaper targets, in which
   8467             // case special animations are needed
   8468             // (since the wallpaper needs to stay static
   8469             // behind them).
   8470             // (2) Find the layout params of the top-most
   8471             // application window in the tokens, which is
   8472             // what will control the animation theme.
   8473             final int NC = mClosingApps.size();
   8474             NN = NC + mOpeningApps.size();
   8475             for (i=0; i<NN; i++) {
   8476                 final AppWindowToken wtoken;
   8477                 if (i < NC) {
   8478                     wtoken = mClosingApps.get(i);
   8479                     if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
   8480                         closingAppHasWallpaper = true;
   8481                     }
   8482                 } else {
   8483                     wtoken = mOpeningApps.get(i - NC);
   8484                     if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
   8485                         openingAppHasWallpaper = true;
   8486                     }
   8487                 }
   8488 
   8489                 if (wtoken.appFullscreen) {
   8490                     WindowState ws = wtoken.findMainWindow();
   8491                     if (ws != null) {
   8492                         animLp = ws.mAttrs;
   8493                         bestAnimLayer = ws.mLayer;
   8494                         fullscreenAnim = true;
   8495                     }
   8496                 } else if (!fullscreenAnim) {
   8497                     WindowState ws = wtoken.findMainWindow();
   8498                     if (ws != null) {
   8499                         if (ws.mLayer > bestAnimLayer) {
   8500                             animLp = ws.mAttrs;
   8501                             bestAnimLayer = ws.mLayer;
   8502                         }
   8503                     }
   8504                 }
   8505             }
   8506 
   8507             mAnimateWallpaperWithTarget = false;
   8508             if (closingAppHasWallpaper && openingAppHasWallpaper) {
   8509                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
   8510                 switch (transit) {
   8511                     case AppTransition.TRANSIT_ACTIVITY_OPEN:
   8512                     case AppTransition.TRANSIT_TASK_OPEN:
   8513                     case AppTransition.TRANSIT_TASK_TO_FRONT:
   8514                         transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
   8515                         break;
   8516                     case AppTransition.TRANSIT_ACTIVITY_CLOSE:
   8517                     case AppTransition.TRANSIT_TASK_CLOSE:
   8518                     case AppTransition.TRANSIT_TASK_TO_BACK:
   8519                         transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
   8520                         break;
   8521                 }
   8522                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
   8523             } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
   8524                     && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
   8525                 // We are transitioning from an activity with
   8526                 // a wallpaper to one without.
   8527                 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
   8528                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8529                         "New transit away from wallpaper: " + transit);
   8530             } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
   8531                 // We are transitioning from an activity without
   8532                 // a wallpaper to now showing the wallpaper
   8533                 transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
   8534                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8535                         "New transit into wallpaper: " + transit);
   8536             } else {
   8537                 mAnimateWallpaperWithTarget = true;
   8538             }
   8539 
   8540             // If all closing windows are obscured, then there is
   8541             // no need to do an animation.  This is the case, for
   8542             // example, when this transition is being done behind
   8543             // the lock screen.
   8544             if (!mPolicy.allowAppAnimationsLw()) {
   8545                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8546                         "Animations disallowed by keyguard or dream.");
   8547                 animLp = null;
   8548             }
   8549 
   8550             AppWindowToken topOpeningApp = null;
   8551             int topOpeningLayer = 0;
   8552 
   8553             NN = mOpeningApps.size();
   8554             for (i=0; i<NN; i++) {
   8555                 AppWindowToken wtoken = mOpeningApps.get(i);
   8556                 final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
   8557                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
   8558                 appAnimator.clearThumbnail();
   8559                 wtoken.inPendingTransaction = false;
   8560                 appAnimator.animation = null;
   8561                 setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
   8562                 wtoken.updateReportedVisibilityLocked();
   8563                 wtoken.waitingToShow = false;
   8564 
   8565                 appAnimator.mAllAppWinAnimators.clear();
   8566                 final int N = wtoken.allAppWindows.size();
   8567                 for (int j = 0; j < N; j++) {
   8568                     appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
   8569                 }
   8570                 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
   8571 
   8572                 if (animLp != null) {
   8573                     int layer = -1;
   8574                     for (int j=0; j<wtoken.windows.size(); j++) {
   8575                         WindowState win = wtoken.windows.get(j);
   8576                         if (win.mWinAnimator.mAnimLayer > layer) {
   8577                             layer = win.mWinAnimator.mAnimLayer;
   8578                         }
   8579                     }
   8580                     if (topOpeningApp == null || layer > topOpeningLayer) {
   8581                         topOpeningApp = wtoken;
   8582                         topOpeningLayer = layer;
   8583                     }
   8584                 }
   8585             }
   8586             NN = mClosingApps.size();
   8587             for (i=0; i<NN; i++) {
   8588                 AppWindowToken wtoken = mClosingApps.get(i);
   8589                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
   8590                 wtoken.mAppAnimator.clearThumbnail();
   8591                 wtoken.inPendingTransaction = false;
   8592                 wtoken.mAppAnimator.animation = null;
   8593                 setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
   8594                 wtoken.updateReportedVisibilityLocked();
   8595                 wtoken.waitingToHide = false;
   8596                 // Force the allDrawn flag, because we want to start
   8597                 // this guy's animations regardless of whether it's
   8598                 // gotten drawn.
   8599                 wtoken.allDrawn = true;
   8600                 wtoken.deferClearAllDrawn = false;
   8601             }
   8602 
   8603             AppWindowAnimator appAnimator =
   8604                     topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
   8605             Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
   8606             if (nextAppTransitionThumbnail != null && appAnimator != null
   8607                     && appAnimator.animation != null) {
   8608                 // This thumbnail animation is very special, we need to have
   8609                 // an extra surface with the thumbnail included with the animation.
   8610                 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
   8611                         nextAppTransitionThumbnail.getHeight());
   8612                 try {
   8613                     // TODO(multi-display): support other displays
   8614                     final DisplayContent displayContent = getDefaultDisplayContentLocked();
   8615                     final Display display = displayContent.getDisplay();
   8616                     SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
   8617                             "thumbnail anim",
   8618                             dirty.width(), dirty.height(),
   8619                             PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
   8620                     surfaceControl.setLayerStack(display.getLayerStack());
   8621                     appAnimator.thumbnail = surfaceControl;
   8622                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
   8623                     Surface drawSurface = new Surface();
   8624                     drawSurface.copyFrom(surfaceControl);
   8625                     Canvas c = drawSurface.lockCanvas(dirty);
   8626                     c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
   8627                     drawSurface.unlockCanvasAndPost(c);
   8628                     drawSurface.release();
   8629                     appAnimator.thumbnailLayer = topOpeningLayer;
   8630                     DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
   8631                     Animation anim = mAppTransition.createThumbnailAnimationLocked(
   8632                             transit, true, true, displayInfo.appWidth, displayInfo.appHeight);
   8633                     appAnimator.thumbnailAnimation = anim;
   8634                     anim.restrictDuration(MAX_ANIMATION_DURATION);
   8635                     anim.scaleCurrentDuration(mTransitionAnimationScale);
   8636                     Point p = new Point();
   8637                     mAppTransition.getStartingPoint(p);
   8638                     appAnimator.thumbnailX = p.x;
   8639                     appAnimator.thumbnailY = p.y;
   8640                 } catch (OutOfResourcesException e) {
   8641                     Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
   8642                             + " h=" + dirty.height(), e);
   8643                     appAnimator.clearThumbnail();
   8644                 }
   8645             }
   8646 
   8647             mAppTransition.postAnimationCallback();
   8648             mAppTransition.clear();
   8649 
   8650             mOpeningApps.clear();
   8651             mClosingApps.clear();
   8652 
   8653             // This has changed the visibility of windows, so perform
   8654             // a new layout to get them all up-to-date.
   8655             changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
   8656                     | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
   8657             getDefaultDisplayContentLocked().layoutNeeded = true;
   8658 
   8659             // TODO(multidisplay): IMEs are only supported on the default display.
   8660             if (windows == getDefaultWindowListLocked()
   8661                     && !moveInputMethodWindowsIfNeededLocked(true)) {
   8662                 assignLayersLocked(windows);
   8663             }
   8664             updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/);
   8665             mFocusMayChange = false;
   8666         }
   8667 
   8668         return changes;
   8669     }
   8670 
   8671     /**
   8672      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
   8673      * @return bitmap indicating if another pass through layout must be made.
   8674      */
   8675     private int handleAnimatingStoppedAndTransitionLocked() {
   8676         int changes = 0;
   8677 
   8678         mAppTransition.setIdle();
   8679         // Restore window app tokens to the ActivityManager views
   8680         final DisplayContent displayContent = getDefaultDisplayContentLocked();
   8681         final ArrayList<Task> tasks = displayContent.getTasks();
   8682         final int numTasks = tasks.size();
   8683         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
   8684             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
   8685             final int numTokens = tokens.size();
   8686             for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
   8687                 final AppWindowToken wtoken = tokens.get(tokenNdx);
   8688                 wtoken.sendingToBottom = false;
   8689             }
   8690         }
   8691         rebuildAppWindowListLocked();
   8692 
   8693         changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
   8694         if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
   8695                 "Wallpaper layer changed: assigning layers + relayout");
   8696         moveInputMethodWindowsIfNeededLocked(true);
   8697         mInnerFields.mWallpaperMayChange = true;
   8698         // Since the window list has been rebuilt, focus might
   8699         // have to be recomputed since the actual order of windows
   8700         // might have changed again.
   8701         mFocusMayChange = true;
   8702 
   8703         return changes;
   8704     }
   8705 
   8706     private void updateResizingWindows(final WindowState w) {
   8707         final WindowStateAnimator winAnimator = w.mWinAnimator;
   8708         if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
   8709             w.setInsetsChanged();
   8710             boolean configChanged = w.isConfigChanged();
   8711             if (DEBUG_CONFIGURATION && configChanged) {
   8712                 Slog.v(TAG, "Win " + w + " config changed: "
   8713                         + mCurConfiguration);
   8714             }
   8715             if (localLOGV) Slog.v(TAG, "Resizing " + w
   8716                     + ": configChanged=" + configChanged
   8717                     + " last=" + w.mLastFrame + " frame=" + w.mFrame);
   8718             w.mLastFrame.set(w.mFrame);
   8719             if (w.mContentInsetsChanged
   8720                     || w.mVisibleInsetsChanged
   8721                     || winAnimator.mSurfaceResized
   8722                     || configChanged) {
   8723                 if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
   8724                     Slog.v(TAG, "Resize reasons for w=" + w + ": "
   8725                             + " contentInsetsChanged=" + w.mContentInsetsChanged
   8726                             + " " + w.mContentInsets.toShortString()
   8727                             + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
   8728                             + " " + w.mVisibleInsets.toShortString()
   8729                             + " surfaceResized=" + winAnimator.mSurfaceResized
   8730                             + " configChanged=" + configChanged);
   8731                 }
   8732 
   8733                 w.mLastOverscanInsets.set(w.mOverscanInsets);
   8734                 w.mLastContentInsets.set(w.mContentInsets);
   8735                 w.mLastVisibleInsets.set(w.mVisibleInsets);
   8736                 makeWindowFreezingScreenIfNeededLocked(w);
   8737                 // If the orientation is changing, then we need to
   8738                 // hold off on unfreezing the display until this
   8739                 // window has been redrawn; to do that, we need
   8740                 // to go through the process of getting informed
   8741                 // by the application when it has finished drawing.
   8742                 if (w.mOrientationChanging) {
   8743                     if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
   8744                             "Orientation start waiting for draw mDrawState=DRAW_PENDING in "
   8745                             + w + ", surface " + winAnimator.mSurfaceControl);
   8746                     winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
   8747                     if (w.mAppToken != null) {
   8748                         w.mAppToken.allDrawn = false;
   8749                         w.mAppToken.deferClearAllDrawn = false;
   8750                     }
   8751                 }
   8752                 if (!mResizingWindows.contains(w)) {
   8753                     if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
   8754                             "Resizing window " + w + " to " + winAnimator.mSurfaceW
   8755                             + "x" + winAnimator.mSurfaceH);
   8756                     mResizingWindows.add(w);
   8757                 }
   8758             } else if (w.mOrientationChanging) {
   8759                 if (w.isDrawnLw()) {
   8760                     if (DEBUG_ORIENTATION) Slog.v(TAG,
   8761                             "Orientation not waiting for draw in "
   8762                             + w + ", surface " + winAnimator.mSurfaceControl);
   8763                     w.mOrientationChanging = false;
   8764                     w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
   8765                             - mDisplayFreezeTime);
   8766                 }
   8767             }
   8768         }
   8769     }
   8770 
   8771     /**
   8772      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
   8773      *
   8774      * @param w WindowState this method is applied to.
   8775      * @param currentTime The time which animations use for calculating transitions.
   8776      * @param innerDw Width of app window.
   8777      * @param innerDh Height of app window.
   8778      */
   8779     private void handleNotObscuredLocked(final WindowState w, final long currentTime,
   8780                                          final int innerDw, final int innerDh) {
   8781         final WindowManager.LayoutParams attrs = w.mAttrs;
   8782         final int attrFlags = attrs.flags;
   8783         final boolean canBeSeen = w.isDisplayedLw();
   8784         final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
   8785 
   8786         if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
   8787             // This window completely covers everything behind it,
   8788             // so we want to leave all of them as undimmed (for
   8789             // performance reasons).
   8790             mInnerFields.mObscured = true;
   8791         }
   8792 
   8793         if (w.mHasSurface) {
   8794             if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
   8795                 mInnerFields.mHoldScreen = w.mSession;
   8796             }
   8797             if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0
   8798                     && mInnerFields.mScreenBrightness < 0) {
   8799                 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness;
   8800             }
   8801             if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0
   8802                     && mInnerFields.mButtonBrightness < 0) {
   8803                 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
   8804             }
   8805             if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
   8806                     && mInnerFields.mUserActivityTimeout < 0) {
   8807                 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
   8808             }
   8809 
   8810             final int type = attrs.type;
   8811             if (canBeSeen
   8812                     && (type == TYPE_SYSTEM_DIALOG
   8813                      || type == TYPE_RECENTS_OVERLAY
   8814                      || type == TYPE_KEYGUARD
   8815                      || type == TYPE_SYSTEM_ERROR)) {
   8816                 mInnerFields.mSyswin = true;
   8817             }
   8818 
   8819             if (canBeSeen) {
   8820                 // This function assumes that the contents of the default display are
   8821                 // processed first before secondary displays.
   8822                 if (w.mDisplayContent.isDefaultDisplay) {
   8823                     // While a dream or keyguard is showing, obscure ordinary application
   8824                     // content on secondary displays (by forcibly enabling mirroring unless
   8825                     // there is other content we want to show) but still allow opaque
   8826                     // keyguard dialogs to be shown.
   8827                     if (type == TYPE_DREAM || type == TYPE_KEYGUARD) {
   8828                         mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true;
   8829                     }
   8830                     mInnerFields.mDisplayHasContent = true;
   8831                 } else if (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays
   8832                         || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG)) {
   8833                     // Allow full screen keyguard presentation dialogs to be seen.
   8834                     mInnerFields.mDisplayHasContent = true;
   8835                 }
   8836             }
   8837         }
   8838     }
   8839 
   8840     private void handleFlagDimBehind(WindowState w, int innerDw, int innerDh) {
   8841         final WindowManager.LayoutParams attrs = w.mAttrs;
   8842         if ((attrs.flags & FLAG_DIM_BEHIND) != 0
   8843                 && w.isDisplayedLw()
   8844                 && !w.mExiting) {
   8845             final WindowStateAnimator winAnimator = w.mWinAnimator;
   8846             final TaskStack stack = w.getStack();
   8847             stack.setDimmingTag();
   8848             if (!stack.isDimming(winAnimator)) {
   8849                 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
   8850                 stack.startDimmingIfNeeded(winAnimator);
   8851             }
   8852         }
   8853     }
   8854 
   8855     private void updateAllDrawnLocked(DisplayContent displayContent) {
   8856         // See if any windows have been drawn, so they (and others
   8857         // associated with them) can now be shown.
   8858         final ArrayList<Task> tasks = displayContent.getTasks();
   8859         final int numTasks = tasks.size();
   8860         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
   8861             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
   8862             final int numTokens = tokens.size();
   8863             for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
   8864                 final AppWindowToken wtoken = tokens.get(tokenNdx);
   8865                 if (!wtoken.allDrawn) {
   8866                     int numInteresting = wtoken.numInterestingWindows;
   8867                     if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
   8868                         if (DEBUG_VISIBILITY) Slog.v(TAG,
   8869                                 "allDrawn: " + wtoken
   8870                                 + " interesting=" + numInteresting
   8871                                 + " drawn=" + wtoken.numDrawnWindows);
   8872                         wtoken.allDrawn = true;
   8873                         mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
   8874                     }
   8875                 }
   8876             }
   8877         }
   8878     }
   8879 
   8880     // "Something has changed!  Let's make it correct now."
   8881     private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
   8882         if (DEBUG_WINDOW_TRACE) {
   8883             Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
   8884                     + Debug.getCallers(3));
   8885         }
   8886 
   8887         final long currentTime = SystemClock.uptimeMillis();
   8888 
   8889         int i;
   8890 
   8891         if (mFocusMayChange) {
   8892             mFocusMayChange = false;
   8893             updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
   8894                     false /*updateInputWindows*/);
   8895         }
   8896 
   8897         // Initialize state of exiting tokens.
   8898         final int numDisplays = mDisplayContents.size();
   8899         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   8900             final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
   8901             for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
   8902                 displayContent.mExitingTokens.get(i).hasVisible = false;
   8903             }
   8904 
   8905             // Initialize state of exiting applications.
   8906             for (i=displayContent.mExitingAppTokens.size()-1; i>=0; i--) {
   8907                 displayContent.mExitingAppTokens.get(i).hasVisible = false;
   8908             }
   8909         }
   8910 
   8911         mInnerFields.mHoldScreen = null;
   8912         mInnerFields.mScreenBrightness = -1;
   8913         mInnerFields.mButtonBrightness = -1;
   8914         mInnerFields.mUserActivityTimeout = -1;
   8915         mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false;
   8916 
   8917         mTransactionSequence++;
   8918 
   8919         final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
   8920         final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
   8921         final int defaultDw = defaultInfo.logicalWidth;
   8922         final int defaultDh = defaultInfo.logicalHeight;
   8923 
   8924         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
   8925                 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
   8926         SurfaceControl.openTransaction();
   8927         try {
   8928 
   8929             if (mWatermark != null) {
   8930                 mWatermark.positionSurface(defaultDw, defaultDh);
   8931             }
   8932             if (mStrictModeFlash != null) {
   8933                 mStrictModeFlash.positionSurface(defaultDw, defaultDh);
   8934             }
   8935 
   8936             boolean focusDisplayed = false;
   8937 
   8938             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   8939                 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
   8940                 boolean updateAllDrawn = false;
   8941                 WindowList windows = displayContent.getWindowList();
   8942                 DisplayInfo displayInfo = displayContent.getDisplayInfo();
   8943                 final int displayId = displayContent.getDisplayId();
   8944                 final int dw = displayInfo.logicalWidth;
   8945                 final int dh = displayInfo.logicalHeight;
   8946                 final int innerDw = displayInfo.appWidth;
   8947                 final int innerDh = displayInfo.appHeight;
   8948                 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
   8949 
   8950                 // Reset for each display.
   8951                 mInnerFields.mDisplayHasContent = false;
   8952 
   8953                 int repeats = 0;
   8954                 do {
   8955                     repeats++;
   8956                     if (repeats > 6) {
   8957                         Slog.w(TAG, "Animation repeat aborted after too many iterations");
   8958                         displayContent.layoutNeeded = false;
   8959                         break;
   8960                     }
   8961 
   8962                     if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
   8963                         displayContent.pendingLayoutChanges);
   8964 
   8965                     if ((displayContent.pendingLayoutChanges &
   8966                             WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
   8967                             (adjustWallpaperWindowsLocked() &
   8968                                     ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
   8969                         assignLayersLocked(windows);
   8970                         displayContent.layoutNeeded = true;
   8971                     }
   8972 
   8973                     if (isDefaultDisplay && (displayContent.pendingLayoutChanges
   8974                             & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
   8975                         if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
   8976                         if (updateOrientationFromAppTokensLocked(true)) {
   8977                             displayContent.layoutNeeded = true;
   8978                             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
   8979                         }
   8980                     }
   8981 
   8982                     if ((displayContent.pendingLayoutChanges
   8983                             & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
   8984                         displayContent.layoutNeeded = true;
   8985                     }
   8986 
   8987                     // FIRST LOOP: Perform a layout, if needed.
   8988                     if (repeats < 4) {
   8989                         performLayoutLockedInner(displayContent, repeats == 1,
   8990                                 false /*updateInputWindows*/);
   8991                     } else {
   8992                         Slog.w(TAG, "Layout repeat skipped after too many iterations");
   8993                     }
   8994 
   8995                     // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
   8996                     // it is animating.
   8997                     displayContent.pendingLayoutChanges = 0;
   8998 
   8999                     if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
   9000                             + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
   9001 
   9002                     if (isDefaultDisplay) {
   9003                         mPolicy.beginPostLayoutPolicyLw(dw, dh);
   9004                         for (i = windows.size() - 1; i >= 0; i--) {
   9005                             WindowState w = windows.get(i);
   9006                             if (w.mHasSurface) {
   9007                                 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs);
   9008                             }
   9009                         }
   9010                         displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
   9011                         if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
   9012                             "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
   9013                     }
   9014                 } while (displayContent.pendingLayoutChanges != 0);
   9015 
   9016                 mInnerFields.mObscured = false;
   9017                 mInnerFields.mSyswin = false;
   9018                 displayContent.resetDimming();
   9019 
   9020                 // Only used if default window
   9021                 final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
   9022 
   9023                 final int N = windows.size();
   9024                 for (i=N-1; i>=0; i--) {
   9025                     WindowState w = windows.get(i);
   9026 
   9027                     final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
   9028 
   9029                     // Update effect.
   9030                     w.mObscured = mInnerFields.mObscured;
   9031                     if (!mInnerFields.mObscured) {
   9032                         handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
   9033                     }
   9034 
   9035                     if (!w.getStack().testDimmingTag()) {
   9036                         handleFlagDimBehind(w, innerDw, innerDh);
   9037                     }
   9038 
   9039                     if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
   9040                             && w.isVisibleLw()) {
   9041                         // This is the wallpaper target and its obscured state
   9042                         // changed... make sure the current wallaper's visibility
   9043                         // has been updated accordingly.
   9044                         updateWallpaperVisibilityLocked();
   9045                     }
   9046 
   9047                     final WindowStateAnimator winAnimator = w.mWinAnimator;
   9048 
   9049                     // If the window has moved due to its containing
   9050                     // content frame changing, then we'd like to animate
   9051                     // it.
   9052                     if (w.mHasSurface && w.shouldAnimateMove()) {
   9053                         // Frame has moved, containing content frame
   9054                         // has also moved, and we're not currently animating...
   9055                         // let's do something.
   9056                         Animation a = AnimationUtils.loadAnimation(mContext,
   9057                                 com.android.internal.R.anim.window_move_from_decor);
   9058                         winAnimator.setAnimation(a);
   9059                         winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
   9060                         winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
   9061                         try {
   9062                             w.mClient.moved(w.mFrame.left, w.mFrame.top);
   9063                         } catch (RemoteException e) {
   9064                         }
   9065                     }
   9066 
   9067                     //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
   9068                     w.mContentChanged = false;
   9069 
   9070                     // Moved from updateWindowsAndWallpaperLocked().
   9071                     if (w.mHasSurface) {
   9072                         // Take care of the window being ready to display.
   9073                         final boolean committed =
   9074                                 winAnimator.commitFinishDrawingLocked(currentTime);
   9075                         if (isDefaultDisplay && committed) {
   9076                             if (w.mAttrs.type == TYPE_DREAM) {
   9077                                 // HACK: When a dream is shown, it may at that
   9078                                 // point hide the lock screen.  So we need to
   9079                                 // redo the layout to let the phone window manager
   9080                                 // make this happen.
   9081                                 displayContent.pendingLayoutChanges |=
   9082                                         WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
   9083                                 if (DEBUG_LAYOUT_REPEATS) {
   9084                                     debugLayoutRepeats(
   9085                                         "dream and commitFinishDrawingLocked true",
   9086                                         displayContent.pendingLayoutChanges);
   9087                                 }
   9088                             }
   9089                             if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
   9090                                 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
   9091                                         "First draw done in potential wallpaper target " + w);
   9092                                 mInnerFields.mWallpaperMayChange = true;
   9093                                 displayContent.pendingLayoutChanges |=
   9094                                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
   9095                                 if (DEBUG_LAYOUT_REPEATS) {
   9096                                     debugLayoutRepeats(
   9097                                         "wallpaper and commitFinishDrawingLocked true",
   9098                                         displayContent.pendingLayoutChanges);
   9099                                 }
   9100                             }
   9101                         }
   9102 
   9103                         winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
   9104 
   9105                         final AppWindowToken atoken = w.mAppToken;
   9106                         if (DEBUG_STARTING_WINDOW && atoken != null
   9107                                 && w == atoken.startingWindow) {
   9108                             Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
   9109                                 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
   9110                                 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
   9111                         }
   9112                         if (atoken != null
   9113                                 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
   9114                             if (atoken.lastTransactionSequence != mTransactionSequence) {
   9115                                 atoken.lastTransactionSequence = mTransactionSequence;
   9116                                 atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
   9117                                 atoken.startingDisplayed = false;
   9118                             }
   9119                             if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
   9120                                     && !w.mExiting && !w.mDestroying) {
   9121                                 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
   9122                                     Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
   9123                                             + ", isAnimating=" + winAnimator.isAnimating());
   9124                                     if (!w.isDrawnLw()) {
   9125                                         Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
   9126                                                 + " pv=" + w.mPolicyVisibility
   9127                                                 + " mDrawState=" + winAnimator.mDrawState
   9128                                                 + " ah=" + w.mAttachedHidden
   9129                                                 + " th=" + atoken.hiddenRequested
   9130                                                 + " a=" + winAnimator.mAnimating);
   9131                                     }
   9132                                 }
   9133                                 if (w != atoken.startingWindow) {
   9134                                     if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
   9135                                         atoken.numInterestingWindows++;
   9136                                         if (w.isDrawnLw()) {
   9137                                             atoken.numDrawnWindows++;
   9138                                             if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
   9139                                                     "tokenMayBeDrawn: " + atoken
   9140                                                     + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
   9141                                                     + " mAppFreezing=" + w.mAppFreezing);
   9142                                             updateAllDrawn = true;
   9143                                         }
   9144                                     }
   9145                                 } else if (w.isDrawnLw()) {
   9146                                     atoken.startingDisplayed = true;
   9147                                 }
   9148                             }
   9149                         }
   9150                     }
   9151 
   9152                     if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
   9153                             && w.isDisplayedLw()) {
   9154                         focusDisplayed = true;
   9155                     }
   9156 
   9157                     updateResizingWindows(w);
   9158                 }
   9159 
   9160                 mDisplayManagerService.setDisplayHasContent(displayId,
   9161                         mInnerFields.mDisplayHasContent,
   9162                         true /* inTraversal, must call performTraversalInTrans... below */);
   9163 
   9164                 getDisplayContentLocked(displayId).stopDimmingIfNeeded();
   9165 
   9166                 if (updateAllDrawn) {
   9167                     updateAllDrawnLocked(displayContent);
   9168                 }
   9169             }
   9170 
   9171             if (focusDisplayed) {
   9172                 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
   9173             }
   9174 
   9175             // Give the display manager a chance to adjust properties
   9176             // like display rotation if it needs to.
   9177             mDisplayManagerService.performTraversalInTransactionFromWindowManager();
   9178 
   9179         } catch (RuntimeException e) {
   9180             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
   9181         } finally {
   9182             SurfaceControl.closeTransaction();
   9183             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
   9184                     "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
   9185         }
   9186 
   9187         final WindowList defaultWindows = defaultDisplay.getWindowList();
   9188 
   9189         // If we are ready to perform an app transition, check through
   9190         // all of the app tokens to be shown and see if they are ready
   9191         // to go.
   9192         if (mAppTransition.isReady()) {
   9193             defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
   9194             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
   9195                     defaultDisplay.pendingLayoutChanges);
   9196         }
   9197 
   9198         if (!mAnimator.mAnimating && mAppTransition.isRunning()) {
   9199             // We have finished the animation of an app transition.  To do
   9200             // this, we have delayed a lot of operations like showing and
   9201             // hiding apps, moving apps in Z-order, etc.  The app token list
   9202             // reflects the correct Z-order, but the window list may now
   9203             // be out of sync with it.  So here we will just rebuild the
   9204             // entire app window list.  Fun!
   9205             defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
   9206             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
   9207                 defaultDisplay.pendingLayoutChanges);
   9208         }
   9209 
   9210         if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
   9211                 && !mAppTransition.isReady()) {
   9212             // At this point, there was a window with a wallpaper that
   9213             // was force hiding other windows behind it, but now it
   9214             // is going away.  This may be simple -- just animate
   9215             // away the wallpaper and its window -- or it may be
   9216             // hard -- the wallpaper now needs to be shown behind
   9217             // something that was hidden.
   9218             defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
   9219             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
   9220                 defaultDisplay.pendingLayoutChanges);
   9221         }
   9222         mInnerFields.mWallpaperForceHidingChanged = false;
   9223 
   9224         if (mInnerFields.mWallpaperMayChange) {
   9225             if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
   9226             defaultDisplay.pendingLayoutChanges |=
   9227                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
   9228             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
   9229                     defaultDisplay.pendingLayoutChanges);
   9230         }
   9231 
   9232         if (mFocusMayChange) {
   9233             mFocusMayChange = false;
   9234             if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
   9235                     false /*updateInputWindows*/)) {
   9236                 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
   9237             }
   9238         }
   9239 
   9240         if (needsLayout()) {
   9241             defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
   9242             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
   9243                     defaultDisplay.pendingLayoutChanges);
   9244         }
   9245 
   9246         for (i = mResizingWindows.size() - 1; i >= 0; i--) {
   9247             WindowState win = mResizingWindows.get(i);
   9248             if (win.mAppFreezing) {
   9249                 // Don't remove this window until rotation has completed.
   9250                 continue;
   9251             }
   9252             final WindowStateAnimator winAnimator = win.mWinAnimator;
   9253             try {
   9254                 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
   9255                         "Reporting new frame to " + win + ": " + win.mCompatFrame);
   9256                 int diff = 0;
   9257                 boolean configChanged = win.isConfigChanged();
   9258                 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
   9259                         && configChanged) {
   9260                     Slog.i(TAG, "Sending new config to window " + win + ": "
   9261                             + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH
   9262                             + " / " + mCurConfiguration + " / 0x"
   9263                             + Integer.toHexString(diff));
   9264                 }
   9265                 win.setConfiguration(mCurConfiguration);
   9266                 if (DEBUG_ORIENTATION &&
   9267                         winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(
   9268                         TAG, "Resizing " + win + " WITH DRAW PENDING");
   9269                 final IWindow client = win.mClient;
   9270                 final Rect frame = win.mFrame;
   9271                 final Rect overscanInsets = win.mLastOverscanInsets;
   9272                 final Rect contentInsets = win.mLastContentInsets;
   9273                 final Rect visibleInsets = win.mLastVisibleInsets;
   9274                 final boolean reportDraw
   9275                         = winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING;
   9276                 final Configuration newConfig = configChanged ? win.mConfiguration : null;
   9277                 if (win.mClient instanceof IWindow.Stub) {
   9278                     // To prevent deadlock simulate one-way call if win.mClient is a local object.
   9279                     mH.post(new Runnable() {
   9280                         @Override
   9281                         public void run() {
   9282                             try {
   9283                                 client.resized(frame, overscanInsets, contentInsets,
   9284                                         visibleInsets, reportDraw, newConfig);
   9285                             } catch (RemoteException e) {
   9286                                 // Not a remote call, RemoteException won't be raised.
   9287                             }
   9288                         }
   9289                     });
   9290                 } else {
   9291                    client.resized(frame, overscanInsets, contentInsets, visibleInsets, reportDraw,
   9292                            newConfig);
   9293                 }
   9294                 win.mOverscanInsetsChanged = false;
   9295                 win.mContentInsetsChanged = false;
   9296                 win.mVisibleInsetsChanged = false;
   9297                 winAnimator.mSurfaceResized = false;
   9298             } catch (RemoteException e) {
   9299                 win.mOrientationChanging = false;
   9300                 win.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
   9301                         - mDisplayFreezeTime);
   9302             }
   9303             mResizingWindows.remove(i);
   9304         }
   9305 
   9306         if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
   9307                 "With display frozen, orientationChangeComplete="
   9308                 + mInnerFields.mOrientationChangeComplete);
   9309         if (mInnerFields.mOrientationChangeComplete) {
   9310             if (mWindowsFreezingScreen) {
   9311                 mWindowsFreezingScreen = false;
   9312                 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource;
   9313                 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
   9314             }
   9315             stopFreezingDisplayLocked();
   9316         }
   9317 
   9318         // Destroy the surface of any windows that are no longer visible.
   9319         boolean wallpaperDestroyed = false;
   9320         i = mDestroySurface.size();
   9321         if (i > 0) {
   9322             do {
   9323                 i--;
   9324                 WindowState win = mDestroySurface.get(i);
   9325                 win.mDestroying = false;
   9326                 if (mInputMethodWindow == win) {
   9327                     mInputMethodWindow = null;
   9328                 }
   9329                 if (win == mWallpaperTarget) {
   9330                     wallpaperDestroyed = true;
   9331                 }
   9332                 win.mWinAnimator.destroySurfaceLocked();
   9333             } while (i > 0);
   9334             mDestroySurface.clear();
   9335         }
   9336 
   9337         // Time to remove any exiting tokens?
   9338         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   9339             final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
   9340             ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
   9341             for (i = exitingTokens.size() - 1; i >= 0; i--) {
   9342                 WindowToken token = exitingTokens.get(i);
   9343                 if (!token.hasVisible) {
   9344                     exitingTokens.remove(i);
   9345                     if (token.windowType == TYPE_WALLPAPER) {
   9346                         mWallpaperTokens.remove(token);
   9347                     }
   9348                 }
   9349             }
   9350 
   9351             // Time to remove any exiting applications?
   9352             AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
   9353             for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
   9354                 AppWindowToken token = exitingAppTokens.get(i);
   9355                 if (!token.hasVisible && !mClosingApps.contains(token)) {
   9356                     // Make sure there is no animation running on this token,
   9357                     // so any windows associated with it will be removed as
   9358                     // soon as their animations are complete
   9359                     token.mAppAnimator.clearAnimation();
   9360                     token.mAppAnimator.animating = false;
   9361                     if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
   9362                             "performLayout: App token exiting now removed" + token);
   9363                     final Task task = mTaskIdToTask.get(token.groupId);
   9364                     if (task != null && task.removeAppToken(token)) {
   9365                         mTaskIdToTask.delete(token.groupId);
   9366                     }
   9367                     exitingAppTokens.remove(i);
   9368                 }
   9369             }
   9370         }
   9371 
   9372         if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
   9373             for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
   9374                 try {
   9375                     mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
   9376                 } catch (RemoteException e) {
   9377                 }
   9378             }
   9379             mRelayoutWhileAnimating.clear();
   9380         }
   9381 
   9382         if (wallpaperDestroyed) {
   9383             defaultDisplay.pendingLayoutChanges |=
   9384                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
   9385             defaultDisplay.layoutNeeded = true;
   9386         }
   9387 
   9388         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   9389             final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
   9390             if (displayContent.pendingLayoutChanges != 0) {
   9391                 displayContent.layoutNeeded = true;
   9392             }
   9393         }
   9394 
   9395         // Finally update all input windows now that the window changes have stabilized.
   9396         mInputMonitor.updateInputWindowsLw(true /*force*/);
   9397 
   9398         setHoldScreenLocked(mInnerFields.mHoldScreen);
   9399         if (!mDisplayFrozen) {
   9400             if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
   9401                 mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1);
   9402             } else {
   9403                 mPowerManager.setScreenBrightnessOverrideFromWindowManager(
   9404                         toBrightnessOverride(mInnerFields.mScreenBrightness));
   9405             }
   9406             if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
   9407                 mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1);
   9408             } else {
   9409                 mPowerManager.setButtonBrightnessOverrideFromWindowManager(
   9410                         toBrightnessOverride(mInnerFields.mButtonBrightness));
   9411             }
   9412             mPowerManager.setUserActivityTimeoutOverrideFromWindowManager(
   9413                     mInnerFields.mUserActivityTimeout);
   9414         }
   9415 
   9416         if (mTurnOnScreen) {
   9417             if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
   9418             mPowerManager.wakeUp(SystemClock.uptimeMillis());
   9419             mTurnOnScreen = false;
   9420         }
   9421 
   9422         if (mInnerFields.mUpdateRotation) {
   9423             if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
   9424             if (updateRotationUncheckedLocked(false)) {
   9425                 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
   9426             } else {
   9427                 mInnerFields.mUpdateRotation = false;
   9428             }
   9429         }
   9430 
   9431         if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded
   9432                 && !mInnerFields.mUpdateRotation) {
   9433             checkDrawnWindowsLocked();
   9434         }
   9435 
   9436         final int N = mPendingRemove.size();
   9437         if (N > 0) {
   9438             if (mPendingRemoveTmp.length < N) {
   9439                 mPendingRemoveTmp = new WindowState[N+10];
   9440             }
   9441             mPendingRemove.toArray(mPendingRemoveTmp);
   9442             mPendingRemove.clear();
   9443             DisplayContentList displayList = new DisplayContentList();
   9444             for (i = 0; i < N; i++) {
   9445                 WindowState w = mPendingRemoveTmp[i];
   9446                 removeWindowInnerLocked(w.mSession, w);
   9447                 if (!displayList.contains(w.mDisplayContent)) {
   9448                     displayList.add(w.mDisplayContent);
   9449                 }
   9450             }
   9451 
   9452             for (DisplayContent displayContent : displayList) {
   9453                 assignLayersLocked(displayContent.getWindowList());
   9454                 displayContent.layoutNeeded = true;
   9455             }
   9456         }
   9457 
   9458         setFocusedStackFrame();
   9459 
   9460         // Check to see if we are now in a state where the screen should
   9461         // be enabled, because the window obscured flags have changed.
   9462         enableScreenIfNeededLocked();
   9463 
   9464         scheduleAnimationLocked();
   9465 
   9466         if (DEBUG_WINDOW_TRACE) {
   9467             Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
   9468                     + mAnimator.mAnimating);
   9469         }
   9470     }
   9471 
   9472     private int toBrightnessOverride(float value) {
   9473         return (int)(value * PowerManager.BRIGHTNESS_ON);
   9474     }
   9475 
   9476     void checkDrawnWindowsLocked() {
   9477         if (mWaitingForDrawn.size() > 0) {
   9478             for (int j=mWaitingForDrawn.size()-1; j>=0; j--) {
   9479                 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j);
   9480                 WindowState win = pair.first;
   9481                 //Slog.i(TAG, "Waiting for drawn " + win + ": removed="
   9482                 //        + win.mRemoved + " visible=" + win.isVisibleLw()
   9483                 //        + " shown=" + win.mSurfaceShown);
   9484                 if (win.mRemoved) {
   9485                     // Window has been removed; no draw will now happen, so stop waiting.
   9486                     Slog.w(TAG, "Aborted waiting for drawn: " + pair.first);
   9487                     try {
   9488                         pair.second.sendResult(null);
   9489                     } catch (RemoteException e) {
   9490                     }
   9491                     mWaitingForDrawn.remove(pair);
   9492                     mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
   9493                 } else if (win.mWinAnimator.mSurfaceShown) {
   9494                     // Window is now drawn (and shown).
   9495                     try {
   9496                         pair.second.sendResult(null);
   9497                     } catch (RemoteException e) {
   9498                     }
   9499                     mWaitingForDrawn.remove(pair);
   9500                     mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
   9501                 }
   9502             }
   9503         }
   9504     }
   9505 
   9506     @Override
   9507     public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
   9508         if (token != null && callback != null) {
   9509             synchronized (mWindowMap) {
   9510                 WindowState win = windowForClientLocked(null, token, true);
   9511                 if (win != null) {
   9512                     Pair<WindowState, IRemoteCallback> pair =
   9513                             new Pair<WindowState, IRemoteCallback>(win, callback);
   9514                     Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
   9515                     mH.sendMessageDelayed(m, 2000);
   9516                     mWaitingForDrawn.add(pair);
   9517                     checkDrawnWindowsLocked();
   9518                     return true;
   9519                 }
   9520                 Slog.i(TAG, "waitForWindowDrawn: win null");
   9521             }
   9522         }
   9523         return false;
   9524     }
   9525 
   9526     void setHoldScreenLocked(final Session newHoldScreen) {
   9527         final boolean hold = newHoldScreen != null;
   9528 
   9529         if (hold && mHoldingScreenOn != newHoldScreen) {
   9530             mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
   9531         }
   9532         mHoldingScreenOn = newHoldScreen;
   9533 
   9534         final boolean state = mHoldingScreenWakeLock.isHeld();
   9535         if (hold != state) {
   9536             if (hold) {
   9537                 mHoldingScreenWakeLock.acquire();
   9538                 mPolicy.keepScreenOnStartedLw();
   9539             } else {
   9540                 mPolicy.keepScreenOnStoppedLw();
   9541                 mHoldingScreenWakeLock.release();
   9542             }
   9543         }
   9544     }
   9545 
   9546     @Override
   9547     public void requestTraversal() {
   9548         synchronized (mWindowMap) {
   9549             requestTraversalLocked();
   9550         }
   9551     }
   9552 
   9553     void requestTraversalLocked() {
   9554         if (!mTraversalScheduled) {
   9555             mTraversalScheduled = true;
   9556             mH.sendEmptyMessage(H.DO_TRAVERSAL);
   9557         }
   9558     }
   9559 
   9560     /** Note that Locked in this case is on mLayoutToAnim */
   9561     void scheduleAnimationLocked() {
   9562         if (!mAnimationScheduled) {
   9563             mAnimationScheduled = true;
   9564             mChoreographer.postCallback(
   9565                     Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
   9566         }
   9567     }
   9568 
   9569     private boolean needsLayout() {
   9570         final int numDisplays = mDisplayContents.size();
   9571         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   9572             final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
   9573             if (displayContent.layoutNeeded) {
   9574                 return true;
   9575             }
   9576         }
   9577         return false;
   9578     }
   9579 
   9580     boolean copyAnimToLayoutParamsLocked() {
   9581         boolean doRequest = false;
   9582 
   9583         final int bulkUpdateParams = mAnimator.mBulkUpdateParams;
   9584         if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
   9585             mInnerFields.mUpdateRotation = true;
   9586             doRequest = true;
   9587         }
   9588         if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
   9589             mInnerFields.mWallpaperMayChange = true;
   9590             doRequest = true;
   9591         }
   9592         if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
   9593             mInnerFields.mWallpaperForceHidingChanged = true;
   9594             doRequest = true;
   9595         }
   9596         if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
   9597             mInnerFields.mOrientationChangeComplete = false;
   9598         } else {
   9599             mInnerFields.mOrientationChangeComplete = true;
   9600             mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource;
   9601             if (mWindowsFreezingScreen) {
   9602                 doRequest = true;
   9603             }
   9604         }
   9605         if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
   9606             mTurnOnScreen = true;
   9607         }
   9608         if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) {
   9609             mInnerFields.mWallpaperActionPending = true;
   9610         }
   9611 
   9612         return doRequest;
   9613     }
   9614 
   9615     /** If a window that has an animation specifying a colored background and the current wallpaper
   9616      * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
   9617      * suddenly disappear. */
   9618     int adjustAnimationBackground(WindowStateAnimator winAnimator) {
   9619         WindowList windows = winAnimator.mWin.getWindowList();
   9620         for (int i = windows.size() - 1; i >= 0; --i) {
   9621             WindowState testWin = windows.get(i);
   9622             if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
   9623                 return testWin.mWinAnimator.mAnimLayer;
   9624             }
   9625         }
   9626         return winAnimator.mAnimLayer;
   9627     }
   9628 
   9629     boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
   9630                                            boolean secure) {
   9631         final SurfaceControl surface = winAnimator.mSurfaceControl;
   9632         boolean leakedSurface = false;
   9633         boolean killedApps = false;
   9634 
   9635         EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
   9636                 winAnimator.mSession.mPid, operation);
   9637 
   9638         if (mForceRemoves == null) {
   9639             mForceRemoves = new ArrayList<WindowState>();
   9640         }
   9641 
   9642         long callingIdentity = Binder.clearCallingIdentity();
   9643         try {
   9644             // There was some problem...   first, do a sanity check of the
   9645             // window list to make sure we haven't left any dangling surfaces
   9646             // around.
   9647 
   9648             Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
   9649             final int numDisplays = mDisplayContents.size();
   9650             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   9651                 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
   9652                 final int numWindows = windows.size();
   9653                 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
   9654                     final WindowState ws = windows.get(winNdx);
   9655                     WindowStateAnimator wsa = ws.mWinAnimator;
   9656                     if (wsa.mSurfaceControl != null) {
   9657                         if (!mSessions.contains(wsa.mSession)) {
   9658                             Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
   9659                                     + ws + " surface=" + wsa.mSurfaceControl
   9660                                     + " token=" + ws.mToken
   9661                                     + " pid=" + ws.mSession.mPid
   9662                                     + " uid=" + ws.mSession.mUid);
   9663                             if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
   9664                             wsa.mSurfaceControl.destroy();
   9665                             wsa.mSurfaceShown = false;
   9666                             wsa.mSurfaceControl = null;
   9667                             ws.mHasSurface = false;
   9668                             mForceRemoves.add(ws);
   9669                             leakedSurface = true;
   9670                         } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
   9671                             Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
   9672                                     + ws + " surface=" + wsa.mSurfaceControl
   9673                                     + " token=" + ws.mAppToken);
   9674                             if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
   9675                             wsa.mSurfaceControl.destroy();
   9676                             wsa.mSurfaceShown = false;
   9677                             wsa.mSurfaceControl = null;
   9678                             ws.mHasSurface = false;
   9679                             leakedSurface = true;
   9680                         }
   9681                     }
   9682                 }
   9683             }
   9684 
   9685             if (!leakedSurface) {
   9686                 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
   9687                 SparseIntArray pidCandidates = new SparseIntArray();
   9688                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   9689                     final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
   9690                     final int numWindows = windows.size();
   9691                     for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
   9692                         final WindowState ws = windows.get(winNdx);
   9693                         if (mForceRemoves.contains(ws)) {
   9694                             continue;
   9695                         }
   9696                         WindowStateAnimator wsa = ws.mWinAnimator;
   9697                         if (wsa.mSurfaceControl != null) {
   9698                             pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
   9699                         }
   9700                     }
   9701                     if (pidCandidates.size() > 0) {
   9702                         int[] pids = new int[pidCandidates.size()];
   9703                         for (int i=0; i<pids.length; i++) {
   9704                             pids[i] = pidCandidates.keyAt(i);
   9705                         }
   9706                         try {
   9707                             if (mActivityManager.killPids(pids, "Free memory", secure)) {
   9708                                 killedApps = true;
   9709                             }
   9710                         } catch (RemoteException e) {
   9711                         }
   9712                     }
   9713                 }
   9714             }
   9715 
   9716             if (leakedSurface || killedApps) {
   9717                 // We managed to reclaim some memory, so get rid of the trouble
   9718                 // surface and ask the app to request another one.
   9719                 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
   9720                 if (surface != null) {
   9721                     if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
   9722                             "RECOVER DESTROY", null);
   9723                     surface.destroy();
   9724                     winAnimator.mSurfaceShown = false;
   9725                     winAnimator.mSurfaceControl = null;
   9726                     winAnimator.mWin.mHasSurface = false;
   9727                     scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken);
   9728                 }
   9729 
   9730                 try {
   9731                     winAnimator.mWin.mClient.dispatchGetNewSurface();
   9732                 } catch (RemoteException e) {
   9733                 }
   9734             }
   9735         } finally {
   9736             Binder.restoreCallingIdentity(callingIdentity);
   9737         }
   9738 
   9739         return leakedSurface || killedApps;
   9740     }
   9741 
   9742     private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
   9743         WindowState newFocus = computeFocusedWindowLocked();
   9744         if (mCurrentFocus != newFocus) {
   9745             Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
   9746             // This check makes sure that we don't already have the focus
   9747             // change message pending.
   9748             mH.removeMessages(H.REPORT_FOCUS_CHANGE);
   9749             mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
   9750             // TODO(multidisplay): Focused windows on default display only.
   9751             final DisplayContent displayContent = getDefaultDisplayContentLocked();
   9752             final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
   9753                     mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
   9754                             && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
   9755             if (imWindowChanged) {
   9756                 displayContent.layoutNeeded = true;
   9757                 newFocus = computeFocusedWindowLocked();
   9758             }
   9759 
   9760             if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " +
   9761                     mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
   9762             final WindowState oldFocus = mCurrentFocus;
   9763             mCurrentFocus = newFocus;
   9764             mLosingFocus.remove(newFocus);
   9765             int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
   9766 
   9767             if (imWindowChanged && oldFocus != mInputMethodWindow) {
   9768                 // Focus of the input method window changed. Perform layout if needed.
   9769                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
   9770                     performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
   9771                     focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
   9772                 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
   9773                     // Client will do the layout, but we need to assign layers
   9774                     // for handleNewWindowLocked() below.
   9775                     assignLayersLocked(displayContent.getWindowList());
   9776                 }
   9777             }
   9778 
   9779             if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
   9780                 // The change in focus caused us to need to do a layout.  Okay.
   9781                 displayContent.layoutNeeded = true;
   9782                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
   9783                     performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
   9784                 }
   9785             }
   9786 
   9787             if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
   9788                 // If we defer assigning layers, then the caller is responsible for
   9789                 // doing this part.
   9790                 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows);
   9791             }
   9792 
   9793             Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
   9794             return true;
   9795         }
   9796         return false;
   9797     }
   9798 
   9799     private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) {
   9800         mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
   9801     }
   9802 
   9803     private WindowState computeFocusedWindowLocked() {
   9804         if (mAnimator.mUniverseBackground != null
   9805                 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
   9806             return mAnimator.mUniverseBackground.mWin;
   9807         }
   9808 
   9809         final int displayCount = mDisplayContents.size();
   9810         for (int i = 0; i < displayCount; i++) {
   9811             final DisplayContent displayContent = mDisplayContents.valueAt(i);
   9812             WindowState win = findFocusedWindowLocked(displayContent);
   9813             if (win != null) {
   9814                 return win;
   9815             }
   9816         }
   9817         return null;
   9818     }
   9819 
   9820     private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
   9821         final WindowList windows = displayContent.getWindowList();
   9822         for (int i = windows.size() - 1; i >= 0; i--) {
   9823             final WindowState win = windows.get(i);
   9824 
   9825             if (localLOGV || DEBUG_FOCUS) Slog.v(
   9826                 TAG, "Looking for focus: " + i
   9827                 + " = " + win
   9828                 + ", flags=" + win.mAttrs.flags
   9829                 + ", canReceive=" + win.canReceiveKeys());
   9830 
   9831             AppWindowToken wtoken = win.mAppToken;
   9832 
   9833             // If this window's application has been removed, just skip it.
   9834             if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
   9835                 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because "
   9836                         + (wtoken.removed ? "removed" : "sendingToBottom"));
   9837                 continue;
   9838             }
   9839 
   9840             if (!win.canReceiveKeys()) {
   9841                 continue;
   9842             }
   9843 
   9844             // Descend through all of the app tokens and find the first that either matches
   9845             // win.mAppToken (return win) or mFocusedApp (return null).
   9846             if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
   9847                     mFocusedApp != null) {
   9848                 ArrayList<Task> tasks = displayContent.getTasks();
   9849                 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
   9850                     AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
   9851                     int tokenNdx = tokens.size() - 1;
   9852                     for ( ; tokenNdx >= 0; --tokenNdx) {
   9853                         final AppWindowToken token = tokens.get(tokenNdx);
   9854                         if (wtoken == token) {
   9855                             break;
   9856                         }
   9857                         if (mFocusedApp == token) {
   9858                             // Whoops, we are below the focused app...  no focus for you!
   9859                             if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG,
   9860                                     "findFocusedWindow: Reached focused app=" + mFocusedApp);
   9861                             return null;
   9862                         }
   9863                     }
   9864                     if (tokenNdx >= 0) {
   9865                         // Early exit from loop, must have found the matching token.
   9866                         break;
   9867                     }
   9868                 }
   9869             }
   9870 
   9871             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i +
   9872                         " = " + win);
   9873             return win;
   9874         }
   9875 
   9876         if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows.");
   9877         return null;
   9878     }
   9879 
   9880     private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
   9881         if (mDisplayFrozen) {
   9882             return;
   9883         }
   9884 
   9885         if (!mDisplayReady || !mPolicy.isScreenOnFully()) {
   9886             // No need to freeze the screen before the system is ready or if
   9887             // the screen is off.
   9888             return;
   9889         }
   9890 
   9891         mScreenFrozenLock.acquire();
   9892 
   9893         mDisplayFrozen = true;
   9894         mDisplayFreezeTime = SystemClock.elapsedRealtime();
   9895         mLastFinishedFreezeSource = null;
   9896 
   9897         mInputMonitor.freezeInputDispatchingLw();
   9898 
   9899         // Clear the last input window -- that is just used for
   9900         // clean transitions between IMEs, and if we are freezing
   9901         // the screen then the whole world is changing behind the scenes.
   9902         mPolicy.setLastInputMethodWindowLw(null, null);
   9903 
   9904         if (mAppTransition.isTransitionSet()) {
   9905             mAppTransition.freeze();
   9906         }
   9907 
   9908         if (PROFILE_ORIENTATION) {
   9909             File file = new File("/data/system/frozen");
   9910             Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
   9911         }
   9912 
   9913         if (CUSTOM_SCREEN_ROTATION) {
   9914             mExitAnimId = exitAnim;
   9915             mEnterAnimId = enterAnim;
   9916             final DisplayContent displayContent = getDefaultDisplayContentLocked();
   9917             final int displayId = displayContent.getDisplayId();
   9918             ScreenRotationAnimation screenRotationAnimation =
   9919                     mAnimator.getScreenRotationAnimationLocked(displayId);
   9920             if (screenRotationAnimation != null) {
   9921                 screenRotationAnimation.kill();
   9922             }
   9923 
   9924             // TODO(multidisplay): rotation on main screen only.
   9925             screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
   9926                     mFxSession, inTransaction, mPolicy.isDefaultOrientationForced());
   9927             mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
   9928         }
   9929     }
   9930 
   9931     private void stopFreezingDisplayLocked() {
   9932         if (!mDisplayFrozen) {
   9933             return;
   9934         }
   9935 
   9936         if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
   9937                 || mClientFreezingScreen) {
   9938             if (DEBUG_ORIENTATION) Slog.d(TAG,
   9939                 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
   9940                 + ", mAppsFreezingScreen=" + mAppsFreezingScreen
   9941                 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
   9942                 + ", mClientFreezingScreen=" + mClientFreezingScreen);
   9943             return;
   9944         }
   9945 
   9946         mDisplayFrozen = false;
   9947         mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
   9948         StringBuilder sb = new StringBuilder(128);
   9949         sb.append("Screen frozen for ");
   9950         TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
   9951         if (mLastFinishedFreezeSource != null) {
   9952             sb.append(" due to ");
   9953             sb.append(mLastFinishedFreezeSource);
   9954         }
   9955         Slog.i(TAG, sb.toString());
   9956         mH.removeMessages(H.APP_FREEZE_TIMEOUT);
   9957         mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
   9958         if (PROFILE_ORIENTATION) {
   9959             Debug.stopMethodTracing();
   9960         }
   9961 
   9962         boolean updateRotation = false;
   9963 
   9964         final DisplayContent displayContent = getDefaultDisplayContentLocked();
   9965         final int displayId = displayContent.getDisplayId();
   9966         ScreenRotationAnimation screenRotationAnimation =
   9967                 mAnimator.getScreenRotationAnimationLocked(displayId);
   9968         if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
   9969                 && screenRotationAnimation.hasScreenshot()) {
   9970             if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
   9971             // TODO(multidisplay): rotation on main screen only.
   9972             DisplayInfo displayInfo = displayContent.getDisplayInfo();
   9973             // Get rotation animation again, with new top window
   9974             boolean isDimming = displayContent.isDimming();
   9975             if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
   9976                 mExitAnimId = mEnterAnimId = 0;
   9977             }
   9978             if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
   9979                     mTransitionAnimationScale, displayInfo.logicalWidth,
   9980                         displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
   9981                 scheduleAnimationLocked();
   9982             } else {
   9983                 screenRotationAnimation.kill();
   9984                 screenRotationAnimation = null;
   9985                 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
   9986                 updateRotation = true;
   9987             }
   9988         } else {
   9989             if (screenRotationAnimation != null) {
   9990                 screenRotationAnimation.kill();
   9991                 screenRotationAnimation = null;
   9992                 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
   9993             }
   9994             updateRotation = true;
   9995         }
   9996 
   9997         mInputMonitor.thawInputDispatchingLw();
   9998 
   9999         boolean configChanged;
   10000 
   10001         // While the display is frozen we don't re-compute the orientation
   10002         // to avoid inconsistent states.  However, something interesting
   10003         // could have actually changed during that time so re-evaluate it
   10004         // now to catch that.
   10005         configChanged = updateOrientationFromAppTokensLocked(false);
   10006 
   10007         // A little kludge: a lot could have happened while the
   10008         // display was frozen, so now that we are coming back we
   10009         // do a gc so that any remote references the system
   10010         // processes holds on others can be released if they are
   10011         // no longer needed.
   10012         mH.removeMessages(H.FORCE_GC);
   10013         mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
   10014 
   10015         mScreenFrozenLock.release();
   10016 
   10017         if (updateRotation) {
   10018             if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
   10019             configChanged |= updateRotationUncheckedLocked(false);
   10020         }
   10021 
   10022         if (configChanged) {
   10023             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
   10024         }
   10025     }
   10026 
   10027     static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
   10028             DisplayMetrics dm) {
   10029         if (index < tokens.length) {
   10030             String str = tokens[index];
   10031             if (str != null && str.length() > 0) {
   10032                 try {
   10033                     int val = Integer.parseInt(str);
   10034                     return val;
   10035                 } catch (Exception e) {
   10036                 }
   10037             }
   10038         }
   10039         if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
   10040             return defDps;
   10041         }
   10042         int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
   10043         return val;
   10044     }
   10045 
   10046     void createWatermarkInTransaction() {
   10047         if (mWatermark != null) {
   10048             return;
   10049         }
   10050 
   10051         File file = new File("/system/etc/setup.conf");
   10052         FileInputStream in = null;
   10053         DataInputStream ind = null;
   10054         try {
   10055             in = new FileInputStream(file);
   10056             ind = new DataInputStream(in);
   10057             String line = ind.readLine();
   10058             if (line != null) {
   10059                 String[] toks = line.split("%");
   10060                 if (toks != null && toks.length > 0) {
   10061                     mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
   10062                             mRealDisplayMetrics, mFxSession, toks);
   10063                 }
   10064             }
   10065         } catch (FileNotFoundException e) {
   10066         } catch (IOException e) {
   10067         } finally {
   10068             if (ind != null) {
   10069                 try {
   10070                     ind.close();
   10071                 } catch (IOException e) {
   10072                 }
   10073             } else if (in != null) {
   10074                 try {
   10075                     in.close();
   10076                 } catch (IOException e) {
   10077                 }
   10078             }
   10079         }
   10080     }
   10081 
   10082     @Override
   10083     public void statusBarVisibilityChanged(int visibility) {
   10084         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
   10085                 != PackageManager.PERMISSION_GRANTED) {
   10086             throw new SecurityException("Caller does not hold permission "
   10087                     + android.Manifest.permission.STATUS_BAR);
   10088         }
   10089 
   10090         synchronized (mWindowMap) {
   10091             mLastStatusBarVisibility = visibility;
   10092             visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
   10093             updateStatusBarVisibilityLocked(visibility);
   10094         }
   10095     }
   10096 
   10097     // TOOD(multidisplay): StatusBar on multiple screens?
   10098     void updateStatusBarVisibilityLocked(int visibility) {
   10099         mInputManager.setSystemUiVisibility(visibility);
   10100         final WindowList windows = getDefaultWindowListLocked();
   10101         final int N = windows.size();
   10102         for (int i = 0; i < N; i++) {
   10103             WindowState ws = windows.get(i);
   10104             try {
   10105                 int curValue = ws.mSystemUiVisibility;
   10106                 int diff = curValue ^ visibility;
   10107                 // We are only interested in differences of one of the
   10108                 // clearable flags...
   10109                 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
   10110                 // ...if it has actually been cleared.
   10111                 diff &= ~visibility;
   10112                 int newValue = (curValue&~diff) | (visibility&diff);
   10113                 if (newValue != curValue) {
   10114                     ws.mSeq++;
   10115                     ws.mSystemUiVisibility = newValue;
   10116                 }
   10117                 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
   10118                     ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
   10119                             visibility, newValue, diff);
   10120                 }
   10121             } catch (RemoteException e) {
   10122                 // so sorry
   10123             }
   10124         }
   10125     }
   10126 
   10127     @Override
   10128     public void reevaluateStatusBarVisibility() {
   10129         synchronized (mWindowMap) {
   10130             int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
   10131             updateStatusBarVisibilityLocked(visibility);
   10132             performLayoutAndPlaceSurfacesLocked();
   10133         }
   10134     }
   10135 
   10136     @Override
   10137     public FakeWindow addFakeWindow(Looper looper,
   10138             InputEventReceiver.Factory inputEventReceiverFactory,
   10139             String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags,
   10140             boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) {
   10141         synchronized (mWindowMap) {
   10142             FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
   10143                     name, windowType,
   10144                     layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys,
   10145                     hasFocus, touchFullscreen);
   10146             int i=0;
   10147             while (i<mFakeWindows.size()) {
   10148                 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
   10149                     break;
   10150                 }
   10151             }
   10152             mFakeWindows.add(i, fw);
   10153             mInputMonitor.updateInputWindowsLw(true);
   10154             return fw;
   10155         }
   10156     }
   10157 
   10158     boolean removeFakeWindowLocked(FakeWindow window) {
   10159         synchronized (mWindowMap) {
   10160             if (mFakeWindows.remove(window)) {
   10161                 mInputMonitor.updateInputWindowsLw(true);
   10162                 return true;
   10163             }
   10164             return false;
   10165         }
   10166     }
   10167 
   10168     // It is assumed that this method is called only by InputMethodManagerService.
   10169     public void saveLastInputMethodWindowForTransition() {
   10170         synchronized (mWindowMap) {
   10171             // TODO(multidisplay): Pass in the displayID.
   10172             DisplayContent displayContent = getDefaultDisplayContentLocked();
   10173             if (mInputMethodWindow != null) {
   10174                 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
   10175             }
   10176         }
   10177     }
   10178 
   10179     @Override
   10180     public boolean hasNavigationBar() {
   10181         return mPolicy.hasNavigationBar();
   10182     }
   10183 
   10184     @Override
   10185     public void lockNow(Bundle options) {
   10186         mPolicy.lockNow(options);
   10187     }
   10188 
   10189     @Override
   10190     public boolean isSafeModeEnabled() {
   10191         return mSafeMode;
   10192     }
   10193 
   10194     void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
   10195         pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
   10196         mPolicy.dump("    ", pw, args);
   10197     }
   10198 
   10199     void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
   10200         pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
   10201         mAnimator.dumpLocked(pw, "    ", dumpAll);
   10202     }
   10203 
   10204     void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
   10205         pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
   10206         if (mTokenMap.size() > 0) {
   10207             pw.println("  All tokens:");
   10208             Iterator<WindowToken> it = mTokenMap.values().iterator();
   10209             while (it.hasNext()) {
   10210                 WindowToken token = it.next();
   10211                 pw.print("  "); pw.print(token);
   10212                 if (dumpAll) {
   10213                     pw.println(':');
   10214                     token.dump(pw, "    ");
   10215                 } else {
   10216                     pw.println();
   10217                 }
   10218             }
   10219         }
   10220         if (mWallpaperTokens.size() > 0) {
   10221             pw.println();
   10222             pw.println("  Wallpaper tokens:");
   10223             for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
   10224                 WindowToken token = mWallpaperTokens.get(i);
   10225                 pw.print("  Wallpaper #"); pw.print(i);
   10226                         pw.print(' '); pw.print(token);
   10227                 if (dumpAll) {
   10228                     pw.println(':');
   10229                     token.dump(pw, "    ");
   10230                 } else {
   10231                     pw.println();
   10232                 }
   10233             }
   10234         }
   10235         if (mFinishedStarting.size() > 0) {
   10236             pw.println();
   10237             pw.println("  Finishing start of application tokens:");
   10238             for (int i=mFinishedStarting.size()-1; i>=0; i--) {
   10239                 WindowToken token = mFinishedStarting.get(i);
   10240                 pw.print("  Finished Starting #"); pw.print(i);
   10241                         pw.print(' '); pw.print(token);
   10242                 if (dumpAll) {
   10243                     pw.println(':');
   10244                     token.dump(pw, "    ");
   10245                 } else {
   10246                     pw.println();
   10247                 }
   10248             }
   10249         }
   10250         if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
   10251             pw.println();
   10252             if (mOpeningApps.size() > 0) {
   10253                 pw.print("  mOpeningApps="); pw.println(mOpeningApps);
   10254             }
   10255             if (mClosingApps.size() > 0) {
   10256                 pw.print("  mClosingApps="); pw.println(mClosingApps);
   10257             }
   10258         }
   10259     }
   10260 
   10261     void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
   10262         pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
   10263         if (mSessions.size() > 0) {
   10264             Iterator<Session> it = mSessions.iterator();
   10265             while (it.hasNext()) {
   10266                 Session s = it.next();
   10267                 pw.print("  Session "); pw.print(s); pw.println(':');
   10268                 s.dump(pw, "    ");
   10269             }
   10270         }
   10271     }
   10272 
   10273     void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
   10274         pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
   10275         if (mDisplayReady) {
   10276             final int numDisplays = mDisplayContents.size();
   10277             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   10278                 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
   10279                 displayContent.dump("  ", pw);
   10280             }
   10281         } else {
   10282             pw.println("  NO DISPLAY");
   10283         }
   10284     }
   10285 
   10286     void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
   10287             ArrayList<WindowState> windows) {
   10288         pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
   10289         dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
   10290     }
   10291 
   10292     void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
   10293             ArrayList<WindowState> windows) {
   10294         final int numDisplays = mDisplayContents.size();
   10295         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   10296             final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
   10297             for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
   10298                 final WindowState w = windowList.get(winNdx);
   10299                 if (windows == null || windows.contains(w)) {
   10300                     pw.print("  Window #"); pw.print(winNdx); pw.print(' ');
   10301                             pw.print(w); pw.println(":");
   10302                     w.dump(pw, "    ", dumpAll || windows != null);
   10303                 }
   10304             }
   10305         }
   10306         if (mInputMethodDialogs.size() > 0) {
   10307             pw.println();
   10308             pw.println("  Input method dialogs:");
   10309             for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
   10310                 WindowState w = mInputMethodDialogs.get(i);
   10311                 if (windows == null || windows.contains(w)) {
   10312                     pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
   10313                 }
   10314             }
   10315         }
   10316         if (mPendingRemove.size() > 0) {
   10317             pw.println();
   10318             pw.println("  Remove pending for:");
   10319             for (int i=mPendingRemove.size()-1; i>=0; i--) {
   10320                 WindowState w = mPendingRemove.get(i);
   10321                 if (windows == null || windows.contains(w)) {
   10322                     pw.print("  Remove #"); pw.print(i); pw.print(' ');
   10323                             pw.print(w);
   10324                     if (dumpAll) {
   10325                         pw.println(":");
   10326                         w.dump(pw, "    ", true);
   10327                     } else {
   10328                         pw.println();
   10329                     }
   10330                 }
   10331             }
   10332         }
   10333         if (mForceRemoves != null && mForceRemoves.size() > 0) {
   10334             pw.println();
   10335             pw.println("  Windows force removing:");
   10336             for (int i=mForceRemoves.size()-1; i>=0; i--) {
   10337                 WindowState w = mForceRemoves.get(i);
   10338                 pw.print("  Removing #"); pw.print(i); pw.print(' ');
   10339                         pw.print(w);
   10340                 if (dumpAll) {
   10341                     pw.println(":");
   10342                     w.dump(pw, "    ", true);
   10343                 } else {
   10344                     pw.println();
   10345                 }
   10346             }
   10347         }
   10348         if (mDestroySurface.size() > 0) {
   10349             pw.println();
   10350             pw.println("  Windows waiting to destroy their surface:");
   10351             for (int i=mDestroySurface.size()-1; i>=0; i--) {
   10352                 WindowState w = mDestroySurface.get(i);
   10353                 if (windows == null || windows.contains(w)) {
   10354                     pw.print("  Destroy #"); pw.print(i); pw.print(' ');
   10355                             pw.print(w);
   10356                     if (dumpAll) {
   10357                         pw.println(":");
   10358                         w.dump(pw, "    ", true);
   10359                     } else {
   10360                         pw.println();
   10361                     }
   10362                 }
   10363             }
   10364         }
   10365         if (mLosingFocus.size() > 0) {
   10366             pw.println();
   10367             pw.println("  Windows losing focus:");
   10368             for (int i=mLosingFocus.size()-1; i>=0; i--) {
   10369                 WindowState w = mLosingFocus.get(i);
   10370                 if (windows == null || windows.contains(w)) {
   10371                     pw.print("  Losing #"); pw.print(i); pw.print(' ');
   10372                             pw.print(w);
   10373                     if (dumpAll) {
   10374                         pw.println(":");
   10375                         w.dump(pw, "    ", true);
   10376                     } else {
   10377                         pw.println();
   10378                     }
   10379                 }
   10380             }
   10381         }
   10382         if (mResizingWindows.size() > 0) {
   10383             pw.println();
   10384             pw.println("  Windows waiting to resize:");
   10385             for (int i=mResizingWindows.size()-1; i>=0; i--) {
   10386                 WindowState w = mResizingWindows.get(i);
   10387                 if (windows == null || windows.contains(w)) {
   10388                     pw.print("  Resizing #"); pw.print(i); pw.print(' ');
   10389                             pw.print(w);
   10390                     if (dumpAll) {
   10391                         pw.println(":");
   10392                         w.dump(pw, "    ", true);
   10393                     } else {
   10394                         pw.println();
   10395                     }
   10396                 }
   10397             }
   10398         }
   10399         if (mWaitingForDrawn.size() > 0) {
   10400             pw.println();
   10401             pw.println("  Clients waiting for these windows to be drawn:");
   10402             for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
   10403                 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i);
   10404                 pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first);
   10405                         pw.print(": "); pw.println(pair.second);
   10406             }
   10407         }
   10408         pw.println();
   10409         pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
   10410         pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
   10411         if (mLastFocus != mCurrentFocus) {
   10412             pw.print("  mLastFocus="); pw.println(mLastFocus);
   10413         }
   10414         pw.print("  mFocusedApp="); pw.println(mFocusedApp);
   10415         if (mInputMethodTarget != null) {
   10416             pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
   10417         }
   10418         pw.print("  mInTouchMode="); pw.print(mInTouchMode);
   10419                 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
   10420         pw.print("  mLastDisplayFreezeDuration=");
   10421                 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
   10422                 if ( mLastFinishedFreezeSource != null) {
   10423                     pw.print(" due to ");
   10424                     pw.print(mLastFinishedFreezeSource);
   10425                 }
   10426                 pw.println();
   10427         if (dumpAll) {
   10428             pw.print("  mSystemDecorLayer="); pw.print(mSystemDecorLayer);
   10429                     pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
   10430             if (mLastStatusBarVisibility != 0) {
   10431                 pw.print("  mLastStatusBarVisibility=0x");
   10432                         pw.println(Integer.toHexString(mLastStatusBarVisibility));
   10433             }
   10434             if (mInputMethodWindow != null) {
   10435                 pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
   10436             }
   10437             pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
   10438             if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
   10439                 pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
   10440                 pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
   10441             }
   10442             pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
   10443                     pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
   10444             if (mInputMethodAnimLayerAdjustment != 0 ||
   10445                     mWallpaperAnimLayerAdjustment != 0) {
   10446                 pw.print("  mInputMethodAnimLayerAdjustment=");
   10447                         pw.print(mInputMethodAnimLayerAdjustment);
   10448                         pw.print("  mWallpaperAnimLayerAdjustment=");
   10449                         pw.println(mWallpaperAnimLayerAdjustment);
   10450             }
   10451             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
   10452                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
   10453             if (needsLayout()) {
   10454                 pw.print("  layoutNeeded on displays=");
   10455                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   10456                     final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
   10457                     if (displayContent.layoutNeeded) {
   10458                         pw.print(displayContent.getDisplayId());
   10459                     }
   10460                 }
   10461                 pw.println();
   10462             }
   10463             pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
   10464             pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
   10465                     pw.print(" windows="); pw.print(mWindowsFreezingScreen);
   10466                     pw.print(" client="); pw.print(mClientFreezingScreen);
   10467                     pw.print(" apps="); pw.print(mAppsFreezingScreen);
   10468                     pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
   10469             pw.print("  mRotation="); pw.print(mRotation);
   10470                     pw.print(" mAltOrientation="); pw.println(mAltOrientation);
   10471             pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
   10472                     pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
   10473             pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
   10474             pw.print("  mWindowAnimationScale="); pw.print(mWindowAnimationScale);
   10475                     pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale);
   10476                     pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale);
   10477             pw.print("  mTraversalScheduled="); pw.println(mTraversalScheduled);
   10478             pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
   10479                     pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
   10480             pw.println("  mLayoutToAnim:");
   10481             mAppTransition.dump(pw);
   10482         }
   10483     }
   10484 
   10485     boolean dumpWindows(PrintWriter pw, String name, String[] args,
   10486             int opti, boolean dumpAll) {
   10487         WindowList windows = new WindowList();
   10488         if ("visible".equals(name)) {
   10489             synchronized(mWindowMap) {
   10490                 final int numDisplays = mDisplayContents.size();
   10491                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   10492                     final WindowList windowList =
   10493                             mDisplayContents.valueAt(displayNdx).getWindowList();
   10494                     for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
   10495                         final WindowState w = windowList.get(winNdx);
   10496                         if (w.mWinAnimator.mSurfaceShown) {
   10497                             windows.add(w);
   10498                         }
   10499                     }
   10500                 }
   10501             }
   10502         } else {
   10503             int objectId = 0;
   10504             // See if this is an object ID.
   10505             try {
   10506                 objectId = Integer.parseInt(name, 16);
   10507                 name = null;
   10508             } catch (RuntimeException e) {
   10509             }
   10510             synchronized(mWindowMap) {
   10511                 final int numDisplays = mDisplayContents.size();
   10512                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   10513                     final WindowList windowList =
   10514                             mDisplayContents.valueAt(displayNdx).getWindowList();
   10515                     for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
   10516                         final WindowState w = windowList.get(winNdx);
   10517                         if (name != null) {
   10518                             if (w.mAttrs.getTitle().toString().contains(name)) {
   10519                                 windows.add(w);
   10520                             }
   10521                         } else if (System.identityHashCode(w) == objectId) {
   10522                             windows.add(w);
   10523                         }
   10524                     }
   10525                 }
   10526             }
   10527         }
   10528 
   10529         if (windows.size() <= 0) {
   10530             return false;
   10531         }
   10532 
   10533         synchronized(mWindowMap) {
   10534             dumpWindowsLocked(pw, dumpAll, windows);
   10535         }
   10536         return true;
   10537     }
   10538 
   10539     void dumpLastANRLocked(PrintWriter pw) {
   10540         pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
   10541         if (mLastANRState == null) {
   10542             pw.println("  <no ANR has occurred since boot>");
   10543         } else {
   10544             pw.println(mLastANRState);
   10545         }
   10546     }
   10547 
   10548     /**
   10549      * Saves information about the state of the window manager at
   10550      * the time an ANR occurred before anything else in the system changes
   10551      * in response.
   10552      *
   10553      * @param appWindowToken The application that ANR'd, may be null.
   10554      * @param windowState The window that ANR'd, may be null.
   10555      * @param reason The reason for the ANR, may be null.
   10556      */
   10557     public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
   10558             String reason) {
   10559         StringWriter sw = new StringWriter();
   10560         PrintWriter pw = new FastPrintWriter(sw, false, 1024);
   10561         pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
   10562         if (appWindowToken != null) {
   10563             pw.println("  Application at fault: " + appWindowToken.stringName);
   10564         }
   10565         if (windowState != null) {
   10566             pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
   10567         }
   10568         if (reason != null) {
   10569             pw.println("  Reason: " + reason);
   10570         }
   10571         pw.println();
   10572         dumpWindowsNoHeaderLocked(pw, true, null);
   10573         pw.close();
   10574         mLastANRState = sw.toString();
   10575     }
   10576 
   10577     @Override
   10578     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   10579         if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
   10580                 != PackageManager.PERMISSION_GRANTED) {
   10581             pw.println("Permission Denial: can't dump WindowManager from from pid="
   10582                     + Binder.getCallingPid()
   10583                     + ", uid=" + Binder.getCallingUid());
   10584             return;
   10585         }
   10586 
   10587         boolean dumpAll = false;
   10588 
   10589         int opti = 0;
   10590         while (opti < args.length) {
   10591             String opt = args[opti];
   10592             if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
   10593                 break;
   10594             }
   10595             opti++;
   10596             if ("-a".equals(opt)) {
   10597                 dumpAll = true;
   10598             } else if ("-h".equals(opt)) {
   10599                 pw.println("Window manager dump options:");
   10600                 pw.println("  [-a] [-h] [cmd] ...");
   10601                 pw.println("  cmd may be one of:");
   10602                 pw.println("    l[astanr]: last ANR information");
   10603                 pw.println("    p[policy]: policy state");
   10604                 pw.println("    a[animator]: animator state");
   10605                 pw.println("    s[essions]: active sessions");
   10606                 pw.println("    d[isplays]: active display contents");
   10607                 pw.println("    t[okens]: token list");
   10608                 pw.println("    w[indows]: window list");
   10609                 pw.println("  cmd may also be a NAME to dump windows.  NAME may");
   10610                 pw.println("    be a partial substring in a window name, a");
   10611                 pw.println("    Window hex object identifier, or");
   10612                 pw.println("    \"all\" for all windows, or");
   10613                 pw.println("    \"visible\" for the visible windows.");
   10614                 pw.println("  -a: include all available server state.");
   10615                 return;
   10616             } else {
   10617                 pw.println("Unknown argument: " + opt + "; use -h for help");
   10618             }
   10619         }
   10620 
   10621         // Is the caller requesting to dump a particular piece of data?
   10622         if (opti < args.length) {
   10623             String cmd = args[opti];
   10624             opti++;
   10625             if ("lastanr".equals(cmd) || "l".equals(cmd)) {
   10626                 synchronized(mWindowMap) {
   10627                     dumpLastANRLocked(pw);
   10628                 }
   10629                 return;
   10630             } else if ("policy".equals(cmd) || "p".equals(cmd)) {
   10631                 synchronized(mWindowMap) {
   10632                     dumpPolicyLocked(pw, args, true);
   10633                 }
   10634                 return;
   10635             } else if ("animator".equals(cmd) || "a".equals(cmd)) {
   10636                 synchronized(mWindowMap) {
   10637                     dumpAnimatorLocked(pw, args, true);
   10638                 }
   10639                 return;
   10640             } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
   10641                 synchronized(mWindowMap) {
   10642                     dumpSessionsLocked(pw, true);
   10643                 }
   10644                 return;
   10645             } else if ("displays".equals(cmd) || "d".equals(cmd)) {
   10646                 synchronized(mWindowMap) {
   10647                     dumpDisplayContentsLocked(pw, true);
   10648                 }
   10649                 return;
   10650             } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
   10651                 synchronized(mWindowMap) {
   10652                     dumpTokensLocked(pw, true);
   10653                 }
   10654                 return;
   10655             } else if ("windows".equals(cmd) || "w".equals(cmd)) {
   10656                 synchronized(mWindowMap) {
   10657                     dumpWindowsLocked(pw, true, null);
   10658                 }
   10659                 return;
   10660             } else if ("all".equals(cmd) || "a".equals(cmd)) {
   10661                 synchronized(mWindowMap) {
   10662                     dumpWindowsLocked(pw, true, null);
   10663                 }
   10664                 return;
   10665             } else {
   10666                 // Dumping a single name?
   10667                 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
   10668                     pw.println("Bad window command, or no windows match: " + cmd);
   10669                     pw.println("Use -h for help.");
   10670                 }
   10671                 return;
   10672             }
   10673         }
   10674 
   10675         synchronized(mWindowMap) {
   10676             pw.println();
   10677             if (dumpAll) {
   10678                 pw.println("-------------------------------------------------------------------------------");
   10679             }
   10680             dumpLastANRLocked(pw);
   10681             pw.println();
   10682             if (dumpAll) {
   10683                 pw.println("-------------------------------------------------------------------------------");
   10684             }
   10685             dumpPolicyLocked(pw, args, dumpAll);
   10686             pw.println();
   10687             if (dumpAll) {
   10688                 pw.println("-------------------------------------------------------------------------------");
   10689             }
   10690             dumpAnimatorLocked(pw, args, dumpAll);
   10691             pw.println();
   10692             if (dumpAll) {
   10693                 pw.println("-------------------------------------------------------------------------------");
   10694             }
   10695             dumpSessionsLocked(pw, dumpAll);
   10696             pw.println();
   10697             if (dumpAll) {
   10698                 pw.println("-------------------------------------------------------------------------------");
   10699             }
   10700             dumpDisplayContentsLocked(pw, dumpAll);
   10701             pw.println();
   10702             if (dumpAll) {
   10703                 pw.println("-------------------------------------------------------------------------------");
   10704             }
   10705             dumpTokensLocked(pw, dumpAll);
   10706             pw.println();
   10707             if (dumpAll) {
   10708                 pw.println("-------------------------------------------------------------------------------");
   10709             }
   10710             dumpWindowsLocked(pw, dumpAll, null);
   10711         }
   10712     }
   10713 
   10714     // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
   10715     @Override
   10716     public void monitor() {
   10717         synchronized (mWindowMap) { }
   10718     }
   10719 
   10720     public interface OnHardKeyboardStatusChangeListener {
   10721         public void onHardKeyboardStatusChange(boolean available, boolean enabled);
   10722     }
   10723 
   10724     void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
   10725         if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
   10726             Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
   10727                     Integer.toHexString(pendingLayoutChanges));
   10728         }
   10729     }
   10730 
   10731     private DisplayContent newDisplayContentLocked(final Display display) {
   10732         DisplayContent displayContent = new DisplayContent(display, this);
   10733         final int displayId = display.getDisplayId();
   10734         mDisplayContents.put(displayId, displayContent);
   10735 
   10736         DisplayInfo displayInfo = displayContent.getDisplayInfo();
   10737         final Rect rect = new Rect();
   10738         mDisplaySettings.getOverscanLocked(displayInfo.name, rect);
   10739         synchronized (displayContent.mDisplaySizeLock) {
   10740             displayInfo.overscanLeft = rect.left;
   10741             displayInfo.overscanTop = rect.top;
   10742             displayInfo.overscanRight = rect.right;
   10743             displayInfo.overscanBottom = rect.bottom;
   10744             mDisplayManagerService.setDisplayInfoOverrideFromWindowManager(
   10745                     displayId, displayInfo);
   10746         }
   10747         configureDisplayPolicyLocked(displayContent);
   10748 
   10749         // TODO: Create an input channel for each display with touch capability.
   10750         if (displayId == Display.DEFAULT_DISPLAY) {
   10751             displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent);
   10752             registerPointerEventListener(displayContent.mTapDetector);
   10753         }
   10754 
   10755         return displayContent;
   10756     }
   10757 
   10758     public void createDisplayContentLocked(final Display display) {
   10759         if (display == null) {
   10760             throw new IllegalArgumentException("getDisplayContent: display must not be null");
   10761         }
   10762         getDisplayContentLocked(display.getDisplayId());
   10763     }
   10764 
   10765     /**
   10766      * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
   10767      * there is a Display for the displayId.
   10768      * @param displayId The display the caller is interested in.
   10769      * @return The DisplayContent associated with displayId or null if there is no Display for it.
   10770      */
   10771     public DisplayContent getDisplayContentLocked(final int displayId) {
   10772         DisplayContent displayContent = mDisplayContents.get(displayId);
   10773         if (displayContent == null) {
   10774             final Display display = mDisplayManager.getDisplay(displayId);
   10775             if (display != null) {
   10776                 displayContent = newDisplayContentLocked(display);
   10777             }
   10778         }
   10779         return displayContent;
   10780     }
   10781 
   10782     // There is an inherent assumption that this will never return null.
   10783     public DisplayContent getDefaultDisplayContentLocked() {
   10784         return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
   10785     }
   10786 
   10787     public WindowList getDefaultWindowListLocked() {
   10788         return getDefaultDisplayContentLocked().getWindowList();
   10789     }
   10790 
   10791     public DisplayInfo getDefaultDisplayInfoLocked() {
   10792         return getDefaultDisplayContentLocked().getDisplayInfo();
   10793     }
   10794 
   10795     /**
   10796      * Return the list of WindowStates associated on the passed display.
   10797      * @param display The screen to return windows from.
   10798      * @return The list of WindowStates on the screen, or null if the there is no screen.
   10799      */
   10800     public WindowList getWindowListLocked(final Display display) {
   10801         return getWindowListLocked(display.getDisplayId());
   10802     }
   10803 
   10804     /**
   10805      * Return the list of WindowStates associated on the passed display.
   10806      * @param displayId The screen to return windows from.
   10807      * @return The list of WindowStates on the screen, or null if the there is no screen.
   10808      */
   10809     public WindowList getWindowListLocked(final int displayId) {
   10810         final DisplayContent displayContent = getDisplayContentLocked(displayId);
   10811         return displayContent != null ? displayContent.getWindowList() : null;
   10812     }
   10813 
   10814     @Override
   10815     public void onDisplayAdded(int displayId) {
   10816         mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
   10817     }
   10818 
   10819     private void handleDisplayAddedLocked(int displayId) {
   10820         final Display display = mDisplayManager.getDisplay(displayId);
   10821         if (display != null) {
   10822             createDisplayContentLocked(display);
   10823             displayReady(displayId);
   10824         }
   10825     }
   10826 
   10827     @Override
   10828     public void onDisplayRemoved(int displayId) {
   10829         mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
   10830     }
   10831 
   10832     private void handleDisplayRemovedLocked(int displayId) {
   10833         final DisplayContent displayContent = getDisplayContentLocked(displayId);
   10834         if (displayContent != null) {
   10835             mDisplayContents.delete(displayId);
   10836             displayContent.close();
   10837             if (displayId == Display.DEFAULT_DISPLAY) {
   10838                 unregisterPointerEventListener(displayContent.mTapDetector);
   10839             }
   10840             WindowList windows = displayContent.getWindowList();
   10841             while (!windows.isEmpty()) {
   10842                 final WindowState win = windows.get(windows.size() - 1);
   10843                 removeWindowLocked(win.mSession, win);
   10844             }
   10845         }
   10846         mAnimator.removeDisplayLocked(displayId);
   10847     }
   10848 
   10849     @Override
   10850     public void onDisplayChanged(int displayId) {
   10851         mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
   10852     }
   10853 
   10854     private void handleDisplayChangedLocked(int displayId) {
   10855         final DisplayContent displayContent = getDisplayContentLocked(displayId);
   10856         if (displayContent != null) {
   10857             displayContent.updateDisplayInfo();
   10858         }
   10859     }
   10860 
   10861     @Override
   10862     public Object getWindowManagerLock() {
   10863         return mWindowMap;
   10864     }
   10865 }
   10866