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