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