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