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