Home | History | Annotate | Download | only in wm
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.wm;
     18 
     19 import static android.view.WindowManager.LayoutParams.*;
     20 
     21 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
     22 import android.app.AppOpsManager;
     23 import android.os.Build;
     24 import android.os.SystemService;
     25 import android.util.ArraySet;
     26 import android.util.TimeUtils;
     27 import android.view.IWindowId;
     28 
     29 import android.view.IWindowSessionCallback;
     30 import android.view.WindowContentFrameStats;
     31 import com.android.internal.app.IBatteryStats;
     32 import com.android.internal.policy.PolicyManager;
     33 import com.android.internal.policy.impl.PhoneWindowManager;
     34 import com.android.internal.util.FastPrintWriter;
     35 import com.android.internal.view.IInputContext;
     36 import com.android.internal.view.IInputMethodClient;
     37 import com.android.internal.view.IInputMethodManager;
     38 import com.android.internal.view.WindowManagerPolicyThread;
     39 import com.android.server.AttributeCache;
     40 import com.android.server.DisplayThread;
     41 import com.android.server.EventLogTags;
     42 import com.android.server.LocalServices;
     43 import com.android.server.UiThread;
     44 import com.android.server.Watchdog;
     45 import com.android.server.am.BatteryStatsService;
     46 import com.android.server.input.InputManagerService;
     47 import com.android.server.power.ShutdownThread;
     48 
     49 import android.Manifest;
     50 import android.app.ActivityManagerNative;
     51 import android.app.IActivityManager;
     52 import android.app.StatusBarManager;
     53 import android.app.admin.DevicePolicyManager;
     54 import android.animation.ValueAnimator;
     55 import android.content.BroadcastReceiver;
     56 import android.content.ContentResolver;
     57 import android.content.Context;
     58 import android.content.Intent;
     59 import android.content.IntentFilter;
     60 import android.content.pm.ActivityInfo;
     61 import android.content.pm.PackageManager;
     62 import android.content.res.CompatibilityInfo;
     63 import android.content.res.Configuration;
     64 import android.database.ContentObserver;
     65 import android.graphics.Bitmap;
     66 import android.graphics.Bitmap.Config;
     67 import android.graphics.Canvas;
     68 import android.graphics.Matrix;
     69 import android.graphics.PixelFormat;
     70 import android.graphics.Point;
     71 import android.graphics.Rect;
     72 import android.graphics.RectF;
     73 import android.graphics.Region;
     74 import android.hardware.display.DisplayManager;
     75 import android.hardware.display.DisplayManagerInternal;
     76 import android.net.Uri;
     77 import android.os.Binder;
     78 import android.os.Bundle;
     79 import android.os.Debug;
     80 import android.os.Handler;
     81 import android.os.IBinder;
     82 import android.os.IRemoteCallback;
     83 import android.os.Looper;
     84 import android.os.Message;
     85 import android.os.Parcel;
     86 import android.os.ParcelFileDescriptor;
     87 import android.os.PowerManager;
     88 import android.os.PowerManagerInternal;
     89 import android.os.Process;
     90 import android.os.RemoteException;
     91 import android.os.ServiceManager;
     92 import android.os.StrictMode;
     93 import android.os.SystemClock;
     94 import android.os.SystemProperties;
     95 import android.os.Trace;
     96 import android.os.UserHandle;
     97 import android.os.WorkSource;
     98 import android.provider.Settings;
     99 import android.util.DisplayMetrics;
    100 import android.util.EventLog;
    101 import android.util.Log;
    102 import android.util.SparseArray;
    103 import android.util.Pair;
    104 import android.util.Slog;
    105 import android.util.SparseIntArray;
    106 import android.util.TypedValue;
    107 import android.view.Choreographer;
    108 import android.view.Display;
    109 import android.view.DisplayInfo;
    110 import android.view.Gravity;
    111 import android.view.IApplicationToken;
    112 import android.view.IInputFilter;
    113 import android.view.IOnKeyguardExitResult;
    114 import android.view.IRotationWatcher;
    115 import android.view.IWindow;
    116 import android.view.IWindowManager;
    117 import android.view.IWindowSession;
    118 import android.view.InputChannel;
    119 import android.view.InputDevice;
    120 import android.view.InputEvent;
    121 import android.view.InputEventReceiver;
    122 import android.view.KeyEvent;
    123 import android.view.MagnificationSpec;
    124 import android.view.MotionEvent;
    125 import android.view.WindowManagerInternal;
    126 import android.view.Surface.OutOfResourcesException;
    127 import android.view.Surface;
    128 import android.view.SurfaceControl;
    129 import android.view.SurfaceSession;
    130 import android.view.View;
    131 import android.view.ViewTreeObserver;
    132 import android.view.WindowManager;
    133 import android.view.WindowManagerGlobal;
    134 import android.view.WindowManagerPolicy;
    135 import android.view.WindowManager.LayoutParams;
    136 import android.view.WindowManagerPolicy.FakeWindow;
    137 import android.view.WindowManagerPolicy.PointerEventListener;
    138 import android.view.animation.Animation;
    139 import android.view.animation.AnimationUtils;
    140 import android.view.animation.Transformation;
    141 
    142 import java.io.BufferedWriter;
    143 import java.io.DataInputStream;
    144 import java.io.File;
    145 import java.io.FileDescriptor;
    146 import java.io.FileInputStream;
    147 import java.io.FileNotFoundException;
    148 import java.io.IOException;
    149 import java.io.OutputStream;
    150 import java.io.OutputStreamWriter;
    151 import java.io.PrintWriter;
    152 import java.io.StringWriter;
    153 import java.net.Socket;
    154 import java.text.DateFormat;
    155 import java.util.ArrayList;
    156 import java.util.Date;
    157 import java.util.HashMap;
    158 import java.util.Iterator;
    159 import java.util.List;
    160 
    161 /** {@hide} */
    162 public class WindowManagerService extends IWindowManager.Stub
    163         implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    164     static final String TAG = "WindowManager";
    165     static final boolean DEBUG = false;
    166     static final boolean DEBUG_ADD_REMOVE = false;
    167     static final boolean DEBUG_FOCUS = false;
    168     static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false;
    169     static final boolean DEBUG_ANIM = false;
    170     static final boolean DEBUG_KEYGUARD = false;
    171     static final boolean DEBUG_LAYOUT = false;
    172     static final boolean DEBUG_RESIZE = false;
    173     static final boolean DEBUG_LAYERS = false;
    174     static final boolean DEBUG_INPUT = false;
    175     static final boolean DEBUG_INPUT_METHOD = false;
    176     static final boolean DEBUG_VISIBILITY = false;
    177     static final boolean DEBUG_WINDOW_MOVEMENT = false;
    178     static final boolean DEBUG_TOKEN_MOVEMENT = false;
    179     static final boolean DEBUG_ORIENTATION = false;
    180     static final boolean DEBUG_APP_ORIENTATION = false;
    181     static final boolean DEBUG_CONFIGURATION = false;
    182     static final boolean DEBUG_APP_TRANSITIONS = false;
    183     static final boolean DEBUG_STARTING_WINDOW = false;
    184     static final boolean DEBUG_REORDER = false;
    185     static final boolean DEBUG_WALLPAPER = false;
    186     static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
    187     static final boolean DEBUG_DRAG = false;
    188     static final boolean DEBUG_SCREEN_ON = false;
    189     static final boolean DEBUG_SCREENSHOT = false;
    190     static final boolean DEBUG_BOOT = false;
    191     static final boolean DEBUG_LAYOUT_REPEATS = true;
    192     static final boolean DEBUG_SURFACE_TRACE = false;
    193     static final boolean DEBUG_WINDOW_TRACE = false;
    194     static final boolean DEBUG_TASK_MOVEMENT = false;
    195     static final boolean DEBUG_STACK = false;
    196     static final boolean DEBUG_DISPLAY = false;
    197     static final boolean SHOW_SURFACE_ALLOC = false;
    198     static final boolean SHOW_TRANSACTIONS = false;
    199     static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
    200     static final boolean HIDE_STACK_CRAWLS = true;
    201     static final int LAYOUT_REPEAT_THRESHOLD = 4;
    202 
    203     static final boolean PROFILE_ORIENTATION = false;
    204     static final boolean localLOGV = DEBUG;
    205 
    206     /** How much to multiply the policy's type layer, to reserve room
    207      * for multiple windows of the same type and Z-ordering adjustment
    208      * with TYPE_LAYER_OFFSET. */
    209     static final int TYPE_LAYER_MULTIPLIER = 10000;
    210 
    211     /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
    212      * or below others in the same layer. */
    213     static final int TYPE_LAYER_OFFSET = 1000;
    214 
    215     /** How much to increment the layer for each window, to reserve room
    216      * for effect surfaces between them.
    217      */
    218     static final int WINDOW_LAYER_MULTIPLIER = 5;
    219 
    220     /**
    221      * Dim surface layer is immediately below target window.
    222      */
    223     static final int LAYER_OFFSET_DIM = 1;
    224 
    225     /**
    226      * Blur surface layer is immediately below dim layer.
    227      */
    228     static final int LAYER_OFFSET_BLUR = 2;
    229 
    230     /**
    231      * FocusedStackFrame layer is immediately above focused window.
    232      */
    233     static final int LAYER_OFFSET_FOCUSED_STACK = 1;
    234 
    235     /**
    236      * Animation thumbnail is as far as possible below the window above
    237      * the thumbnail (or in other words as far as possible above the window
    238      * below it).
    239      */
    240     static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1;
    241 
    242     /**
    243      * Layer at which to put the rotation freeze snapshot.
    244      */
    245     static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1;
    246 
    247     /**
    248      * Layer at which to put the mask for emulated screen sizes.
    249      */
    250     static final int MASK_LAYER = TYPE_LAYER_MULTIPLIER * 200;
    251 
    252     /** The maximum length we will accept for a loaded animation duration:
    253      * this is 10 seconds.
    254      */
    255     static final int MAX_ANIMATION_DURATION = 10*1000;
    256 
    257     /** Amount of time (in milliseconds) to animate the fade-in-out transition for
    258      * compatible windows.
    259      */
    260     static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
    261 
    262     /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
    263     static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
    264 
    265     /** Amount of time to allow a last ANR message to exist before freeing the memory. */
    266     static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours
    267     /**
    268      * If true, the window manager will do its own custom freezing and general
    269      * management of the screen during rotation.
    270      */
    271     static final boolean CUSTOM_SCREEN_ROTATION = true;
    272 
    273     // Maximum number of milliseconds to wait for input devices to be enumerated before
    274     // proceding with safe mode detection.
    275     private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
    276 
    277     // Default input dispatching timeout in nanoseconds.
    278     static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
    279 
    280     // Poll interval in milliseconds for watching boot animation finished.
    281     private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
    282 
    283     // The name of the boot animation service in init.rc.
    284     private static final String BOOT_ANIMATION_SERVICE = "bootanim";
    285 
    286     /** Minimum value for attachStack and resizeStack weight value */
    287     public static final float STACK_WEIGHT_MIN = 0.2f;
    288 
    289     /** Maximum value for attachStack and resizeStack weight value */
    290     public static final float STACK_WEIGHT_MAX = 0.8f;
    291 
    292     static final int UPDATE_FOCUS_NORMAL = 0;
    293     static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
    294     static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
    295     static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
    296 
    297     private static final String SYSTEM_SECURE = "ro.secure";
    298     private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
    299 
    300     private static final String DENSITY_OVERRIDE = "ro.config.density_override";
    301     private static final String SIZE_OVERRIDE = "ro.config.size_override";
    302 
    303     private static final int MAX_SCREENSHOT_RETRIES = 3;
    304 
    305     // The flag describing a full screen app window (where the app takes care of drawing under the
    306     // SystemUI bars)
    307     private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
    308             View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
    309 
    310     private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
    311 
    312     final private KeyguardDisableHandler mKeyguardDisableHandler;
    313 
    314     final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    315         @Override
    316         public void onReceive(Context context, Intent intent) {
    317             final String action = intent.getAction();
    318             if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
    319                 mKeyguardDisableHandler.sendEmptyMessage(
    320                     KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED);
    321             }
    322         }
    323     };
    324 
    325     /**
    326      * Current user when multi-user is enabled. Don't show windows of
    327      * non-current user. Also see mCurrentProfileIds.
    328      */
    329     int mCurrentUserId;
    330     /**
    331      * Users that are profiles of the current user. These are also allowed to show windows
    332      * on the current user.
    333      */
    334     int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER};
    335 
    336     final Context mContext;
    337 
    338     final boolean mHaveInputMethods;
    339 
    340     final boolean mHasPermanentDpad;
    341 
    342     final boolean mAllowBootMessages;
    343 
    344     final boolean mLimitedAlphaCompositing;
    345 
    346     final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
    347 
    348     final IActivityManager mActivityManager;
    349 
    350     final IBatteryStats mBatteryStats;
    351 
    352     final AppOpsManager mAppOps;
    353 
    354     final DisplaySettings mDisplaySettings;
    355 
    356     /**
    357      * All currently active sessions with clients.
    358      */
    359     final ArraySet<Session> mSessions = new ArraySet<Session>();
    360 
    361     /**
    362      * Mapping from an IWindow IBinder to the server's Window object.
    363      * This is also used as the lock for all of our state.
    364      * NOTE: Never call into methods that lock ActivityManagerService while holding this object.
    365      */
    366     final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
    367 
    368     /**
    369      * Mapping from a token IBinder to a WindowToken object.
    370      */
    371     final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>();
    372 
    373     /**
    374      * List of window tokens that have finished starting their application,
    375      * and now need to have the policy remove their windows.
    376      */
    377     final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
    378 
    379     /**
    380      * Fake windows added to the window manager.  Note: ordered from top to
    381      * bottom, opposite of mWindows.
    382      */
    383     final ArrayList<FakeWindowImpl> mFakeWindows = new ArrayList<FakeWindowImpl>();
    384 
    385     /**
    386      * Windows that are being resized.  Used so we can tell the client about
    387      * the resize after closing the transaction in which we resized the
    388      * underlying surface.
    389      */
    390     final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
    391 
    392     /**
    393      * Windows whose animations have ended and now must be removed.
    394      */
    395     final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
    396 
    397     /**
    398      * Stacks whose animations have ended and whose tasks, apps, selves may now be removed.
    399      */
    400     final ArraySet<TaskStack> mPendingStacksRemove = new ArraySet<TaskStack>();
    401 
    402     /**
    403      * Used when processing mPendingRemove to avoid working on the original array.
    404      */
    405     WindowState[] mPendingRemoveTmp = new WindowState[20];
    406 
    407     /**
    408      * Windows whose surface should be destroyed.
    409      */
    410     final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
    411 
    412     /**
    413      * Windows that have lost input focus and are waiting for the new
    414      * focus window to be displayed before they are told about this.
    415      */
    416     ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
    417 
    418     /**
    419      * This is set when we have run out of memory, and will either be an empty
    420      * list or contain windows that need to be force removed.
    421      */
    422     ArrayList<WindowState> mForceRemoves;
    423 
    424     /**
    425      * Windows that clients are waiting to have drawn.
    426      */
    427     ArrayList<WindowState> mWaitingForDrawn = new ArrayList<WindowState>();
    428     /**
    429      * And the callback to make when they've all been drawn.
    430      */
    431     Runnable mWaitingForDrawnCallback;
    432 
    433     /**
    434      * Windows that have called relayout() while we were running animations,
    435      * so we need to tell when the animation is done.
    436      */
    437     final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>();
    438 
    439     /**
    440      * Used when rebuilding window list to keep track of windows that have
    441      * been removed.
    442      */
    443     WindowState[] mRebuildTmp = new WindowState[20];
    444 
    445     /**
    446      * Stores for each user whether screencapture is disabled
    447      * This array is essentially a cache for all userId for
    448      * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled}
    449      */
    450     SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<Boolean>();
    451 
    452     IInputMethodManager mInputMethodManager;
    453 
    454     AccessibilityController mAccessibilityController;
    455 
    456     final SurfaceSession mFxSession;
    457     Watermark mWatermark;
    458     StrictModeFlash mStrictModeFlash;
    459     CircularDisplayMask mCircularDisplayMask;
    460     EmulatorDisplayOverlay mEmulatorDisplayOverlay;
    461     FocusedStackFrame mFocusedStackFrame;
    462 
    463     int mFocusedStackLayer;
    464 
    465     final float[] mTmpFloats = new float[9];
    466     final Rect mTmpContentRect = new Rect();
    467 
    468     boolean mDisplayReady;
    469     boolean mSafeMode;
    470     boolean mDisplayEnabled = false;
    471     boolean mSystemBooted = false;
    472     boolean mForceDisplayEnabled = false;
    473     boolean mShowingBootMessages = false;
    474     boolean mBootAnimationStopped = false;
    475 
    476     String mLastANRState;
    477 
    478     /** All DisplayContents in the world, kept here */
    479     SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(2);
    480 
    481     int mRotation = 0;
    482     int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
    483     boolean mAltOrientation = false;
    484 
    485     private boolean mKeyguardWaitingForActivityDrawn;
    486 
    487     class RotationWatcher {
    488         IRotationWatcher watcher;
    489         IBinder.DeathRecipient deathRecipient;
    490         RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d) {
    491             watcher = w;
    492             deathRecipient = d;
    493         }
    494     }
    495     ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<RotationWatcher>();
    496     int mDeferredRotationPauseCount;
    497 
    498     int mSystemDecorLayer = 0;
    499     final Rect mScreenRect = new Rect();
    500 
    501     boolean mTraversalScheduled = false;
    502     boolean mDisplayFrozen = false;
    503     long mDisplayFreezeTime = 0;
    504     int mLastDisplayFreezeDuration = 0;
    505     Object mLastFinishedFreezeSource = null;
    506     boolean mWaitingForConfig = false;
    507     boolean mWindowsFreezingScreen = false;
    508     boolean mClientFreezingScreen = false;
    509     int mAppsFreezingScreen = 0;
    510     int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
    511 
    512     int mLayoutSeq = 0;
    513 
    514     int mLastStatusBarVisibility = 0;
    515 
    516     // State while inside of layoutAndPlaceSurfacesLocked().
    517     boolean mFocusMayChange;
    518 
    519     Configuration mCurConfiguration = new Configuration();
    520 
    521     // This is held as long as we have the screen frozen, to give us time to
    522     // perform a rotation animation when turning off shows the lock screen which
    523     // changes the orientation.
    524     private final PowerManager.WakeLock mScreenFrozenLock;
    525 
    526     final AppTransition mAppTransition;
    527     boolean mStartingIconInTransition = false;
    528     boolean mSkipAppTransitionAnimation = false;
    529 
    530     final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<AppWindowToken>();
    531     final ArraySet<AppWindowToken> mClosingApps = new ArraySet<AppWindowToken>();
    532 
    533     boolean mIsTouchDevice;
    534 
    535     final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
    536     final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
    537     final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
    538     final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
    539 
    540     final H mH = new H();
    541 
    542     final Choreographer mChoreographer = Choreographer.getInstance();
    543 
    544     WindowState mCurrentFocus = null;
    545     WindowState mLastFocus = null;
    546 
    547     /** This just indicates the window the input method is on top of, not
    548      * necessarily the window its input is going to. */
    549     WindowState mInputMethodTarget = null;
    550 
    551     /** If true hold off on modifying the animation layer of mInputMethodTarget */
    552     boolean mInputMethodTargetWaitingAnim;
    553     int mInputMethodAnimLayerAdjustment;
    554 
    555     WindowState mInputMethodWindow = null;
    556     final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
    557 
    558     boolean mHardKeyboardAvailable;
    559     boolean mShowImeWithHardKeyboard;
    560     OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
    561     SettingsObserver mSettingsObserver;
    562 
    563     private final class SettingsObserver extends ContentObserver {
    564         private final Uri mShowImeWithHardKeyboardUri =
    565                 Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
    566 
    567         private final Uri mDisplayInversionEnabledUri =
    568                 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
    569 
    570         public SettingsObserver() {
    571             super(new Handler());
    572             ContentResolver resolver = mContext.getContentResolver();
    573             resolver.registerContentObserver(mShowImeWithHardKeyboardUri, false, this);
    574             resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this);
    575         }
    576 
    577         @Override
    578         public void onChange(boolean selfChange, Uri uri) {
    579             if (mShowImeWithHardKeyboardUri.equals(uri)) {
    580                 updateShowImeWithHardKeyboard();
    581             } else if (mDisplayInversionEnabledUri.equals(uri)) {
    582                 updateCircularDisplayMaskIfNeeded();
    583             }
    584         }
    585     }
    586 
    587     final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
    588 
    589     // If non-null, this is the currently visible window that is associated
    590     // with the wallpaper.
    591     WindowState mWallpaperTarget = null;
    592     // If non-null, we are in the middle of animating from one wallpaper target
    593     // to another, and this is the lower one in Z-order.
    594     WindowState mLowerWallpaperTarget = null;
    595     // If non-null, we are in the middle of animating from one wallpaper target
    596     // to another, and this is the higher one in Z-order.
    597     WindowState mUpperWallpaperTarget = null;
    598     int mWallpaperAnimLayerAdjustment;
    599     float mLastWallpaperX = -1;
    600     float mLastWallpaperY = -1;
    601     float mLastWallpaperXStep = -1;
    602     float mLastWallpaperYStep = -1;
    603     int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE;
    604     int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE;
    605     // This is set when we are waiting for a wallpaper to tell us it is done
    606     // changing its scroll position.
    607     WindowState mWaitingOnWallpaper;
    608     // The last time we had a timeout when waiting for a wallpaper.
    609     long mLastWallpaperTimeoutTime;
    610     // We give a wallpaper up to 150ms to finish scrolling.
    611     static final long WALLPAPER_TIMEOUT = 150;
    612     // Time we wait after a timeout before trying to wait again.
    613     static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
    614     boolean mAnimateWallpaperWithTarget;
    615 
    616     AppWindowToken mFocusedApp = null;
    617 
    618     PowerManager mPowerManager;
    619     PowerManagerInternal mPowerManagerInternal;
    620 
    621     float mWindowAnimationScaleSetting = 1.0f;
    622     float mTransitionAnimationScaleSetting = 1.0f;
    623     float mAnimatorDurationScaleSetting = 1.0f;
    624     boolean mAnimationsDisabled = false;
    625 
    626     final InputManagerService mInputManager;
    627     final DisplayManagerInternal mDisplayManagerInternal;
    628     final DisplayManager mDisplayManager;
    629 
    630     // Who is holding the screen on.
    631     Session mHoldingScreenOn;
    632     PowerManager.WakeLock mHoldingScreenWakeLock;
    633 
    634     boolean mTurnOnScreen;
    635 
    636     // Whether or not a layout can cause a wake up when theater mode is enabled.
    637     boolean mAllowTheaterModeWakeFromLayout;
    638 
    639     DragState mDragState = null;
    640 
    641     // For frozen screen animations.
    642     int mExitAnimId, mEnterAnimId;
    643 
    644     /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple
    645      * methods. */
    646     class LayoutFields {
    647         static final int SET_UPDATE_ROTATION                = 1 << 0;
    648         static final int SET_WALLPAPER_MAY_CHANGE           = 1 << 1;
    649         static final int SET_FORCE_HIDING_CHANGED           = 1 << 2;
    650         static final int SET_ORIENTATION_CHANGE_COMPLETE    = 1 << 3;
    651         static final int SET_TURN_ON_SCREEN                 = 1 << 4;
    652         static final int SET_WALLPAPER_ACTION_PENDING       = 1 << 5;
    653 
    654         boolean mWallpaperForceHidingChanged = false;
    655         boolean mWallpaperMayChange = false;
    656         boolean mOrientationChangeComplete = true;
    657         Object mLastWindowFreezeSource = null;
    658         private Session mHoldScreen = null;
    659         private boolean mObscured = false;
    660         private boolean mSyswin = false;
    661         private float mScreenBrightness = -1;
    662         private float mButtonBrightness = -1;
    663         private long mUserActivityTimeout = -1;
    664         private boolean mUpdateRotation = false;
    665         boolean mWallpaperActionPending = false;
    666 
    667         // Set to true when the display contains content to show the user.
    668         // When false, the display manager may choose to mirror or blank the display.
    669         boolean mDisplayHasContent = false;
    670 
    671         // Only set while traversing the default display based on its content.
    672         // Affects the behavior of mirroring on secondary displays.
    673         boolean mObscureApplicationContentOnSecondaryDisplays = false;
    674 
    675         float mPreferredRefreshRate = 0;
    676     }
    677     final LayoutFields mInnerFields = new LayoutFields();
    678 
    679     boolean mAnimationScheduled;
    680 
    681     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
    682      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
    683     private int mTransactionSequence;
    684 
    685     /** Only do a maximum of 6 repeated layouts. After that quit */
    686     private int mLayoutRepeatCount;
    687 
    688     final WindowAnimator mAnimator;
    689 
    690     SparseArray<Task> mTaskIdToTask = new SparseArray<Task>();
    691 
    692     /** All of the TaskStacks in the window manager, unordered. For an ordered list call
    693      * DisplayContent.getStacks(). */
    694     SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>();
    695 
    696     private final PointerEventDispatcher mPointerEventDispatcher;
    697 
    698     private WindowContentFrameStats mTempWindowRenderStats;
    699 
    700     final class DragInputEventReceiver extends InputEventReceiver {
    701         public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
    702             super(inputChannel, looper);
    703         }
    704 
    705         @Override
    706         public void onInputEvent(InputEvent event) {
    707             boolean handled = false;
    708             try {
    709                 if (event instanceof MotionEvent
    710                         && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
    711                         && mDragState != null) {
    712                     final MotionEvent motionEvent = (MotionEvent)event;
    713                     boolean endDrag = false;
    714                     final float newX = motionEvent.getRawX();
    715                     final float newY = motionEvent.getRawY();
    716 
    717                     switch (motionEvent.getAction()) {
    718                     case MotionEvent.ACTION_DOWN: {
    719                         if (DEBUG_DRAG) {
    720                             Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer");
    721                         }
    722                     } break;
    723 
    724                     case MotionEvent.ACTION_MOVE: {
    725                         synchronized (mWindowMap) {
    726                             // move the surface and tell the involved window(s) where we are
    727                             mDragState.notifyMoveLw(newX, newY);
    728                         }
    729                     } break;
    730 
    731                     case MotionEvent.ACTION_UP: {
    732                         if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at "
    733                                 + newX + "," + newY);
    734                         synchronized (mWindowMap) {
    735                             endDrag = mDragState.notifyDropLw(newX, newY);
    736                         }
    737                     } break;
    738 
    739                     case MotionEvent.ACTION_CANCEL: {
    740                         if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!");
    741                         endDrag = true;
    742                     } break;
    743                     }
    744 
    745                     if (endDrag) {
    746                         if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state");
    747                         // tell all the windows that the drag has ended
    748                         synchronized (mWindowMap) {
    749                             mDragState.endDragLw();
    750                         }
    751                     }
    752 
    753                     handled = true;
    754                 }
    755             } catch (Exception e) {
    756                 Slog.e(TAG, "Exception caught by drag handleMotion", e);
    757             } finally {
    758                 finishInputEvent(event, handled);
    759             }
    760         }
    761     }
    762 
    763     /**
    764      * Whether the UI is currently running in touch mode (not showing
    765      * navigational focus because the user is directly pressing the screen).
    766      */
    767     boolean mInTouchMode;
    768 
    769     private ViewServer mViewServer;
    770     private final ArrayList<WindowChangeListener> mWindowChangeListeners =
    771         new ArrayList<WindowChangeListener>();
    772     private boolean mWindowsChanged = false;
    773 
    774     public interface WindowChangeListener {
    775         public void windowsChanged();
    776         public void focusChanged();
    777     }
    778 
    779     final Configuration mTempConfiguration = new Configuration();
    780 
    781     // The desired scaling factor for compatible apps.
    782     float mCompatibleScreenScale;
    783 
    784     // If true, only the core apps and services are being launched because the device
    785     // is in a special boot mode, such as being encrypted or waiting for a decryption password.
    786     // For example, when this flag is true, there will be no wallpaper service.
    787     final boolean mOnlyCore;
    788 
    789     public static WindowManagerService main(final Context context,
    790             final InputManagerService im,
    791             final boolean haveInputMethods, final boolean showBootMsgs,
    792             final boolean onlyCore) {
    793         final WindowManagerService[] holder = new WindowManagerService[1];
    794         DisplayThread.getHandler().runWithScissors(new Runnable() {
    795             @Override
    796             public void run() {
    797                 holder[0] = new WindowManagerService(context, im,
    798                         haveInputMethods, showBootMsgs, onlyCore);
    799             }
    800         }, 0);
    801         return holder[0];
    802     }
    803 
    804     private void initPolicy() {
    805         UiThread.getHandler().runWithScissors(new Runnable() {
    806             @Override
    807             public void run() {
    808                 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
    809 
    810                 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
    811                 mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer()
    812                         * TYPE_LAYER_MULTIPLIER
    813                         + TYPE_LAYER_OFFSET;
    814             }
    815         }, 0);
    816     }
    817 
    818     private WindowManagerService(Context context, InputManagerService inputManager,
    819             boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
    820         mContext = context;
    821         mHaveInputMethods = haveInputMethods;
    822         mAllowBootMessages = showBootMsgs;
    823         mOnlyCore = onlyCore;
    824         mLimitedAlphaCompositing = context.getResources().getBoolean(
    825                 com.android.internal.R.bool.config_sf_limitedAlpha);
    826         mHasPermanentDpad = context.getResources().getBoolean(
    827                 com.android.internal.R.bool.config_hasPermanentDpad);
    828         mInTouchMode = context.getResources().getBoolean(
    829                 com.android.internal.R.bool.config_defaultInTouchMode);
    830         mInputManager = inputManager; // Must be before createDisplayContentLocked.
    831         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
    832         mDisplaySettings = new DisplaySettings();
    833         mDisplaySettings.readSettingsLocked();
    834 
    835         LocalServices.addService(WindowManagerPolicy.class, mPolicy);
    836 
    837         mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG));
    838 
    839         mFxSession = new SurfaceSession();
    840         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
    841         Display[] displays = mDisplayManager.getDisplays();
    842         for (Display display : displays) {
    843             createDisplayContentLocked(display);
    844         }
    845 
    846         mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
    847 
    848         mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    849         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
    850         mPowerManagerInternal.registerLowPowerModeObserver(
    851                 new PowerManagerInternal.LowPowerModeListener() {
    852             @Override
    853             public void onLowPowerModeChanged(boolean enabled) {
    854                 synchronized (mWindowMap) {
    855                     if (mAnimationsDisabled != enabled) {
    856                         mAnimationsDisabled = enabled;
    857                         dispatchNewAnimatorScaleLocked(null);
    858                     }
    859                 }
    860             }
    861         });
    862         mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled();
    863         mScreenFrozenLock = mPowerManager.newWakeLock(
    864                 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
    865         mScreenFrozenLock.setReferenceCounted(false);
    866 
    867         mAppTransition = new AppTransition(context, mH);
    868 
    869         mActivityManager = ActivityManagerNative.getDefault();
    870         mBatteryStats = BatteryStatsService.getService();
    871         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
    872         AppOpsManager.OnOpChangedInternalListener opListener =
    873                 new AppOpsManager.OnOpChangedInternalListener() {
    874                     @Override public void onOpChanged(int op, String packageName) {
    875                         updateAppOpsState();
    876                     }
    877                 };
    878         mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, opListener);
    879         mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener);
    880 
    881         // Get persisted window scale setting
    882         mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
    883                 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
    884         mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
    885                 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting);
    886         setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
    887                 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
    888 
    889         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
    890         IntentFilter filter = new IntentFilter();
    891         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
    892         mContext.registerReceiver(mBroadcastReceiver, filter);
    893 
    894         mSettingsObserver = new SettingsObserver();
    895         updateShowImeWithHardKeyboard();
    896 
    897         mHoldingScreenWakeLock = mPowerManager.newWakeLock(
    898                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG);
    899         mHoldingScreenWakeLock.setReferenceCounted(false);
    900 
    901         mAnimator = new WindowAnimator(this);
    902 
    903         mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
    904                 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
    905 
    906         LocalServices.addService(WindowManagerInternal.class, new LocalService());
    907         initPolicy();
    908 
    909         // Add ourself to the Watchdog monitors.
    910         Watchdog.getInstance().addMonitor(this);
    911 
    912         SurfaceControl.openTransaction();
    913         try {
    914             createWatermarkInTransaction();
    915             mFocusedStackFrame = new FocusedStackFrame(
    916                     getDefaultDisplayContentLocked().getDisplay(), mFxSession);
    917         } finally {
    918             SurfaceControl.closeTransaction();
    919         }
    920 
    921         updateCircularDisplayMaskIfNeeded();
    922         showEmulatorDisplayOverlayIfNeeded();
    923     }
    924 
    925     public InputMonitor getInputMonitor() {
    926         return mInputMonitor;
    927     }
    928 
    929     @Override
    930     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
    931             throws RemoteException {
    932         try {
    933             return super.onTransact(code, data, reply, flags);
    934         } catch (RuntimeException e) {
    935             // The window manager only throws security exceptions, so let's
    936             // log all others.
    937             if (!(e instanceof SecurityException)) {
    938                 Slog.wtf(TAG, "Window Manager Crash", e);
    939             }
    940             throw e;
    941         }
    942     }
    943 
    944     private void placeWindowAfter(WindowState pos, WindowState window) {
    945         final WindowList windows = pos.getWindowList();
    946         final int i = windows.indexOf(pos);
    947         if (true || DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
    948             TAG, "Adding window " + window + " at "
    949             + (i+1) + " of " + windows.size() + " (after " + pos + ")");
    950         windows.add(i+1, window);
    951         mWindowsChanged = true;
    952     }
    953 
    954     private void placeWindowBefore(WindowState pos, WindowState window) {
    955         final WindowList windows = pos.getWindowList();
    956         int i = windows.indexOf(pos);
    957         if (true || DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
    958             TAG, "Adding window " + window + " at "
    959             + i + " of " + windows.size() + " (before " + pos + ")");
    960         if (i < 0) {
    961             Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows);
    962             i = 0;
    963         }
    964         windows.add(i, window);
    965         mWindowsChanged = true;
    966     }
    967 
    968     //This method finds out the index of a window that has the same app token as
    969     //win. used for z ordering the windows in mWindows
    970     private int findIdxBasedOnAppTokens(WindowState win) {
    971         WindowList windows = win.getWindowList();
    972         for(int j = windows.size() - 1; j >= 0; j--) {
    973             WindowState wentry = windows.get(j);
    974             if(wentry.mAppToken == win.mAppToken) {
    975                 return j;
    976             }
    977         }
    978         return -1;
    979     }
    980 
    981     /**
    982      * Return the list of Windows from the passed token on the given Display.
    983      * @param token The token with all the windows.
    984      * @param displayContent The display we are interested in.
    985      * @return List of windows from token that are on displayContent.
    986      */
    987     WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) {
    988         final WindowList windowList = new WindowList();
    989         final int count = token.windows.size();
    990         for (int i = 0; i < count; i++) {
    991             final WindowState win = token.windows.get(i);
    992             if (win.getDisplayContent() == displayContent) {
    993                 windowList.add(win);
    994             }
    995         }
    996         return windowList;
    997     }
    998 
    999     /**
   1000      * Recursive search through a WindowList and all of its windows' children.
   1001      * @param targetWin The window to search for.
   1002      * @param windows The list to search.
   1003      * @return The index of win in windows or of the window that is an ancestor of win.
   1004      */
   1005     private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) {
   1006         for (int i = windows.size() - 1; i >= 0; i--) {
   1007             final WindowState w = windows.get(i);
   1008             if (w == targetWin) {
   1009                 return i;
   1010             }
   1011             if (!w.mChildWindows.isEmpty()) {
   1012                 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) {
   1013                     return i;
   1014                 }
   1015             }
   1016         }
   1017         return -1;
   1018     }
   1019 
   1020     private int addAppWindowToListLocked(final WindowState win) {
   1021         final IWindow client = win.mClient;
   1022         final WindowToken token = win.mToken;
   1023         final DisplayContent displayContent = win.getDisplayContent();
   1024         if (displayContent == null) {
   1025             // It doesn't matter this display is going away.
   1026             return 0;
   1027         }
   1028 
   1029         final WindowList windows = win.getWindowList();
   1030         final int N = windows.size();
   1031         WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
   1032         int tokenWindowsPos = 0;
   1033         int windowListPos = tokenWindowList.size();
   1034         if (!tokenWindowList.isEmpty()) {
   1035             // If this application has existing windows, we
   1036             // simply place the new window on top of them... but
   1037             // keep the starting window on top.
   1038             if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
   1039                 // Base windows go behind everything else.
   1040                 WindowState lowestWindow = tokenWindowList.get(0);
   1041                 placeWindowBefore(lowestWindow, win);
   1042                 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows);
   1043             } else {
   1044                 AppWindowToken atoken = win.mAppToken;
   1045                 WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
   1046                 if (atoken != null && lastWindow == atoken.startingWindow) {
   1047                     placeWindowBefore(lastWindow, win);
   1048                     tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows);
   1049                 } else {
   1050                     int newIdx = findIdxBasedOnAppTokens(win);
   1051                     //there is a window above this one associated with the same
   1052                     //apptoken note that the window could be a floating window
   1053                     //that was created later or a window at the top of the list of
   1054                     //windows associated with this token.
   1055                     if (true || DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
   1056                             "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " +
   1057                             N);
   1058                     windows.add(newIdx + 1, win);
   1059                     if (newIdx < 0) {
   1060                         // No window from token found on win's display.
   1061                         tokenWindowsPos = 0;
   1062                     } else {
   1063                         tokenWindowsPos = indexOfWinInWindowList(
   1064                                 windows.get(newIdx), token.windows) + 1;
   1065                     }
   1066                     mWindowsChanged = true;
   1067                 }
   1068             }
   1069             return tokenWindowsPos;
   1070         }
   1071 
   1072         // No windows from this token on this display
   1073         if (localLOGV) Slog.v(TAG, "Figuring out where to add app window " + client.asBinder()
   1074                 + " (token=" + token + ")");
   1075         // Figure out where the window should go, based on the
   1076         // order of applications.
   1077         WindowState pos = null;
   1078 
   1079         final ArrayList<Task> tasks = displayContent.getTasks();
   1080         int taskNdx;
   1081         int tokenNdx = -1;
   1082         for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
   1083             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
   1084             for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
   1085                 final AppWindowToken t = tokens.get(tokenNdx);
   1086                 if (t == token) {
   1087                     --tokenNdx;
   1088                     if (tokenNdx < 0) {
   1089                         --taskNdx;
   1090                         if (taskNdx >= 0) {
   1091                             tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1;
   1092                         }
   1093                     }
   1094                     break;
   1095                 }
   1096 
   1097                 // We haven't reached the token yet; if this token
   1098                 // is not going to the bottom and has windows on this display, we can
   1099                 // use it as an anchor for when we do reach the token.
   1100                 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
   1101                 if (!t.sendingToBottom && tokenWindowList.size() > 0) {
   1102                     pos = tokenWindowList.get(0);
   1103                 }
   1104             }
   1105             if (tokenNdx >= 0) {
   1106                 // early exit
   1107                 break;
   1108             }
   1109         }
   1110 
   1111         // We now know the index into the apps.  If we found
   1112         // an app window above, that gives us the position; else
   1113         // we need to look some more.
   1114         if (pos != null) {
   1115             // Move behind any windows attached to this one.
   1116             WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
   1117             if (atoken != null) {
   1118                 tokenWindowList =
   1119                         getTokenWindowsOnDisplay(atoken, displayContent);
   1120                 final int NC = tokenWindowList.size();
   1121                 if (NC > 0) {
   1122                     WindowState bottom = tokenWindowList.get(0);
   1123                     if (bottom.mSubLayer < 0) {
   1124                         pos = bottom;
   1125                     }
   1126                 }
   1127             }
   1128             placeWindowBefore(pos, win);
   1129             return tokenWindowsPos;
   1130         }
   1131 
   1132         // Continue looking down until we find the first
   1133         // token that has windows on this display.
   1134         for ( ; taskNdx >= 0; --taskNdx) {
   1135             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
   1136             for ( ; tokenNdx >= 0; --tokenNdx) {
   1137                 final AppWindowToken t = tokens.get(tokenNdx);
   1138                 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
   1139                 final int NW = tokenWindowList.size();
   1140                 if (NW > 0) {
   1141                     pos = tokenWindowList.get(NW-1);
   1142                     break;
   1143                 }
   1144             }
   1145             if (tokenNdx >= 0) {
   1146                 // found
   1147                 break;
   1148             }
   1149         }
   1150 
   1151         if (pos != null) {
   1152             // Move in front of any windows attached to this
   1153             // one.
   1154             WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
   1155             if (atoken != null) {
   1156                 final int NC = atoken.windows.size();
   1157                 if (NC > 0) {
   1158                     WindowState top = atoken.windows.get(NC-1);
   1159                     if (top.mSubLayer >= 0) {
   1160                         pos = top;
   1161                     }
   1162                 }
   1163             }
   1164             placeWindowAfter(pos, win);
   1165             return tokenWindowsPos;
   1166         }
   1167 
   1168         // Just search for the start of this layer.
   1169         final int myLayer = win.mBaseLayer;
   1170         int i;
   1171         for (i = N - 1; i >= 0; --i) {
   1172             WindowState w = windows.get(i);
   1173             if (w.mBaseLayer <= myLayer) {
   1174                 break;
   1175             }
   1176         }
   1177         if (true || DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
   1178                 "Based on layer: Adding window " + win + " at " + (i + 1) + " of " + N);
   1179         windows.add(i + 1, win);
   1180         mWindowsChanged = true;
   1181         return tokenWindowsPos;
   1182     }
   1183 
   1184     private void addFreeWindowToListLocked(final WindowState win) {
   1185         final WindowList windows = win.getWindowList();
   1186 
   1187         // Figure out where window should go, based on layer.
   1188         final int myLayer = win.mBaseLayer;
   1189         int i;
   1190         for (i = windows.size() - 1; i >= 0; i--) {
   1191             if (windows.get(i).mBaseLayer <= myLayer) {
   1192                 break;
   1193             }
   1194         }
   1195         i++;
   1196         if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
   1197                 "Free window: Adding window " + win + " at " + i + " of " + windows.size());
   1198         windows.add(i, win);
   1199         mWindowsChanged = true;
   1200     }
   1201 
   1202     private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) {
   1203         final WindowToken token = win.mToken;
   1204         final DisplayContent displayContent = win.getDisplayContent();
   1205         if (displayContent == null) {
   1206             return;
   1207         }
   1208         final WindowState attached = win.mAttachedWindow;
   1209 
   1210         WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
   1211 
   1212         // Figure out this window's ordering relative to the window
   1213         // it is attached to.
   1214         final int NA = tokenWindowList.size();
   1215         final int sublayer = win.mSubLayer;
   1216         int largestSublayer = Integer.MIN_VALUE;
   1217         WindowState windowWithLargestSublayer = null;
   1218         int i;
   1219         for (i = 0; i < NA; i++) {
   1220             WindowState w = tokenWindowList.get(i);
   1221             final int wSublayer = w.mSubLayer;
   1222             if (wSublayer >= largestSublayer) {
   1223                 largestSublayer = wSublayer;
   1224                 windowWithLargestSublayer = w;
   1225             }
   1226             if (sublayer < 0) {
   1227                 // For negative sublayers, we go below all windows
   1228                 // in the same sublayer.
   1229                 if (wSublayer >= sublayer) {
   1230                     if (addToToken) {
   1231                         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
   1232                         token.windows.add(i, win);
   1233                     }
   1234                     placeWindowBefore(wSublayer >= 0 ? attached : w, win);
   1235                     break;
   1236                 }
   1237             } else {
   1238                 // For positive sublayers, we go above all windows
   1239                 // in the same sublayer.
   1240                 if (wSublayer > sublayer) {
   1241                     if (addToToken) {
   1242                         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
   1243                         token.windows.add(i, win);
   1244                     }
   1245                     placeWindowBefore(w, win);
   1246                     break;
   1247                 }
   1248             }
   1249         }
   1250         if (i >= NA) {
   1251             if (addToToken) {
   1252                 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
   1253                 token.windows.add(win);
   1254             }
   1255             if (sublayer < 0) {
   1256                 placeWindowBefore(attached, win);
   1257             } else {
   1258                 placeWindowAfter(largestSublayer >= 0
   1259                                  ? windowWithLargestSublayer
   1260                                  : attached,
   1261                                  win);
   1262             }
   1263         }
   1264     }
   1265 
   1266     private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) {
   1267         if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win +
   1268                 " Callers=" + Debug.getCallers(4));
   1269         if (win.mAttachedWindow == null) {
   1270             final WindowToken token = win.mToken;
   1271             int tokenWindowsPos = 0;
   1272             if (token.appWindowToken != null) {
   1273                 tokenWindowsPos = addAppWindowToListLocked(win);
   1274             } else {
   1275                 addFreeWindowToListLocked(win);
   1276             }
   1277             if (addToToken) {
   1278                 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
   1279                 token.windows.add(tokenWindowsPos, win);
   1280             }
   1281         } else {
   1282             addAttachedWindowToListLocked(win, addToToken);
   1283         }
   1284 
   1285         if (win.mAppToken != null && addToToken) {
   1286             win.mAppToken.allAppWindows.add(win);
   1287         }
   1288     }
   1289 
   1290     static boolean canBeImeTarget(WindowState w) {
   1291         final int fl = w.mAttrs.flags
   1292                 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
   1293         if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)
   1294                 || w.mAttrs.type == TYPE_APPLICATION_STARTING) {
   1295             if (DEBUG_INPUT_METHOD) {
   1296                 Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
   1297                 if (!w.isVisibleOrAdding()) {
   1298                     Slog.i(TAG, "  mSurface=" + w.mWinAnimator.mSurfaceControl
   1299                             + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility
   1300                             + " policyVis=" + w.mPolicyVisibility
   1301                             + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
   1302                             + " attachHid=" + w.mAttachedHidden
   1303                             + " exiting=" + w.mExiting + " destroying=" + w.mDestroying);
   1304                     if (w.mAppToken != null) {
   1305                         Slog.i(TAG, "  mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
   1306                     }
   1307                 }
   1308             }
   1309             return w.isVisibleOrAdding();
   1310         }
   1311         return false;
   1312     }
   1313 
   1314     /**
   1315      * Dig through the WindowStates and find the one that the Input Method will target.
   1316      * @param willMove
   1317      * @return The index+1 in mWindows of the discovered target.
   1318      */
   1319     int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
   1320         // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
   1321         // same display. Or even when the current IME/target are not on the same screen as the next
   1322         // IME/target. For now only look for input windows on the main screen.
   1323         WindowList windows = getDefaultWindowListLocked();
   1324         WindowState w = null;
   1325         int i;
   1326         for (i = windows.size() - 1; i >= 0; --i) {
   1327             WindowState win = windows.get(i);
   1328 
   1329             if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i
   1330                     + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
   1331             if (canBeImeTarget(win)) {
   1332                 w = win;
   1333                 //Slog.i(TAG, "Putting input method here!");
   1334 
   1335                 // Yet more tricksyness!  If this window is a "starting"
   1336                 // window, we do actually want to be on top of it, but
   1337                 // it is not -really- where input will go.  So if the caller
   1338                 // is not actually looking to move the IME, look down below
   1339                 // for a real window to target...
   1340                 if (!willMove
   1341                         && w.mAttrs.type == TYPE_APPLICATION_STARTING
   1342                         && i > 0) {
   1343                     WindowState wb = windows.get(i-1);
   1344                     if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
   1345                         i--;
   1346                         w = wb;
   1347                     }
   1348                 }
   1349                 break;
   1350             }
   1351         }
   1352 
   1353         // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
   1354 
   1355         if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w);
   1356 
   1357         // Now, a special case -- if the last target's window is in the
   1358         // process of exiting, and is above the new target, keep on the
   1359         // last target to avoid flicker.  Consider for example a Dialog with
   1360         // the IME shown: when the Dialog is dismissed, we want to keep
   1361         // the IME above it until it is completely gone so it doesn't drop
   1362         // behind the dialog or its full-screen scrim.
   1363         final WindowState curTarget = mInputMethodTarget;
   1364         if (curTarget != null
   1365                 && curTarget.isDisplayedLw()
   1366                 && curTarget.isClosing()
   1367                 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
   1368             if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing");
   1369             return windows.indexOf(curTarget) + 1;
   1370         }
   1371 
   1372         if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
   1373                 + w + " willMove=" + willMove);
   1374 
   1375         if (willMove && w != null) {
   1376             AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
   1377             if (token != null) {
   1378 
   1379                 // Now some fun for dealing with window animations that
   1380                 // modify the Z order.  We need to look at all windows below
   1381                 // the current target that are in this app, finding the highest
   1382                 // visible one in layering.
   1383                 WindowState highestTarget = null;
   1384                 int highestPos = 0;
   1385                 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
   1386                     WindowList curWindows = curTarget.getWindowList();
   1387                     int pos = curWindows.indexOf(curTarget);
   1388                     while (pos >= 0) {
   1389                         WindowState win = curWindows.get(pos);
   1390                         if (win.mAppToken != token) {
   1391                             break;
   1392                         }
   1393                         if (!win.mRemoved) {
   1394                             if (highestTarget == null || win.mWinAnimator.mAnimLayer >
   1395                                     highestTarget.mWinAnimator.mAnimLayer) {
   1396                                 highestTarget = win;
   1397                                 highestPos = pos;
   1398                             }
   1399                         }
   1400                         pos--;
   1401                     }
   1402                 }
   1403 
   1404                 if (highestTarget != null) {
   1405                     if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget
   1406                             + " animating=" + highestTarget.mWinAnimator.isAnimating()
   1407                             + " layer=" + highestTarget.mWinAnimator.mAnimLayer
   1408                             + " new layer=" + w.mWinAnimator.mAnimLayer);
   1409 
   1410                     if (mAppTransition.isTransitionSet()) {
   1411                         // If we are currently setting up for an animation,
   1412                         // hold everything until we can find out what will happen.
   1413                         mInputMethodTargetWaitingAnim = true;
   1414                         mInputMethodTarget = highestTarget;
   1415                         return highestPos + 1;
   1416                     } else if (highestTarget.mWinAnimator.isAnimating() &&
   1417                             highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
   1418                         // If the window we are currently targeting is involved
   1419                         // with an animation, and it is on top of the next target
   1420                         // we will be over, then hold off on moving until
   1421                         // that is done.
   1422                         mInputMethodTargetWaitingAnim = true;
   1423                         mInputMethodTarget = highestTarget;
   1424                         return highestPos + 1;
   1425                     }
   1426                 }
   1427             }
   1428         }
   1429 
   1430         //Slog.i(TAG, "Placing input method @" + (i+1));
   1431         if (w != null) {
   1432             if (willMove) {
   1433                 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to "
   1434                         + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
   1435                 mInputMethodTarget = w;
   1436                 mInputMethodTargetWaitingAnim = false;
   1437                 if (w.mAppToken != null) {
   1438                     setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment);
   1439                 } else {
   1440                     setInputMethodAnimLayerAdjustment(0);
   1441                 }
   1442             }
   1443             return i+1;
   1444         }
   1445         if (willMove) {
   1446             if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null."
   1447                     + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
   1448             mInputMethodTarget = null;
   1449             setInputMethodAnimLayerAdjustment(0);
   1450         }
   1451         return -1;
   1452     }
   1453 
   1454     void addInputMethodWindowToListLocked(WindowState win) {
   1455         int pos = findDesiredInputMethodWindowIndexLocked(true);
   1456         if (pos >= 0) {
   1457             win.mTargetAppToken = mInputMethodTarget.mAppToken;
   1458             if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
   1459                     TAG, "Adding input method window " + win + " at " + pos);
   1460             // TODO(multidisplay): IMEs are only supported on the default display.
   1461             getDefaultWindowListLocked().add(pos, win);
   1462             mWindowsChanged = true;
   1463             moveInputMethodDialogsLocked(pos+1);
   1464             return;
   1465         }
   1466         win.mTargetAppToken = null;
   1467         addWindowToListInOrderLocked(win, true);
   1468         moveInputMethodDialogsLocked(pos);
   1469     }
   1470 
   1471     void setInputMethodAnimLayerAdjustment(int adj) {
   1472         if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj);
   1473         mInputMethodAnimLayerAdjustment = adj;
   1474         WindowState imw = mInputMethodWindow;
   1475         if (imw != null) {
   1476             imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
   1477             if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
   1478                     + " anim layer: " + imw.mWinAnimator.mAnimLayer);
   1479             int wi = imw.mChildWindows.size();
   1480             while (wi > 0) {
   1481                 wi--;
   1482                 WindowState cw = imw.mChildWindows.get(wi);
   1483                 cw.mWinAnimator.mAnimLayer = cw.mLayer + adj;
   1484                 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw
   1485                         + " anim layer: " + cw.mWinAnimator.mAnimLayer);
   1486             }
   1487         }
   1488         int di = mInputMethodDialogs.size();
   1489         while (di > 0) {
   1490             di --;
   1491             imw = mInputMethodDialogs.get(di);
   1492             imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
   1493             if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
   1494                     + " anim layer: " + imw.mWinAnimator.mAnimLayer);
   1495         }
   1496     }
   1497 
   1498     private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
   1499         WindowList windows = win.getWindowList();
   1500         int wpos = windows.indexOf(win);
   1501         if (wpos >= 0) {
   1502             if (wpos < interestingPos) interestingPos--;
   1503             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
   1504             windows.remove(wpos);
   1505             mWindowsChanged = true;
   1506             int NC = win.mChildWindows.size();
   1507             while (NC > 0) {
   1508                 NC--;
   1509                 WindowState cw = win.mChildWindows.get(NC);
   1510                 int cpos = windows.indexOf(cw);
   1511                 if (cpos >= 0) {
   1512                     if (cpos < interestingPos) interestingPos--;
   1513                     if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
   1514                             + cpos + ": " + cw);
   1515                     windows.remove(cpos);
   1516                 }
   1517             }
   1518         }
   1519         return interestingPos;
   1520     }
   1521 
   1522     private void reAddWindowToListInOrderLocked(WindowState win) {
   1523         addWindowToListInOrderLocked(win, false);
   1524         // This is a hack to get all of the child windows added as well
   1525         // at the right position.  Child windows should be rare and
   1526         // this case should be rare, so it shouldn't be that big a deal.
   1527         WindowList windows = win.getWindowList();
   1528         int wpos = windows.indexOf(win);
   1529         if (wpos >= 0) {
   1530             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win);
   1531             windows.remove(wpos);
   1532             mWindowsChanged = true;
   1533             reAddWindowLocked(wpos, win);
   1534         }
   1535     }
   1536 
   1537     void logWindowList(final WindowList windows, String prefix) {
   1538         int N = windows.size();
   1539         while (N > 0) {
   1540             N--;
   1541             Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N));
   1542         }
   1543     }
   1544 
   1545     void moveInputMethodDialogsLocked(int pos) {
   1546         ArrayList<WindowState> dialogs = mInputMethodDialogs;
   1547 
   1548         // TODO(multidisplay): IMEs are only supported on the default display.
   1549         WindowList windows = getDefaultWindowListLocked();
   1550         final int N = dialogs.size();
   1551         if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
   1552         for (int i=0; i<N; i++) {
   1553             pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
   1554         }
   1555         if (DEBUG_INPUT_METHOD) {
   1556             Slog.v(TAG, "Window list w/pos=" + pos);
   1557             logWindowList(windows, "  ");
   1558         }
   1559 
   1560         if (pos >= 0) {
   1561             final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
   1562             // Skip windows owned by the input method.
   1563             if (mInputMethodWindow != null) {
   1564                 while (pos < windows.size()) {
   1565                     WindowState wp = windows.get(pos);
   1566                     if (wp == mInputMethodWindow || wp.mAttachedWindow == mInputMethodWindow) {
   1567                         pos++;
   1568                         continue;
   1569                     }
   1570                     break;
   1571                 }
   1572             }
   1573             if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
   1574             for (int i=0; i<N; i++) {
   1575                 WindowState win = dialogs.get(i);
   1576                 win.mTargetAppToken = targetAppToken;
   1577                 pos = reAddWindowLocked(pos, win);
   1578             }
   1579             if (DEBUG_INPUT_METHOD) {
   1580                 Slog.v(TAG, "Final window list:");
   1581                 logWindowList(windows, "  ");
   1582             }
   1583             return;
   1584         }
   1585         for (int i=0; i<N; i++) {
   1586             WindowState win = dialogs.get(i);
   1587             win.mTargetAppToken = null;
   1588             reAddWindowToListInOrderLocked(win);
   1589             if (DEBUG_INPUT_METHOD) {
   1590                 Slog.v(TAG, "No IM target, final list:");
   1591                 logWindowList(windows, "  ");
   1592             }
   1593         }
   1594     }
   1595 
   1596     boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
   1597         final WindowState imWin = mInputMethodWindow;
   1598         final int DN = mInputMethodDialogs.size();
   1599         if (imWin == null && DN == 0) {
   1600             return false;
   1601         }
   1602 
   1603         // TODO(multidisplay): IMEs are only supported on the default display.
   1604         WindowList windows = getDefaultWindowListLocked();
   1605 
   1606         int imPos = findDesiredInputMethodWindowIndexLocked(true);
   1607         if (imPos >= 0) {
   1608             // In this case, the input method windows are to be placed
   1609             // immediately above the window they are targeting.
   1610 
   1611             // First check to see if the input method windows are already
   1612             // located here, and contiguous.
   1613             final int N = windows.size();
   1614             WindowState firstImWin = imPos < N
   1615                     ? windows.get(imPos) : null;
   1616 
   1617             // Figure out the actual input method window that should be
   1618             // at the bottom of their stack.
   1619             WindowState baseImWin = imWin != null
   1620                     ? imWin : mInputMethodDialogs.get(0);
   1621             if (baseImWin.mChildWindows.size() > 0) {
   1622                 WindowState cw = baseImWin.mChildWindows.get(0);
   1623                 if (cw.mSubLayer < 0) baseImWin = cw;
   1624             }
   1625 
   1626             if (firstImWin == baseImWin) {
   1627                 // The windows haven't moved...  but are they still contiguous?
   1628                 // First find the top IM window.
   1629                 int pos = imPos+1;
   1630                 while (pos < N) {
   1631                     if (!(windows.get(pos)).mIsImWindow) {
   1632                         break;
   1633                     }
   1634                     pos++;
   1635                 }
   1636                 pos++;
   1637                 // Now there should be no more input method windows above.
   1638                 while (pos < N) {
   1639                     if ((windows.get(pos)).mIsImWindow) {
   1640                         break;
   1641                     }
   1642                     pos++;
   1643                 }
   1644                 if (pos >= N) {
   1645                     // Z order is good.
   1646                     // The IM target window may be changed, so update the mTargetAppToken.
   1647                     if (imWin != null) {
   1648                         imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
   1649                     }
   1650                     return false;
   1651                 }
   1652             }
   1653 
   1654             if (imWin != null) {
   1655                 if (DEBUG_INPUT_METHOD) {
   1656                     Slog.v(TAG, "Moving IM from " + imPos);
   1657                     logWindowList(windows, "  ");
   1658                 }
   1659                 imPos = tmpRemoveWindowLocked(imPos, imWin);
   1660                 if (DEBUG_INPUT_METHOD) {
   1661                     Slog.v(TAG, "List after removing with new pos " + imPos + ":");
   1662                     logWindowList(windows, "  ");
   1663                 }
   1664                 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
   1665                 reAddWindowLocked(imPos, imWin);
   1666                 if (DEBUG_INPUT_METHOD) {
   1667                     Slog.v(TAG, "List after moving IM to " + imPos + ":");
   1668                     logWindowList(windows, "  ");
   1669                 }
   1670                 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
   1671             } else {
   1672                 moveInputMethodDialogsLocked(imPos);
   1673             }
   1674 
   1675         } else {
   1676             // In this case, the input method windows go in a fixed layer,
   1677             // because they aren't currently associated with a focus window.
   1678 
   1679             if (imWin != null) {
   1680                 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos);
   1681                 tmpRemoveWindowLocked(0, imWin);
   1682                 imWin.mTargetAppToken = null;
   1683                 reAddWindowToListInOrderLocked(imWin);
   1684                 if (DEBUG_INPUT_METHOD) {
   1685                     Slog.v(TAG, "List with no IM target:");
   1686                     logWindowList(windows, "  ");
   1687                 }
   1688                 if (DN > 0) moveInputMethodDialogsLocked(-1);
   1689             } else {
   1690                 moveInputMethodDialogsLocked(-1);
   1691             }
   1692 
   1693         }
   1694 
   1695         if (needAssignLayers) {
   1696             assignLayersLocked(windows);
   1697         }
   1698 
   1699         return true;
   1700     }
   1701 
   1702     final boolean isWallpaperVisible(WindowState wallpaperTarget) {
   1703         if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
   1704                 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
   1705                 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
   1706                         ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
   1707                 + " upper=" + mUpperWallpaperTarget
   1708                 + " lower=" + mLowerWallpaperTarget);
   1709         return (wallpaperTarget != null
   1710                         && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
   1711                                 && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
   1712                 || mUpperWallpaperTarget != null
   1713                 || mLowerWallpaperTarget != null;
   1714     }
   1715 
   1716     static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
   1717     static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
   1718 
   1719     int adjustWallpaperWindowsLocked() {
   1720         mInnerFields.mWallpaperMayChange = false;
   1721         boolean targetChanged = false;
   1722 
   1723         // TODO(multidisplay): Wallpapers on main screen only.
   1724         final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo();
   1725         final int dw = displayInfo.logicalWidth;
   1726         final int dh = displayInfo.logicalHeight;
   1727 
   1728         // First find top-most window that has asked to be on top of the
   1729         // wallpaper; all wallpapers go behind it.
   1730         final WindowList windows = getDefaultWindowListLocked();
   1731         int N = windows.size();
   1732         WindowState w = null;
   1733         WindowState foundW = null;
   1734         int foundI = 0;
   1735         WindowState topCurW = null;
   1736         int topCurI = 0;
   1737         int windowDetachedI = -1;
   1738         int i = N;
   1739         while (i > 0) {
   1740             i--;
   1741             w = windows.get(i);
   1742             if ((w.mAttrs.type == TYPE_WALLPAPER)) {
   1743                 if (topCurW == null) {
   1744                     topCurW = w;
   1745                     topCurI = i;
   1746                 }
   1747                 continue;
   1748             }
   1749             topCurW = null;
   1750             if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
   1751                 // If this window's app token is hidden and not animating,
   1752                 // it is of no interest to us.
   1753                 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
   1754                     if (DEBUG_WALLPAPER) Slog.v(TAG,
   1755                             "Skipping hidden and not animating token: " + w);
   1756                     continue;
   1757                 }
   1758             }
   1759             if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
   1760                     + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
   1761 
   1762             // If the app is executing an animation because the keyguard is going away, keep the
   1763             // wallpaper during the animation so it doesn't flicker out.
   1764             final boolean hasWallpaper = (w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
   1765                     || (w.mAppToken != null
   1766                             && w.mWinAnimator.mKeyguardGoingAwayAnimation);
   1767             if (hasWallpaper && w.isOnScreen()
   1768                     && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
   1769                 if (DEBUG_WALLPAPER) Slog.v(TAG,
   1770                         "Found wallpaper target: #" + i + "=" + w);
   1771                 foundW = w;
   1772                 foundI = i;
   1773                 if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) {
   1774                     // The current wallpaper target is animating, so we'll
   1775                     // look behind it for another possible target and figure
   1776                     // out what is going on below.
   1777                     if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
   1778                             + ": token animating, looking behind.");
   1779                     continue;
   1780                 }
   1781                 break;
   1782             } else if (w == mAnimator.mWindowDetachedWallpaper) {
   1783                 windowDetachedI = i;
   1784             }
   1785         }
   1786 
   1787         if (foundW == null && windowDetachedI >= 0) {
   1788             if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
   1789                     "Found animating detached wallpaper activity: #" + i + "=" + w);
   1790             foundW = w;
   1791             foundI = windowDetachedI;
   1792         }
   1793 
   1794         if (mWallpaperTarget != foundW
   1795                 && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) {
   1796             if (DEBUG_WALLPAPER_LIGHT) {
   1797                 Slog.v(TAG, "New wallpaper target: " + foundW
   1798                         + " oldTarget: " + mWallpaperTarget);
   1799             }
   1800 
   1801             mLowerWallpaperTarget = null;
   1802             mUpperWallpaperTarget = null;
   1803 
   1804             WindowState oldW = mWallpaperTarget;
   1805             mWallpaperTarget = foundW;
   1806             targetChanged = true;
   1807 
   1808             // Now what is happening...  if the current and new targets are
   1809             // animating, then we are in our super special mode!
   1810             if (foundW != null && oldW != null) {
   1811                 boolean oldAnim = oldW.isAnimatingLw();
   1812                 boolean foundAnim = foundW.isAnimatingLw();
   1813                 if (DEBUG_WALLPAPER_LIGHT) {
   1814                     Slog.v(TAG, "New animation: " + foundAnim
   1815                             + " old animation: " + oldAnim);
   1816                 }
   1817                 if (foundAnim && oldAnim) {
   1818                     int oldI = windows.indexOf(oldW);
   1819                     if (DEBUG_WALLPAPER_LIGHT) {
   1820                         Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
   1821                     }
   1822                     if (oldI >= 0) {
   1823                         if (DEBUG_WALLPAPER_LIGHT) {
   1824                             Slog.v(TAG, "Animating wallpapers: old#" + oldI
   1825                                     + "=" + oldW + "; new#" + foundI
   1826                                     + "=" + foundW);
   1827                         }
   1828 
   1829                         // Set the new target correctly.
   1830                         if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
   1831                             if (DEBUG_WALLPAPER_LIGHT) {
   1832                                 Slog.v(TAG, "Old wallpaper still the target.");
   1833                             }
   1834                             mWallpaperTarget = oldW;
   1835                             foundW = oldW;
   1836                             foundI = oldI;
   1837                         }
   1838                         // Now set the upper and lower wallpaper targets
   1839                         // correctly, and make sure that we are positioning
   1840                         // the wallpaper below the lower.
   1841                         else if (foundI > oldI) {
   1842                             // The new target is on top of the old one.
   1843                             if (DEBUG_WALLPAPER_LIGHT) {
   1844                                 Slog.v(TAG, "Found target above old target.");
   1845                             }
   1846                             mUpperWallpaperTarget = foundW;
   1847                             mLowerWallpaperTarget = oldW;
   1848                             foundW = oldW;
   1849                             foundI = oldI;
   1850                         } else {
   1851                             // The new target is below the old one.
   1852                             if (DEBUG_WALLPAPER_LIGHT) {
   1853                                 Slog.v(TAG, "Found target below old target.");
   1854                             }
   1855                             mUpperWallpaperTarget = oldW;
   1856                             mLowerWallpaperTarget = foundW;
   1857                         }
   1858                     }
   1859                 }
   1860             }
   1861 
   1862         } else if (mLowerWallpaperTarget != null) {
   1863             // Is it time to stop animating?
   1864             if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
   1865                 if (DEBUG_WALLPAPER_LIGHT) {
   1866                     Slog.v(TAG, "No longer animating wallpaper targets!");
   1867                 }
   1868                 mLowerWallpaperTarget = null;
   1869                 mUpperWallpaperTarget = null;
   1870                 mWallpaperTarget = foundW;
   1871                 targetChanged = true;
   1872             }
   1873         }
   1874 
   1875         boolean visible = foundW != null;
   1876         if (visible) {
   1877             // The window is visible to the compositor...  but is it visible
   1878             // to the user?  That is what the wallpaper cares about.
   1879             visible = isWallpaperVisible(foundW);
   1880             if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
   1881 
   1882             // If the wallpaper target is animating, we may need to copy
   1883             // its layer adjustment.  Only do this if we are not transfering
   1884             // between two wallpaper targets.
   1885             mWallpaperAnimLayerAdjustment =
   1886                     (mLowerWallpaperTarget == null && foundW.mAppToken != null)
   1887                     ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0;
   1888 
   1889             final int maxLayer = mPolicy.getMaxWallpaperLayer()
   1890                     * TYPE_LAYER_MULTIPLIER
   1891                     + TYPE_LAYER_OFFSET;
   1892 
   1893             // Now w is the window we are supposed to be behind...  but we
   1894             // need to be sure to also be behind any of its attached windows,
   1895             // AND any starting window associated with it, AND below the
   1896             // maximum layer the policy allows for wallpapers.
   1897             while (foundI > 0) {
   1898                 WindowState wb = windows.get(foundI-1);
   1899                 if (wb.mBaseLayer < maxLayer &&
   1900                         wb.mAttachedWindow != foundW &&
   1901                         (foundW.mAttachedWindow == null ||
   1902                                 wb.mAttachedWindow != foundW.mAttachedWindow) &&
   1903                         (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
   1904                                 foundW.mToken == null || wb.mToken != foundW.mToken)) {
   1905                     // This window is not related to the previous one in any
   1906                     // interesting way, so stop here.
   1907                     break;
   1908                 }
   1909                 foundW = wb;
   1910                 foundI--;
   1911             }
   1912         } else {
   1913             if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
   1914         }
   1915 
   1916         if (foundW == null && topCurW != null) {
   1917             // There is no wallpaper target, so it goes at the bottom.
   1918             // We will assume it is the same place as last time, if known.
   1919             foundW = topCurW;
   1920             foundI = topCurI+1;
   1921         } else {
   1922             // Okay i is the position immediately above the wallpaper.  Look at
   1923             // what is below it for later.
   1924             foundW = foundI > 0 ? windows.get(foundI-1) : null;
   1925         }
   1926 
   1927         if (visible) {
   1928             if (mWallpaperTarget.mWallpaperX >= 0) {
   1929                 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
   1930                 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
   1931             }
   1932             if (mWallpaperTarget.mWallpaperY >= 0) {
   1933                 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
   1934                 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
   1935             }
   1936             if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
   1937                 mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX;
   1938             }
   1939             if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
   1940                 mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY;
   1941             }
   1942         }
   1943 
   1944         // Start stepping backwards from here, ensuring that our wallpaper windows
   1945         // are correctly placed.
   1946         int changed = 0;
   1947         int curTokenIndex = mWallpaperTokens.size();
   1948         while (curTokenIndex > 0) {
   1949             curTokenIndex--;
   1950             WindowToken token = mWallpaperTokens.get(curTokenIndex);
   1951             if (token.hidden == visible) {
   1952                 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
   1953                         "Wallpaper token " + token + " hidden=" + !visible);
   1954                 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
   1955                 token.hidden = !visible;
   1956                 // Need to do a layout to ensure the wallpaper now has the
   1957                 // correct size.
   1958                 getDefaultDisplayContentLocked().layoutNeeded = true;
   1959             }
   1960 
   1961             int curWallpaperIndex = token.windows.size();
   1962             while (curWallpaperIndex > 0) {
   1963                 curWallpaperIndex--;
   1964                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
   1965 
   1966                 if (visible) {
   1967                     updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
   1968                 }
   1969 
   1970                 // First, make sure the client has the current visibility
   1971                 // state.
   1972                 dispatchWallpaperVisibility(wallpaper, visible);
   1973 
   1974                 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
   1975                 if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
   1976                         + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
   1977 
   1978                 // First, if this window is at the current index, then all
   1979                 // is well.
   1980                 if (wallpaper == foundW) {
   1981                     foundI--;
   1982                     foundW = foundI > 0
   1983                             ? windows.get(foundI-1) : null;
   1984                     continue;
   1985                 }
   1986 
   1987                 // The window didn't match...  the current wallpaper window,
   1988                 // wherever it is, is in the wrong place, so make sure it is
   1989                 // not in the list.
   1990                 int oldIndex = windows.indexOf(wallpaper);
   1991                 if (oldIndex >= 0) {
   1992                     if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
   1993                             + oldIndex + ": " + wallpaper);
   1994                     windows.remove(oldIndex);
   1995                     mWindowsChanged = true;
   1996                     if (oldIndex < foundI) {
   1997                         foundI--;
   1998                     }
   1999                 }
   2000 
   2001                 // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
   2002                 // layer. For keyguard over wallpaper put the wallpaper under the keyguard.
   2003                 int insertionIndex = 0;
   2004                 if (visible && foundW != null) {
   2005                     final int type = foundW.mAttrs.type;
   2006                     final int privateFlags = foundW.mAttrs.privateFlags;
   2007                     if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0
   2008                             || type == TYPE_KEYGUARD_SCRIM) {
   2009                         insertionIndex = windows.indexOf(foundW);
   2010                     }
   2011                 }
   2012                 if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
   2013                     Slog.v(TAG, "Moving wallpaper " + wallpaper
   2014                             + " from " + oldIndex + " to " + insertionIndex);
   2015                 }
   2016 
   2017                 windows.add(insertionIndex, wallpaper);
   2018                 mWindowsChanged = true;
   2019                 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
   2020             }
   2021         }
   2022 
   2023         /*
   2024         final TaskStack targetStack =
   2025                 mWallpaperTarget == null ? null : mWallpaperTarget.getStack();
   2026         if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 &&
   2027                 targetStack != null && !targetStack.isHomeStack()) {
   2028             // If the wallpaper target is not on the home stack then make sure that all windows
   2029             // from other non-home stacks are above the wallpaper.
   2030             for (i = foundI - 1; i >= 0; --i) {
   2031                 WindowState win = windows.get(i);
   2032                 if (!win.isVisibleLw()) {
   2033                     continue;
   2034                 }
   2035                 final TaskStack winStack = win.getStack();
   2036                 if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) {
   2037                     windows.remove(i);
   2038                     windows.add(foundI + 1, win);
   2039                 }
   2040             }
   2041         }
   2042         */
   2043 
   2044         if (targetChanged && DEBUG_WALLPAPER_LIGHT) {
   2045             Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget
   2046                     + " lower=" + mLowerWallpaperTarget + " upper="
   2047                     + mUpperWallpaperTarget);
   2048         }
   2049 
   2050         return changed;
   2051     }
   2052 
   2053     void setWallpaperAnimLayerAdjustmentLocked(int adj) {
   2054         if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
   2055                 "Setting wallpaper layer adj to " + adj);
   2056         mWallpaperAnimLayerAdjustment = adj;
   2057         int curTokenIndex = mWallpaperTokens.size();
   2058         while (curTokenIndex > 0) {
   2059             curTokenIndex--;
   2060             WindowToken token = mWallpaperTokens.get(curTokenIndex);
   2061             int curWallpaperIndex = token.windows.size();
   2062             while (curWallpaperIndex > 0) {
   2063                 curWallpaperIndex--;
   2064                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
   2065                 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj;
   2066                 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win "
   2067                         + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
   2068             }
   2069         }
   2070     }
   2071 
   2072     boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
   2073             boolean sync) {
   2074         boolean changed = false;
   2075         boolean rawChanged = false;
   2076         float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
   2077         float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
   2078         int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
   2079         int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
   2080         if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
   2081             offset += mLastWallpaperDisplayOffsetX;
   2082         }
   2083         changed = wallpaperWin.mXOffset != offset;
   2084         if (changed) {
   2085             if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
   2086                     + wallpaperWin + " x: " + offset);
   2087             wallpaperWin.mXOffset = offset;
   2088         }
   2089         if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
   2090             wallpaperWin.mWallpaperX = wpx;
   2091             wallpaperWin.mWallpaperXStep = wpxs;
   2092             rawChanged = true;
   2093         }
   2094 
   2095         float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
   2096         float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
   2097         int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
   2098         offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
   2099         if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
   2100             offset += mLastWallpaperDisplayOffsetY;
   2101         }
   2102         if (wallpaperWin.mYOffset != offset) {
   2103             if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
   2104                     + wallpaperWin + " y: " + offset);
   2105             changed = true;
   2106             wallpaperWin.mYOffset = offset;
   2107         }
   2108         if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
   2109             wallpaperWin.mWallpaperY = wpy;
   2110             wallpaperWin.mWallpaperYStep = wpys;
   2111             rawChanged = true;
   2112         }
   2113 
   2114         if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
   2115                     WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
   2116             try {
   2117                 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
   2118                         + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
   2119                         + " y=" + wallpaperWin.mWallpaperY);
   2120                 if (sync) {
   2121                     mWaitingOnWallpaper = wallpaperWin;
   2122                 }
   2123                 wallpaperWin.mClient.dispatchWallpaperOffsets(
   2124                         wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
   2125                         wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
   2126                 if (sync) {
   2127                     if (mWaitingOnWallpaper != null) {
   2128                         long start = SystemClock.uptimeMillis();
   2129                         if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
   2130                                 < start) {
   2131                             try {
   2132                                 if (DEBUG_WALLPAPER) Slog.v(TAG,
   2133                                         "Waiting for offset complete...");
   2134                                 mWindowMap.wait(WALLPAPER_TIMEOUT);
   2135                             } catch (InterruptedException e) {
   2136                             }
   2137                             if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
   2138                             if ((start+WALLPAPER_TIMEOUT)
   2139                                     < SystemClock.uptimeMillis()) {
   2140                                 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
   2141                                         + wallpaperWin);
   2142                                 mLastWallpaperTimeoutTime = start;
   2143                             }
   2144                         }
   2145                         mWaitingOnWallpaper = null;
   2146                     }
   2147                 }
   2148             } catch (RemoteException e) {
   2149             }
   2150         }
   2151 
   2152         return changed;
   2153     }
   2154 
   2155     void wallpaperOffsetsComplete(IBinder window) {
   2156         synchronized (mWindowMap) {
   2157             if (mWaitingOnWallpaper != null &&
   2158                     mWaitingOnWallpaper.mClient.asBinder() == window) {
   2159                 mWaitingOnWallpaper = null;
   2160                 mWindowMap.notifyAll();
   2161             }
   2162         }
   2163     }
   2164 
   2165     void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
   2166         final DisplayContent displayContent = changingTarget.getDisplayContent();
   2167         if (displayContent == null) {
   2168             return;
   2169         }
   2170         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
   2171         final int dw = displayInfo.logicalWidth;
   2172         final int dh = displayInfo.logicalHeight;
   2173 
   2174         WindowState target = mWallpaperTarget;
   2175         if (target != null) {
   2176             if (target.mWallpaperX >= 0) {
   2177                 mLastWallpaperX = target.mWallpaperX;
   2178             } else if (changingTarget.mWallpaperX >= 0) {
   2179                 mLastWallpaperX = changingTarget.mWallpaperX;
   2180             }
   2181             if (target.mWallpaperY >= 0) {
   2182                 mLastWallpaperY = target.mWallpaperY;
   2183             } else if (changingTarget.mWallpaperY >= 0) {
   2184                 mLastWallpaperY = changingTarget.mWallpaperY;
   2185             }
   2186             if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
   2187                 mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX;
   2188             } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
   2189                 mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX;
   2190             }
   2191             if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
   2192                 mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY;
   2193             } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
   2194                 mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
   2195             }
   2196         }
   2197 
   2198         int curTokenIndex = mWallpaperTokens.size();
   2199         while (curTokenIndex > 0) {
   2200             curTokenIndex--;
   2201             WindowToken token = mWallpaperTokens.get(curTokenIndex);
   2202             int curWallpaperIndex = token.windows.size();
   2203             while (curWallpaperIndex > 0) {
   2204                 curWallpaperIndex--;
   2205                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
   2206                 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
   2207                     WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
   2208                     winAnimator.computeShownFrameLocked();
   2209                     // No need to lay out the windows - we can just set the wallpaper position
   2210                     // directly.
   2211                     winAnimator.setWallpaperOffset(wallpaper.mShownFrame);
   2212                     // We only want to be synchronous with one wallpaper.
   2213                     sync = false;
   2214                 }
   2215             }
   2216         }
   2217     }
   2218 
   2219     /**
   2220      * Check wallpaper for visiblity change and notify window if so.
   2221      * @param wallpaper The wallpaper to test and notify.
   2222      * @param visible Current visibility.
   2223      */
   2224     void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) {
   2225         if (wallpaper.mWallpaperVisible != visible) {
   2226             wallpaper.mWallpaperVisible = visible;
   2227             try {
   2228                 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
   2229                         "Updating vis of wallpaper " + wallpaper
   2230                         + ": " + visible + " from:\n" + Debug.getCallers(4, "  "));
   2231                 wallpaper.mClient.dispatchAppVisibility(visible);
   2232             } catch (RemoteException e) {
   2233             }
   2234         }
   2235     }
   2236 
   2237     void updateWallpaperVisibilityLocked() {
   2238         final boolean visible = isWallpaperVisible(mWallpaperTarget);
   2239         final DisplayContent displayContent = mWallpaperTarget.getDisplayContent();
   2240         if (displayContent == null) {
   2241             return;
   2242         }
   2243         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
   2244         final int dw = displayInfo.logicalWidth;
   2245         final int dh = displayInfo.logicalHeight;
   2246 
   2247         int curTokenIndex = mWallpaperTokens.size();
   2248         while (curTokenIndex > 0) {
   2249             curTokenIndex--;
   2250             WindowToken token = mWallpaperTokens.get(curTokenIndex);
   2251             if (token.hidden == visible) {
   2252                 token.hidden = !visible;
   2253                 // Need to do a layout to ensure the wallpaper now has the
   2254                 // correct size.
   2255                 getDefaultDisplayContentLocked().layoutNeeded = true;
   2256             }
   2257 
   2258             int curWallpaperIndex = token.windows.size();
   2259             while (curWallpaperIndex > 0) {
   2260                 curWallpaperIndex--;
   2261                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
   2262                 if (visible) {
   2263                     updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
   2264                 }
   2265 
   2266                 dispatchWallpaperVisibility(wallpaper, visible);
   2267             }
   2268         }
   2269     }
   2270 
   2271     public int addWindow(Session session, IWindow client, int seq,
   2272             WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
   2273             Rect outContentInsets, Rect outStableInsets, InputChannel outInputChannel) {
   2274         int[] appOp = new int[1];
   2275         int res = mPolicy.checkAddPermission(attrs, appOp);
   2276         if (res != WindowManagerGlobal.ADD_OKAY) {
   2277             return res;
   2278         }
   2279 
   2280         boolean reportNewConfig = false;
   2281         WindowState attachedWindow = null;
   2282         WindowState win = null;
   2283         long origId;
   2284         final int type = attrs.type;
   2285 
   2286         synchronized(mWindowMap) {
   2287             if (!mDisplayReady) {
   2288                 throw new IllegalStateException("Display has not been initialialized");
   2289             }
   2290 
   2291             final DisplayContent displayContent = getDisplayContentLocked(displayId);
   2292             if (displayContent == null) {
   2293                 Slog.w(TAG, "Attempted to add window to a display that does not exist: "
   2294                         + displayId + ".  Aborting.");
   2295                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
   2296             }
   2297             if (!displayContent.hasAccess(session.mUid)) {
   2298                 Slog.w(TAG, "Attempted to add window to a display for which the application "
   2299                         + "does not have access: " + displayId + ".  Aborting.");
   2300                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
   2301             }
   2302 
   2303             if (mWindowMap.containsKey(client.asBinder())) {
   2304                 Slog.w(TAG, "Window " + client + " is already added");
   2305                 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
   2306             }
   2307 
   2308             if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
   2309                 attachedWindow = windowForClientLocked(null, attrs.token, false);
   2310                 if (attachedWindow == null) {
   2311                     Slog.w(TAG, "Attempted to add window with token that is not a window: "
   2312                           + attrs.token + ".  Aborting.");
   2313                     return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
   2314                 }
   2315                 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
   2316                         && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
   2317                     Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
   2318                             + attrs.token + ".  Aborting.");
   2319                     return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
   2320                 }
   2321             }
   2322 
   2323             if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
   2324                 Slog.w(TAG, "Attempted to add private presentation window to a non-private display.  Aborting.");
   2325                 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
   2326             }
   2327 
   2328             boolean addToken = false;
   2329             WindowToken token = mTokenMap.get(attrs.token);
   2330             if (token == null) {
   2331                 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
   2332                     Slog.w(TAG, "Attempted to add application window with unknown token "
   2333                           + attrs.token + ".  Aborting.");
   2334                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2335                 }
   2336                 if (type == TYPE_INPUT_METHOD) {
   2337                     Slog.w(TAG, "Attempted to add input method window with unknown token "
   2338                           + attrs.token + ".  Aborting.");
   2339                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2340                 }
   2341                 if (type == TYPE_VOICE_INTERACTION) {
   2342                     Slog.w(TAG, "Attempted to add voice interaction window with unknown token "
   2343                           + attrs.token + ".  Aborting.");
   2344                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2345                 }
   2346                 if (type == TYPE_WALLPAPER) {
   2347                     Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
   2348                           + attrs.token + ".  Aborting.");
   2349                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2350                 }
   2351                 if (type == TYPE_DREAM) {
   2352                     Slog.w(TAG, "Attempted to add Dream window with unknown token "
   2353                           + attrs.token + ".  Aborting.");
   2354                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2355                 }
   2356                 if (type == TYPE_ACCESSIBILITY_OVERLAY) {
   2357                     Slog.w(TAG, "Attempted to add Accessibility overlay window with unknown token "
   2358                             + attrs.token + ".  Aborting.");
   2359                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2360                 }
   2361                 token = new WindowToken(this, attrs.token, -1, false);
   2362                 addToken = true;
   2363             } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
   2364                 AppWindowToken atoken = token.appWindowToken;
   2365                 if (atoken == null) {
   2366                     Slog.w(TAG, "Attempted to add window with non-application token "
   2367                           + token + ".  Aborting.");
   2368                     return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
   2369                 } else if (atoken.removed) {
   2370                     Slog.w(TAG, "Attempted to add window with exiting application token "
   2371                           + token + ".  Aborting.");
   2372                     return WindowManagerGlobal.ADD_APP_EXITING;
   2373                 }
   2374                 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
   2375                     // No need for this guy!
   2376                     if (localLOGV) Slog.v(
   2377                             TAG, "**** NO NEED TO START: " + attrs.getTitle());
   2378                     return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
   2379                 }
   2380             } else if (type == TYPE_INPUT_METHOD) {
   2381                 if (token.windowType != TYPE_INPUT_METHOD) {
   2382                     Slog.w(TAG, "Attempted to add input method window with bad token "
   2383                             + attrs.token + ".  Aborting.");
   2384                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2385                 }
   2386             } else if (type == TYPE_VOICE_INTERACTION) {
   2387                 if (token.windowType != TYPE_VOICE_INTERACTION) {
   2388                     Slog.w(TAG, "Attempted to add voice interaction window with bad token "
   2389                             + attrs.token + ".  Aborting.");
   2390                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2391                 }
   2392             } else if (type == TYPE_WALLPAPER) {
   2393                 if (token.windowType != TYPE_WALLPAPER) {
   2394                     Slog.w(TAG, "Attempted to add wallpaper window with bad token "
   2395                             + attrs.token + ".  Aborting.");
   2396                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2397                 }
   2398             } else if (type == TYPE_DREAM) {
   2399                 if (token.windowType != TYPE_DREAM) {
   2400                     Slog.w(TAG, "Attempted to add Dream window with bad token "
   2401                             + attrs.token + ".  Aborting.");
   2402                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2403                 }
   2404             } else if (type == TYPE_ACCESSIBILITY_OVERLAY) {
   2405                 if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
   2406                     Slog.w(TAG, "Attempted to add Accessibility overlay window with bad token "
   2407                             + attrs.token + ".  Aborting.");
   2408                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   2409                 }
   2410             } else if (token.appWindowToken != null) {
   2411                 Slog.w(TAG, "Non-null appWindowToken for system window of type=" + type);
   2412                 // It is not valid to use an app token with other system types; we will
   2413                 // instead make a new token for it (as if null had been passed in for the token).
   2414                 attrs.token = null;
   2415                 token = new WindowToken(this, null, -1, false);
   2416                 addToken = true;
   2417             }
   2418 
   2419             win = new WindowState(this, session, client, token,
   2420                     attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
   2421             if (win.mDeathRecipient == null) {
   2422                 // Client has apparently died, so there is no reason to
   2423                 // continue.
   2424                 Slog.w(TAG, "Adding window client " + client.asBinder()
   2425                         + " that is dead, aborting.");
   2426                 return WindowManagerGlobal.ADD_APP_EXITING;
   2427             }
   2428 
   2429             if (win.getDisplayContent() == null) {
   2430                 Slog.w(TAG, "Adding window to Display that has been removed.");
   2431                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
   2432             }
   2433 
   2434             mPolicy.adjustWindowParamsLw(win.mAttrs);
   2435             win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
   2436 
   2437             res = mPolicy.prepareAddWindowLw(win, attrs);
   2438             if (res != WindowManagerGlobal.ADD_OKAY) {
   2439                 return res;
   2440             }
   2441 
   2442             if (outInputChannel != null && (attrs.inputFeatures
   2443                     & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
   2444                 String name = win.makeInputChannelName();
   2445                 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
   2446                 win.setInputChannel(inputChannels[0]);
   2447                 inputChannels[1].transferTo(outInputChannel);
   2448 
   2449                 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
   2450             }
   2451 
   2452             // From now on, no exceptions or errors allowed!
   2453 
   2454             res = WindowManagerGlobal.ADD_OKAY;
   2455 
   2456             origId = Binder.clearCallingIdentity();
   2457 
   2458             if (addToken) {
   2459                 mTokenMap.put(attrs.token, token);
   2460             }
   2461             win.attach();
   2462             mWindowMap.put(client.asBinder(), win);
   2463             if (win.mAppOp != AppOpsManager.OP_NONE) {
   2464                 if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage())
   2465                         != AppOpsManager.MODE_ALLOWED) {
   2466                     win.setAppOpVisibilityLw(false);
   2467                 }
   2468             }
   2469 
   2470             if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
   2471                 token.appWindowToken.startingWindow = win;
   2472                 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken
   2473                         + " startingWindow=" + win);
   2474             }
   2475 
   2476             boolean imMayMove = true;
   2477 
   2478             if (type == TYPE_INPUT_METHOD) {
   2479                 win.mGivenInsetsPending = true;
   2480                 mInputMethodWindow = win;
   2481                 addInputMethodWindowToListLocked(win);
   2482                 imMayMove = false;
   2483             } else if (type == TYPE_INPUT_METHOD_DIALOG) {
   2484                 mInputMethodDialogs.add(win);
   2485                 addWindowToListInOrderLocked(win, true);
   2486                 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
   2487                 imMayMove = false;
   2488             } else {
   2489                 addWindowToListInOrderLocked(win, true);
   2490                 if (type == TYPE_WALLPAPER) {
   2491                     mLastWallpaperTimeoutTime = 0;
   2492                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
   2493                 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
   2494                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
   2495                 } else if (mWallpaperTarget != null
   2496                         && mWallpaperTarget.mLayer >= win.mBaseLayer) {
   2497                     // If there is currently a wallpaper being shown, and
   2498                     // the base layer of the new window is below the current
   2499                     // layer of the target window, then adjust the wallpaper.
   2500                     // This is to avoid a new window being placed between the
   2501                     // wallpaper and its target.
   2502                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
   2503                 }
   2504             }
   2505 
   2506             final WindowStateAnimator winAnimator = win.mWinAnimator;
   2507             winAnimator.mEnterAnimationPending = true;
   2508             winAnimator.mEnteringAnimation = true;
   2509 
   2510             if (displayContent.isDefaultDisplay) {
   2511                 mPolicy.getInsetHintLw(win.mAttrs, outContentInsets, outStableInsets);
   2512             } else {
   2513                 outContentInsets.setEmpty();
   2514                 outStableInsets.setEmpty();
   2515             }
   2516 
   2517             if (mInTouchMode) {
   2518                 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
   2519             }
   2520             if (win.mAppToken == null || !win.mAppToken.clientHidden) {
   2521                 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
   2522             }
   2523 
   2524             mInputMonitor.setUpdateInputWindowsNeededLw();
   2525 
   2526             boolean focusChanged = false;
   2527             if (win.canReceiveKeys()) {
   2528                 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
   2529                         false /*updateInputWindows*/);
   2530                 if (focusChanged) {
   2531                     imMayMove = false;
   2532                 }
   2533             }
   2534 
   2535             if (imMayMove) {
   2536                 moveInputMethodWindowsIfNeededLocked(false);
   2537             }
   2538 
   2539             assignLayersLocked(displayContent.getWindowList());
   2540             // Don't do layout here, the window must call
   2541             // relayout to be displayed, so we'll do it there.
   2542 
   2543             if (focusChanged) {
   2544                 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
   2545             }
   2546             mInputMonitor.updateInputWindowsLw(false /*force*/);
   2547 
   2548             if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG, "addWindow: New client "
   2549                     + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
   2550 
   2551             if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
   2552                 reportNewConfig = true;
   2553             }
   2554         }
   2555 
   2556         if (reportNewConfig) {
   2557             sendNewConfiguration();
   2558         }
   2559 
   2560         Binder.restoreCallingIdentity(origId);
   2561 
   2562         return res;
   2563     }
   2564 
   2565     /**
   2566      * Returns whether screen capture is disabled for all windows of a specific user.
   2567      */
   2568     boolean isScreenCaptureDisabledLocked(int userId) {
   2569         Boolean disabled = mScreenCaptureDisabled.get(userId);
   2570         if (disabled == null) {
   2571             return false;
   2572         }
   2573         return disabled;
   2574     }
   2575 
   2576     /**
   2577      * Set mScreenCaptureDisabled for specific user
   2578      */
   2579     @Override
   2580     public void setScreenCaptureDisabled(int userId, boolean disabled) {
   2581         int callingUid = Binder.getCallingUid();
   2582         if (callingUid != Process.SYSTEM_UID) {
   2583             throw new SecurityException("Only system can call setScreenCaptureDisabled.");
   2584         }
   2585 
   2586         synchronized(mWindowMap) {
   2587             mScreenCaptureDisabled.put(userId, disabled);
   2588         }
   2589     }
   2590 
   2591     public void removeWindow(Session session, IWindow client) {
   2592         synchronized(mWindowMap) {
   2593             WindowState win = windowForClientLocked(session, client, false);
   2594             if (win == null) {
   2595                 return;
   2596             }
   2597             removeWindowLocked(session, win);
   2598         }
   2599     }
   2600 
   2601     public void removeWindowLocked(Session session, WindowState win) {
   2602         if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
   2603             if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win);
   2604         }
   2605 
   2606         if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v(
   2607                 TAG, "Remove " + win + " client="
   2608                 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder()))
   2609                 + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers="
   2610                 + Debug.getCallers(4));
   2611 
   2612         final long origId = Binder.clearCallingIdentity();
   2613 
   2614         win.disposeInputChannel();
   2615 
   2616         if (DEBUG_APP_TRANSITIONS) Slog.v(
   2617                 TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl
   2618                 + " mExiting=" + win.mExiting
   2619                 + " isAnimating=" + win.mWinAnimator.isAnimating()
   2620                 + " app-animation="
   2621                 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
   2622                 + " inPendingTransaction="
   2623                 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
   2624                 + " mDisplayFrozen=" + mDisplayFrozen);
   2625         // Visibility of the removed window. Will be used later to update orientation later on.
   2626         boolean wasVisible = false;
   2627         // First, see if we need to run an animation.  If we do, we have
   2628         // to hold off on removing the window until the animation is done.
   2629         // If the display is frozen, just remove immediately, since the
   2630         // animation wouldn't be seen.
   2631         if (win.mHasSurface && okToDisplay()) {
   2632             // If we are not currently running the exit animation, we
   2633             // need to see about starting one.
   2634             wasVisible = win.isWinVisibleLw();
   2635             if (wasVisible) {
   2636 
   2637                 int transit = WindowManagerPolicy.TRANSIT_EXIT;
   2638                 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
   2639                     transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
   2640                 }
   2641                 // Try starting an animation.
   2642                 if (win.mWinAnimator.applyAnimationLocked(transit, false)) {
   2643                     win.mExiting = true;
   2644                 }
   2645                 //TODO (multidisplay): Magnification is supported only for the default display.
   2646                 if (mAccessibilityController != null
   2647                         && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
   2648                     mAccessibilityController.onWindowTransitionLocked(win, transit);
   2649                 }
   2650             }
   2651             if (win.mExiting || win.mWinAnimator.isAnimating()) {
   2652                 // The exit animation is running... wait for it!
   2653                 //Slog.i(TAG, "*** Running exit animation...");
   2654                 win.mExiting = true;
   2655                 win.mRemoveOnExit = true;
   2656                 final DisplayContent displayContent = win.getDisplayContent();
   2657                 if (displayContent != null) {
   2658                     displayContent.layoutNeeded = true;
   2659                 }
   2660                 final boolean focusChanged = updateFocusedWindowLocked(
   2661                         UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
   2662                 performLayoutAndPlaceSurfacesLocked();
   2663                 if (win.mAppToken != null) {
   2664                     win.mAppToken.updateReportedVisibilityLocked();
   2665                 }
   2666                 if (focusChanged) {
   2667                     mInputMonitor.updateInputWindowsLw(false /*force*/);
   2668                 }
   2669                 //dump();
   2670                 Binder.restoreCallingIdentity(origId);
   2671                 return;
   2672             }
   2673         }
   2674 
   2675         removeWindowInnerLocked(session, win);
   2676         // Removing a visible window will effect the computed orientation
   2677         // So just update orientation if needed.
   2678         if (wasVisible && updateOrientationFromAppTokensLocked(false)) {
   2679             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
   2680         }
   2681         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
   2682         Binder.restoreCallingIdentity(origId);
   2683     }
   2684 
   2685     void removeWindowInnerLocked(Session session, WindowState win) {
   2686         if (win.mRemoved) {
   2687             // Nothing to do.
   2688             return;
   2689         }
   2690 
   2691         for (int i=win.mChildWindows.size()-1; i>=0; i--) {
   2692             WindowState cwin = win.mChildWindows.get(i);
   2693             Slog.w(TAG, "Force-removing child win " + cwin + " from container "
   2694                     + win);
   2695             removeWindowInnerLocked(cwin.mSession, cwin);
   2696         }
   2697 
   2698         win.mRemoved = true;
   2699 
   2700         if (mInputMethodTarget == win) {
   2701             moveInputMethodWindowsIfNeededLocked(false);
   2702         }
   2703 
   2704         if (false) {
   2705             RuntimeException e = new RuntimeException("here");
   2706             e.fillInStackTrace();
   2707             Slog.w(TAG, "Removing window " + win, e);
   2708         }
   2709 
   2710         mPolicy.removeWindowLw(win);
   2711         win.removeLocked();
   2712 
   2713         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win);
   2714         mWindowMap.remove(win.mClient.asBinder());
   2715         if (win.mAppOp != AppOpsManager.OP_NONE) {
   2716             mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
   2717         }
   2718 
   2719         mPendingRemove.remove(win);
   2720         mResizingWindows.remove(win);
   2721         mWindowsChanged = true;
   2722         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
   2723 
   2724         if (mInputMethodWindow == win) {
   2725             mInputMethodWindow = null;
   2726         } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
   2727             mInputMethodDialogs.remove(win);
   2728         }
   2729 
   2730         final WindowToken token = win.mToken;
   2731         final AppWindowToken atoken = win.mAppToken;
   2732         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token);
   2733         token.windows.remove(win);
   2734         if (atoken != null) {
   2735             atoken.allAppWindows.remove(win);
   2736         }
   2737         if (localLOGV) Slog.v(
   2738                 TAG, "**** Removing window " + win + ": count="
   2739                 + token.windows.size());
   2740         if (token.windows.size() == 0) {
   2741             if (!token.explicit) {
   2742                 mTokenMap.remove(token.token);
   2743             } else if (atoken != null) {
   2744                 atoken.firstWindowDrawn = false;
   2745             }
   2746         }
   2747 
   2748         if (atoken != null) {
   2749             if (atoken.startingWindow == win) {
   2750                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Notify removed startingWindow " + win);
   2751                 scheduleRemoveStartingWindowLocked(atoken);
   2752             } else
   2753             if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
   2754                 // If this is the last window and we had requested a starting
   2755                 // transition window, well there is no point now.
   2756                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling last startingWindow");
   2757                 atoken.startingData = null;
   2758             } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
   2759                 // If this is the last window except for a starting transition
   2760                 // window, we need to get rid of the starting transition.
   2761                 scheduleRemoveStartingWindowLocked(atoken);
   2762             }
   2763         }
   2764 
   2765         if (win.mAttrs.type == TYPE_WALLPAPER) {
   2766             mLastWallpaperTimeoutTime = 0;
   2767             getDefaultDisplayContentLocked().pendingLayoutChanges |=
   2768                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
   2769         } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
   2770             getDefaultDisplayContentLocked().pendingLayoutChanges |=
   2771                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
   2772         }
   2773 
   2774         final WindowList windows = win.getWindowList();
   2775         if (windows != null) {
   2776             windows.remove(win);
   2777             if (!mInLayout) {
   2778                 assignLayersLocked(windows);
   2779                 final DisplayContent displayContent = win.getDisplayContent();
   2780                 if (displayContent != null) {
   2781                     displayContent.layoutNeeded = true;
   2782                 }
   2783                 performLayoutAndPlaceSurfacesLocked();
   2784                 if (win.mAppToken != null) {
   2785                     win.mAppToken.updateReportedVisibilityLocked();
   2786                 }
   2787             }
   2788         }
   2789 
   2790         mInputMonitor.updateInputWindowsLw(true /*force*/);
   2791     }
   2792 
   2793     public void updateAppOpsState() {
   2794         synchronized(mWindowMap) {
   2795             final int numDisplays = mDisplayContents.size();
   2796             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
   2797                 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
   2798                 final int numWindows = windows.size();
   2799                 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
   2800                     final WindowState win = windows.get(winNdx);
   2801                     if (win.mAppOp != AppOpsManager.OP_NONE) {
   2802                         final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
   2803                                 win.getOwningPackage());
   2804                         win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED);
   2805                     }
   2806                 }
   2807             }
   2808         }
   2809     }
   2810 
   2811     static void logSurface(WindowState w, String msg, RuntimeException where) {
   2812         String str = "  SURFACE " + msg + ": " + w;
   2813         if (where != null) {
   2814             Slog.i(TAG, str, where);
   2815         } else {
   2816             Slog.i(TAG, str);
   2817         }
   2818     }
   2819 
   2820     static void logSurface(SurfaceControl s, String title, String msg, RuntimeException where) {
   2821         String str = "  SURFACE " + s + ": " + msg + " / " + title;
   2822         if (where != null) {
   2823             Slog.i(TAG, str, where);
   2824         } else {
   2825             Slog.i(TAG, str);
   2826         }
   2827     }
   2828 
   2829     void setTransparentRegionWindow(Session session, IWindow client, Region region) {
   2830         long origId = Binder.clearCallingIdentity();
   2831         try {
   2832             synchronized (mWindowMap) {
   2833                 WindowState w = windowForClientLocked(session, client, false);
   2834                 if ((w != null) && w.mHasSurface) {
   2835                     w.mWinAnimator.setTransparentRegionHintLocked(region);
   2836                 }
   2837             }
   2838         } finally {
   2839             Binder.restoreCallingIdentity(origId);
   2840         }
   2841     }
   2842 
   2843     void setInsetsWindow(Session session, IWindow client,
   2844             int touchableInsets, Rect contentInsets,
   2845             Rect visibleInsets, Region touchableRegion) {
   2846         long origId = Binder.clearCallingIdentity();
   2847         try {
   2848             synchronized (mWindowMap) {
   2849                 WindowState w = windowForClientLocked(session, client, false);
   2850                 if (w != null) {
   2851                     w.mGivenInsetsPending = false;
   2852                     w.mGivenContentInsets.set(contentInsets);
   2853                     w.mGivenVisibleInsets.set(visibleInsets);
   2854                     w.mGivenTouchableRegion.set(touchableRegion);
   2855                     w.mTouchableInsets = touchableInsets;
   2856                     if (w.mGlobalScale != 1) {
   2857                         w.mGivenContentInsets.scale(w.mGlobalScale);
   2858                         w.mGivenVisibleInsets.scale(w.mGlobalScale);
   2859                         w.mGivenTouchableRegion.scale(w.mGlobalScale);
   2860                     }
   2861                     final DisplayContent displayContent = w.getDisplayContent();
   2862                     if (displayContent != null) {
   2863                         displayContent.layoutNeeded = true;
   2864                     }
   2865                     performLayoutAndPlaceSurfacesLocked();
   2866                 }
   2867             }
   2868         } finally {
   2869             Binder.restoreCallingIdentity(origId);
   2870         }
   2871     }
   2872 
   2873     public void getWindowDisplayFrame(Session session, IWindow client,
   2874             Rect outDisplayFrame) {
   2875         synchronized(mWindowMap) {
   2876             WindowState win = windowForClientLocked(session, client, false);
   2877             if (win == null) {
   2878                 outDisplayFrame.setEmpty();
   2879                 return;
   2880             }
   2881             outDisplayFrame.set(win.mDisplayFrame);
   2882         }
   2883     }
   2884 
   2885     public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
   2886             float xStep, float yStep) {
   2887         if (window.mWallpaperX != x || window.mWallpaperY != y)  {
   2888             window.mWallpaperX = x;
   2889             window.mWallpaperY = y;
   2890             window.mWallpaperXStep = xStep;
   2891             window.mWallpaperYStep = yStep;
   2892             updateWallpaperOffsetLocked(window, true);
   2893         }
   2894     }
   2895 
   2896     void wallpaperCommandComplete(IBinder window, Bundle result) {
   2897         synchronized (mWindowMap) {
   2898             if (mWaitingOnWallpaper != null &&
   2899                     mWaitingOnWallpaper.mClient.asBinder() == window) {
   2900                 mWaitingOnWallpaper = null;
   2901                 mWindowMap.notifyAll();
   2902             }
   2903         }
   2904     }
   2905 
   2906     public void setWindowWallpaperDisplayOffsetLocked(WindowState window, int x, int y) {
   2907         if (window.mWallpaperDisplayOffsetX != x || window.mWallpaperDisplayOffsetY != y)  {
   2908             window.mWallpaperDisplayOffsetX = x;
   2909             window.mWallpaperDisplayOffsetY = y;
   2910             updateWallpaperOffsetLocked(window, true);
   2911         }
   2912     }
   2913 
   2914     public Bundle sendWindowWallpaperCommandLocked(WindowState window,
   2915             String action, int x, int y, int z, Bundle extras, boolean sync) {
   2916         if (window == mWallpaperTarget || window == mLowerWallpaperTarget
   2917                 || window == mUpperWallpaperTarget) {
   2918             boolean doWait = sync;
   2919             int curTokenIndex = mWallpaperTokens.size();
   2920             while (curTokenIndex > 0) {
   2921                 curTokenIndex--;
   2922                 WindowToken token = mWallpaperTokens.get(curTokenIndex);
   2923                 int curWallpaperIndex = token.windows.size();
   2924                 while (curWallpaperIndex > 0) {
   2925                     curWallpaperIndex--;
   2926                     WindowState wallpaper = token.windows.get(curWallpaperIndex);
   2927                     try {
   2928                         wallpaper.mClient.dispatchWallpaperCommand(action,
   2929                                 x, y, z, extras, sync);
   2930                         // We only want to be synchronous with one wallpaper.
   2931                         sync = false;
   2932                     } catch (RemoteException e) {
   2933                     }
   2934                 }
   2935             }
   2936 
   2937             if (doWait) {
   2938                 // XXX Need to wait for result.
   2939             }
   2940         }
   2941 
   2942         return null;
   2943     }
   2944 
   2945     public void setUniverseTransformLocked(WindowState window, float alpha,
   2946             float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) {
   2947         Transformation transform = window.mWinAnimator.mUniverseTransform;
   2948         transform.setAlpha(alpha);
   2949         Matrix matrix = transform.getMatrix();
   2950         matrix.getValues(mTmpFloats);
   2951         mTmpFloats[Matrix.MTRANS_X] = offx;
   2952         mTmpFloats[Matrix.MTRANS_Y] = offy;
   2953         mTmpFloats[Matrix.MSCALE_X] = dsdx;
   2954         mTmpFloats[Matrix.MSKEW_Y] = dtdx;
   2955         mTmpFloats[Matrix.MSKEW_X] = dsdy;
   2956         mTmpFloats[Matrix.MSCALE_Y] = dtdy;
   2957         matrix.setValues(mTmpFloats);
   2958         final DisplayContent displayContent = window.getDisplayContent();
   2959         if (displayContent == null) {
   2960             return;
   2961         }
   2962 
   2963         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
   2964         final RectF dispRect = new RectF(0, 0,
   2965                 displayInfo.logicalWidth, displayInfo.logicalHeight);
   2966         matrix.mapRect(dispRect);
   2967         window.mGivenTouchableRegion.set(0, 0,
   2968                 displayInfo.logicalWidth, displayInfo.logicalHeight);
   2969         window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top,
   2970                 (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE);
   2971         window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
   2972         displayContent.layoutNeeded = true;
   2973         performLayoutAndPlaceSurfacesLocked();
   2974     }
   2975 
   2976     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
   2977         synchronized (mWindowMap) {
   2978             if (mAccessibilityController != null) {
   2979                 WindowState window = mWindowMap.get(token);
   2980                 //TODO (multidisplay): Magnification is supported only for the default display.
   2981                 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
   2982                     mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle);
   2983                 }
   2984             }
   2985         }
   2986     }
   2987 
   2988     public IWindowId getWindowId(IBinder token) {
   2989         synchronized (mWindowMap) {
   2990             WindowState window = mWindowMap.get(token);
   2991             return window != null ? window.mWindowId : null;
   2992         }
   2993     }
   2994 
   2995     public int relayoutWindow(Session session, IWindow client, int seq,
   2996             WindowManager.LayoutParams attrs, int requestedWidth,
   2997             int requestedHeight, int viewVisibility, int flags,
   2998             Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
   2999             Rect outVisibleInsets, Rect outStableInsets, Configuration outConfig,
   3000             Surface outSurface) {
   3001         boolean toBeDisplayed = false;
   3002         boolean inTouchMode;
   3003         boolean configChanged;
   3004         boolean surfaceChanged = false;
   3005         boolean animating;
   3006         boolean hasStatusBarPermission =
   3007                 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
   3008                         == PackageManager.PERMISSION_GRANTED;
   3009 
   3010         long origId = Binder.clearCallingIdentity();
   3011 
   3012         synchronized(mWindowMap) {
   3013             WindowState win = windowForClientLocked(session, client, false);
   3014             if (win == null) {
   3015                 return 0;
   3016             }
   3017             WindowStateAnimator winAnimator = win.mWinAnimator;
   3018             if (viewVisibility != View.GONE && (win.mRequestedWidth != requestedWidth
   3019                     || win.mRequestedHeight != requestedHeight)) {
   3020                 win.mLayoutNeeded = true;
   3021                 win.mRequestedWidth = requestedWidth;
   3022                 win.mRequestedHeight = requestedHeight;
   3023             }
   3024 
   3025             if (attrs != null) {
   3026                 mPolicy.adjustWindowParamsLw(attrs);
   3027             }
   3028 
   3029             // if they don't have the permission, mask out the status bar bits
   3030             int systemUiVisibility = 0;
   3031             if (attrs != null) {
   3032                 systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility);
   3033                 if ((systemUiVisibility & StatusBarManager.DISABLE_MASK) != 0) {
   3034                     if (!hasStatusBarPermission) {
   3035                         systemUiVisibility &= ~StatusBarManager.DISABLE_MASK;
   3036                     }
   3037                 }
   3038             }
   3039 
   3040             if (attrs != null && seq == win.mSeq) {
   3041                 win.mSystemUiVisibility = systemUiVisibility;
   3042             }
   3043 
   3044             winAnimator.mSurfaceDestroyDeferred =
   3045                     (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
   3046 
   3047             int attrChanges = 0;
   3048             int flagChanges = 0;
   3049             if (attrs != null) {
   3050                 if (win.mAttrs.type != attrs.type) {
   3051                     throw new IllegalArgumentException(
   3052                             "Window type can not be changed after the window is added.");
   3053                 }
   3054                 flagChanges = win.mAttrs.flags ^= attrs.flags;
   3055                 attrChanges = win.mAttrs.copyFrom(attrs);
   3056                 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
   3057                         | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
   3058                     win.mLayoutNeeded = true;
   3059                 }
   3060             }
   3061 
   3062             if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
   3063                     + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
   3064 
   3065             win.mEnforceSizeCompat =
   3066                     (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
   3067 
   3068             if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
   3069                 winAnimator.mAlpha = attrs.alpha;
   3070             }
   3071 
   3072             final boolean scaledWindow =
   3073                 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
   3074 
   3075             if (scaledWindow) {
   3076                 // requested{Width|Height} Surface's physical size
   3077                 // attrs.{width|height} Size on screen
   3078                 win.mHScale = (attrs.width  != requestedWidth)  ?
   3079                         (attrs.width  / (float)requestedWidth) : 1.0f;
   3080                 win.mVScale = (attrs.height != requestedHeight) ?
   3081                         (attrs.height / (float)requestedHeight) : 1.0f;
   3082             } else {
   3083                 win.mHScale = win.mVScale = 1;
   3084             }
   3085 
   3086             boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
   3087 
   3088             final boolean isDefaultDisplay = win.isDefaultDisplay();
   3089             boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
   3090                     || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
   3091                     || (!win.mRelayoutCalled));
   3092 
   3093             boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
   3094                     && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
   3095             wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
   3096 
   3097             win.mRelayoutCalled = true;
   3098             final int oldVisibility = win.mViewVisibility;
   3099             win.mViewVisibility = viewVisibility;
   3100             if (DEBUG_SCREEN_ON) {
   3101                 RuntimeException stack = new RuntimeException();
   3102                 stack.fillInStackTrace();
   3103                 Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility
   3104                         + " newVis=" + viewVisibility, stack);
   3105             }
   3106             if (viewVisibility == View.VISIBLE &&
   3107                     (win.mAppToken == null || !win.mAppToken.clientHidden)) {
   3108                 toBeDisplayed = !win.isVisibleLw();
   3109                 if (win.mExiting) {
   3110                     winAnimator.cancelExitAnimationForNextAnimationLocked();
   3111                     win.mExiting = false;
   3112                 }
   3113                 if (win.mDestroying) {
   3114                     win.mDestroying = false;
   3115                     mDestroySurface.remove(win);
   3116                 }
   3117                 if (oldVisibility == View.GONE) {
   3118                     winAnimator.mEnterAnimationPending = true;
   3119                 }
   3120                 winAnimator.mEnteringAnimation = true;
   3121                 if (toBeDisplayed) {
   3122                     if (win.isDrawnLw() && okToDisplay()) {
   3123                         winAnimator.applyEnterAnimationLocked();
   3124                     }
   3125                     if ((win.mAttrs.flags
   3126                             & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
   3127                         if (DEBUG_VISIBILITY) Slog.v(TAG,
   3128                                 "Relayout window turning screen on: " + win);
   3129                         win.mTurnOnScreen = true;
   3130                     }
   3131                     if (win.isConfigChanged()) {
   3132                         if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win
   3133                                 + " visible with new config: " + mCurConfiguration);
   3134                         outConfig.setTo(mCurConfiguration);
   3135                     }
   3136                 }
   3137                 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
   3138                     // To change the format, we need to re-build the surface.
   3139                     winAnimator.destroySurfaceLocked();
   3140                     toBeDisplayed = true;
   3141                     surfaceChanged = true;
   3142                 }
   3143                 try {
   3144                     if (!win.mHasSurface) {
   3145                         surfaceChanged = true;
   3146                     }
   3147                     SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
   3148                     if (surfaceControl != null) {
   3149                         outSurface.copyFrom(surfaceControl);
   3150                         if (SHOW_TRANSACTIONS) Slog.i(TAG,
   3151                                 "  OUT SURFACE " + outSurface + ": copied");
   3152                     } else {
   3153                         // For some reason there isn't a surface.  Clear the
   3154                         // caller's object so they see the same state.
   3155                         outSurface.release();
   3156                     }
   3157                 } catch (Exception e) {
   3158                     mInputMonitor.updateInputWindowsLw(true /*force*/);
   3159 
   3160                     Slog.w(TAG, "Exception thrown when creating surface for client "
   3161                              + client + " (" + win.mAttrs.getTitle() + ")",
   3162                              e);
   3163                     Binder.restoreCallingIdentity(origId);
   3164                     return 0;
   3165                 }
   3166                 if (toBeDisplayed) {
   3167                     focusMayChange = isDefaultDisplay;
   3168                 }
   3169                 if (win.mAttrs.type == TYPE_INPUT_METHOD
   3170                         && mInputMethodWindow == null) {
   3171                     mInputMethodWindow = win;
   3172                     imMayMove = true;
   3173                 }
   3174                 if (win.mAttrs.type == TYPE_BASE_APPLICATION
   3175                         && win.mAppToken != null
   3176                         && win.mAppToken.startingWindow != null) {
   3177                     // Special handling of starting window over the base
   3178                     // window of the app: propagate lock screen flags to it,
   3179                     // to provide the correct semantics while starting.
   3180                     final int mask =
   3181                         WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
   3182                         | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
   3183                         | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
   3184                     WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
   3185                     sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
   3186                 }
   3187             } else {
   3188                 winAnimator.mEnterAnimationPending = false;
   3189                 winAnimator.mEnteringAnimation = false;
   3190                 if (winAnimator.mSurfaceControl != null) {
   3191                     if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
   3192                             + ": mExiting=" + win.mExiting);
   3193                     // If we are not currently running the exit animation, we
   3194                     // need to see about starting one.
   3195                     if (!win.mExiting) {
   3196                         surfaceChanged = true;
   3197                         // Try starting an animation; if there isn't one, we
   3198                         // can destroy the surface right away.
   3199                         int transit = WindowManagerPolicy.TRANSIT_EXIT;
   3200                         if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
   3201                             transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
   3202                         }
   3203                         if (win.isWinVisibleLw() &&
   3204                                 winAnimator.applyAnimationLocked(transit, false)) {
   3205                             focusMayChange = isDefaultDisplay;
   3206                             win.mExiting = true;
   3207                         } else if (win.mWinAnimator.isAnimating()) {
   3208                             // Currently in a hide animation... turn this into
   3209                             // an exit.
   3210                             win.mExiting = true;
   3211                         } else if (win == mWallpaperTarget) {
   3212                             // If the wallpaper is currently behind this
   3213                             // window, we need to change both of them inside
   3214                             // of a transaction to avoid artifacts.
   3215                             win.mExiting = true;
   3216                             win.mWinAnimator.mAnimating = true;
   3217                         } else {
   3218                             if (mInputMethodWindow == win) {
   3219                                 mInputMethodWindow = null;
   3220                             }
   3221                             winAnimator.destroySurfaceLocked();
   3222                         }
   3223                         //TODO (multidisplay): Magnification is supported only for the default
   3224                         if (mAccessibilityController != null
   3225                                 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
   3226                             mAccessibilityController.onWindowTransitionLocked(win, transit);
   3227                         }
   3228                     }
   3229                 }
   3230 
   3231                 outSurface.release();
   3232                 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
   3233             }
   3234 
   3235             if (focusMayChange) {
   3236                 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
   3237                 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
   3238                         false /*updateInputWindows*/)) {
   3239                     imMayMove = false;
   3240                 }
   3241                 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
   3242             }
   3243 
   3244             // updateFocusedWindowLocked() already assigned layers so we only need to
   3245             // reassign them at this point if the IM window state gets shuffled
   3246             if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) {
   3247                 // Little hack here -- we -should- be able to rely on the
   3248                 // function to return true if the IME has moved and needs
   3249                 // its layer recomputed.  However, if the IME was hidden
   3250                 // and isn't actually moved in the list, its layer may be
   3251                 // out of data so we make sure to recompute it.
   3252                 assignLayersLocked(win.getWindowList());
   3253             }
   3254 
   3255             if (wallpaperMayMove) {
   3256                 getDefaultDisplayContentLocked().pendingLayoutChanges |=
   3257                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
   3258             }
   3259 
   3260             final DisplayContent displayContent = win.getDisplayContent();
   3261             if (displayContent != null) {
   3262                 displayContent.layoutNeeded = true;
   3263             }
   3264             win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
   3265             configChanged = updateOrientationFromAppTokensLocked(false);
   3266             performLayoutAndPlaceSurfacesLocked();
   3267             if (toBeDisplayed && win.mIsWallpaper) {
   3268                 DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
   3269                 updateWallpaperOffsetLocked(win,
   3270                         displayInfo.logicalWidth, displayInfo.logicalHeight, false);
   3271             }
   3272             if (win.mAppToken != null) {
   3273                 win.mAppToken.updateReportedVisibilityLocked();
   3274             }
   3275             outFrame.set(win.mCompatFrame);
   3276             outOverscanInsets.set(win.mOverscanInsets);
   3277             outContentInsets.set(win.mContentInsets);
   3278             outVisibleInsets.set(win.mVisibleInsets);
   3279             outStableInsets.set(win.mStableInsets);
   3280             if (localLOGV) Slog.v(
   3281                 TAG, "Relayout given client " + client.asBinder()
   3282                 + ", requestedWidth=" + requestedWidth
   3283                 + ", requestedHeight=" + requestedHeight
   3284                 + ", viewVisibility=" + viewVisibility
   3285                 + "\nRelayout returning frame=" + outFrame
   3286                 + ", surface=" + outSurface);
   3287 
   3288             if (localLOGV || DEBUG_FOCUS) Slog.v(
   3289                 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
   3290 
   3291             inTouchMode = mInTouchMode;
   3292             animating = mAnimator.mAnimating && win.mWinAnimator.isAnimating();
   3293             if (animating && !mRelayoutWhileAnimating.contains(win)) {
   3294                 mRelayoutWhileAnimating.add(win);
   3295             }
   3296 
   3297             mInputMonitor.updateInputWindowsLw(true /*force*/);
   3298 
   3299             if (DEBUG_LAYOUT) {
   3300                 Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
   3301             }
   3302         }
   3303 
   3304         if (configChanged) {
   3305             sendNewConfiguration();
   3306         }
   3307 
   3308         Binder.restoreCallingIdentity(origId);
   3309 
   3310         return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0)
   3311                 | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0)
   3312                 | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0)
   3313                 | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0);
   3314     }
   3315 
   3316     public void performDeferredDestroyWindow(Session session, IWindow client) {
   3317         long origId = Binder.clearCallingIdentity();
   3318 
   3319         try {
   3320             synchronized (mWindowMap) {
   3321                 WindowState win = windowForClientLocked(session, client, false);
   3322                 if (win == null) {
   3323                     return;
   3324                 }
   3325                 win.mWinAnimator.destroyDeferredSurfaceLocked();
   3326             }
   3327         } finally {
   3328             Binder.restoreCallingIdentity(origId);
   3329         }
   3330     }
   3331 
   3332     public boolean outOfMemoryWindow(Session session, IWindow client) {
   3333         long origId = Binder.clearCallingIdentity();
   3334 
   3335         try {
   3336             synchronized (mWindowMap) {
   3337                 WindowState win = windowForClientLocked(session, client, false);
   3338                 if (win == null) {
   3339                     return false;
   3340                 }
   3341                 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false);
   3342             }
   3343         } finally {
   3344             Binder.restoreCallingIdentity(origId);
   3345         }
   3346     }
   3347 
   3348     public void finishDrawingWindow(Session session, IWindow client) {
   3349         final long origId = Binder.clearCallingIdentity();
   3350         try {
   3351             synchronized (mWindowMap) {
   3352                 WindowState win = windowForClientLocked(session, client, false);
   3353                 if (win != null && win.mWinAnimator.finishDrawingLocked()) {
   3354                     if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
   3355                         getDefaultDisplayContentLocked().pendingLayoutChanges |=
   3356                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
   3357                     }
   3358                     final DisplayContent displayContent = win.getDisplayContent();
   3359                     if (displayContent != null) {
   3360                         displayContent.layoutNeeded = true;
   3361                     }
   3362                     requestTraversalLocked();
   3363                 }
   3364             }
   3365         } finally {
   3366             Binder.restoreCallingIdentity(origId);
   3367         }
   3368     }
   3369 
   3370     private boolean applyAnimationLocked(AppWindowToken atoken,
   3371             WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) {
   3372         // Only apply an animation if the display isn't frozen.  If it is
   3373         // frozen, there is no reason to animate and it can cause strange
   3374         // artifacts when we unfreeze the display if some different animation
   3375         // is running.
   3376         if (okToDisplay()) {
   3377             DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
   3378             final int width = displayInfo.appWidth;
   3379             final int height = displayInfo.appHeight;
   3380             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken="
   3381                     + atoken);
   3382 
   3383             // Determine the visible rect to calculate the thumbnail clip
   3384             WindowState win = atoken.findMainWindow();
   3385             Rect containingFrame = new Rect(0, 0, width, height);
   3386             Rect contentInsets = new Rect();
   3387             boolean isFullScreen = true;
   3388             if (win != null) {
   3389                 if (win.mContainingFrame != null) {
   3390                     containingFrame.set(win.mContainingFrame);
   3391                 }
   3392                 if (win.mContentInsets != null) {
   3393                     contentInsets.set(win.mContentInsets);
   3394                 }
   3395                 isFullScreen =
   3396                         ((win.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) ==
   3397                                 SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) ||
   3398                                 ((win.mAttrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0);
   3399             }
   3400 
   3401             if (atoken.mLaunchTaskBehind) {
   3402                 // Differentiate the two animations. This one which is briefly on the screen
   3403                 // gets the !enter animation, and the other activity which remains on the
   3404                 // screen gets the enter animation. Both appear in the mOpeningApps set.
   3405                 enter = false;
   3406             }
   3407             Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height,
   3408                     mCurConfiguration.orientation, containingFrame, contentInsets, isFullScreen,
   3409                     isVoiceInteraction);
   3410             if (a != null) {
   3411                 if (DEBUG_ANIM) {
   3412                     RuntimeException e = null;
   3413                     if (!HIDE_STACK_CRAWLS) {
   3414                         e = new RuntimeException();
   3415                         e.fillInStackTrace();
   3416                     }
   3417                     Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e);
   3418                 }
   3419                 atoken.mAppAnimator.setAnimation(a, width, height);
   3420             }
   3421         } else {
   3422             atoken.mAppAnimator.clearAnimation();
   3423         }
   3424 
   3425         return atoken.mAppAnimator.animation != null;
   3426     }
   3427 
   3428     // -------------------------------------------------------------
   3429     // Application Window Tokens
   3430     // -------------------------------------------------------------
   3431 
   3432     public void validateAppTokens(int stackId, List<TaskGroup> tasks) {
   3433         synchronized (mWindowMap) {
   3434             int t = tasks.size() - 1;
   3435             if (t < 0) {
   3436                 Slog.w(TAG, "validateAppTokens: empty task list");
   3437                 return;
   3438             }
   3439 
   3440             TaskGroup task = tasks.get(0);
   3441             int taskId = task.taskId;
   3442             Task targetTask = mTaskIdToTask.get(taskId);
   3443             DisplayContent displayContent = targetTask.getDisplayContent();
   3444             if (displayContent == null) {
   3445                 Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId);
   3446                 return;
   3447             }
   3448 
   3449             final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks();
   3450             int taskNdx;
   3451             for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) {
   3452                 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens;
   3453                 task = tasks.get(t);
   3454                 List<IApplicationToken> tokens = task.tokens;
   3455 
   3456                 DisplayContent lastDisplayContent = displayContent;
   3457                 displayContent = mTaskIdToTask.get(taskId).getDisplayContent();
   3458                 if (displayContent != lastDisplayContent) {
   3459                     Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!");
   3460                     return;
   3461                 }
   3462 
   3463                 int tokenNdx;
   3464                 int v;
   3465                 for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1;
   3466                         tokenNdx >= 0 && v >= 0; ) {
   3467                     final AppWindowToken atoken = localTokens.get(tokenNdx);
   3468                     if (atoken.removed) {
   3469                         --tokenNdx;
   3470                         continue;
   3471                     }
   3472                     if (tokens.get(v) != atoken.token) {
   3473                         break;
   3474                     }
   3475                     --tokenNdx;
   3476                     v--;
   3477                 }
   3478 
   3479                 if (tokenNdx >= 0 || v >= 0) {
   3480                     break;
   3481                 }
   3482             }
   3483 
   3484             if (taskNdx >= 0 || t >= 0) {
   3485                 Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks);
   3486                 Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + localTasks);
   3487                 Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4));
   3488             }
   3489         }
   3490     }
   3491 
   3492     public void validateStackOrder(Integer[] remoteStackIds) {
   3493         // TODO:
   3494     }
   3495 
   3496     boolean checkCallingPermission(String permission, String func) {
   3497         // Quick check: if the calling permission is me, it's all okay.
   3498         if (Binder.getCallingPid() == Process.myPid()) {
   3499             return true;
   3500         }
   3501 
   3502         if (mContext.checkCallingPermission(permission)
   3503                 == PackageManager.PERMISSION_GRANTED) {
   3504             return true;
   3505         }
   3506         String msg = "Permission Denial: " + func + " from pid="
   3507                 + Binder.getCallingPid()
   3508                 + ", uid=" + Binder.getCallingUid()
   3509                 + " requires " + permission;
   3510         Slog.w(TAG, msg);
   3511         return false;
   3512     }
   3513 
   3514     boolean okToDisplay() {
   3515         return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn();
   3516     }
   3517 
   3518     AppWindowToken findAppWindowToken(IBinder token) {
   3519         WindowToken wtoken = mTokenMap.get(token);
   3520         if (wtoken == null) {
   3521             return null;
   3522         }
   3523         return wtoken.appWindowToken;
   3524     }
   3525 
   3526     @Override
   3527     public void addWindowToken(IBinder token, int type) {
   3528         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3529                 "addWindowToken()")) {
   3530             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3531         }
   3532 
   3533         synchronized(mWindowMap) {
   3534             WindowToken wtoken = mTokenMap.get(token);
   3535             if (wtoken != null) {
   3536                 Slog.w(TAG, "Attempted to add existing input method token: " + token);
   3537                 return;
   3538             }
   3539             wtoken = new WindowToken(this, token, type, true);
   3540             mTokenMap.put(token, wtoken);
   3541             if (type == TYPE_WALLPAPER) {
   3542                 mWallpaperTokens.add(wtoken);
   3543             }
   3544         }
   3545     }
   3546 
   3547     @Override
   3548     public void removeWindowToken(IBinder token) {
   3549         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3550                 "removeWindowToken()")) {
   3551             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3552         }
   3553 
   3554         final long origId = Binder.clearCallingIdentity();
   3555         synchronized(mWindowMap) {
   3556             DisplayContent displayContent = null;
   3557             WindowToken wtoken = mTokenMap.remove(token);
   3558             if (wtoken != null) {
   3559                 boolean delayed = false;
   3560                 if (!wtoken.hidden) {
   3561                     final int N = wtoken.windows.size();
   3562                     boolean changed = false;
   3563 
   3564                     for (int i=0; i<N; i++) {
   3565                         WindowState win = wtoken.windows.get(i);
   3566                         displayContent = win.getDisplayContent();
   3567 
   3568                         if (win.mWinAnimator.isAnimating()) {
   3569                             delayed = true;
   3570                         }
   3571 
   3572                         if (win.isVisibleNow()) {
   3573                             win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
   3574                                     false);
   3575                             //TODO (multidisplay): Magnification is supported only for the default
   3576                             if (mAccessibilityController != null && win.isDefaultDisplay()) {
   3577                                 mAccessibilityController.onWindowTransitionLocked(win,
   3578                                         WindowManagerPolicy.TRANSIT_EXIT);
   3579                             }
   3580                             changed = true;
   3581                             if (displayContent != null) {
   3582                                 displayContent.layoutNeeded = true;
   3583                             }
   3584                         }
   3585                     }
   3586 
   3587                     wtoken.hidden = true;
   3588 
   3589                     if (changed) {
   3590                         performLayoutAndPlaceSurfacesLocked();
   3591                         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
   3592                                 false /*updateInputWindows*/);
   3593                     }
   3594 
   3595                     if (delayed) {
   3596                         if (displayContent != null) {
   3597                             displayContent.mExitingTokens.add(wtoken);
   3598                         }
   3599                     } else if (wtoken.windowType == TYPE_WALLPAPER) {
   3600                         mWallpaperTokens.remove(wtoken);
   3601                     }
   3602                 }
   3603 
   3604                 mInputMonitor.updateInputWindowsLw(true /*force*/);
   3605             } else {
   3606                 Slog.w(TAG, "Attempted to remove non-existing token: " + token);
   3607             }
   3608         }
   3609         Binder.restoreCallingIdentity(origId);
   3610     }
   3611 
   3612     private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) {
   3613         if (DEBUG_STACK) Slog.i(TAG, "createTask: taskId=" + taskId + " stackId=" + stackId
   3614                 + " atoken=" + atoken);
   3615         final TaskStack stack = mStackIdToStack.get(stackId);
   3616         if (stack == null) {
   3617             throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
   3618         }
   3619         EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
   3620         Task task = new Task(atoken, stack, userId);
   3621         mTaskIdToTask.put(taskId, task);
   3622         stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */);
   3623         return task;
   3624     }
   3625 
   3626     @Override
   3627     public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
   3628             int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
   3629             int configChanges, boolean voiceInteraction, boolean launchTaskBehind) {
   3630         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3631                 "addAppToken()")) {
   3632             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3633         }
   3634 
   3635         // Get the dispatching timeout here while we are not holding any locks so that it
   3636         // can be cached by the AppWindowToken.  The timeout value is used later by the
   3637         // input dispatcher in code that does hold locks.  If we did not cache the value
   3638         // here we would run the chance of introducing a deadlock between the window manager
   3639         // (which holds locks while updating the input dispatcher state) and the activity manager
   3640         // (which holds locks while querying the application token).
   3641         long inputDispatchingTimeoutNanos;
   3642         try {
   3643             inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
   3644         } catch (RemoteException ex) {
   3645             Slog.w(TAG, "Could not get dispatching timeout.", ex);
   3646             inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
   3647         }
   3648 
   3649         synchronized(mWindowMap) {
   3650             AppWindowToken atoken = findAppWindowToken(token.asBinder());
   3651             if (atoken != null) {
   3652                 Slog.w(TAG, "Attempted to add existing app token: " + token);
   3653                 return;
   3654             }
   3655             atoken = new AppWindowToken(this, token, voiceInteraction);
   3656             atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
   3657             atoken.groupId = taskId;
   3658             atoken.appFullscreen = fullscreen;
   3659             atoken.showWhenLocked = showWhenLocked;
   3660             atoken.requestedOrientation = requestedOrientation;
   3661             atoken.layoutConfigChanges = (configChanges &
   3662                     (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
   3663             atoken.mLaunchTaskBehind = launchTaskBehind;
   3664             if (true || DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
   3665                     + " to stack=" + stackId + " task=" + taskId + " at " + addPos);
   3666 
   3667             Task task = mTaskIdToTask.get(taskId);
   3668             if (task == null) {
   3669                 createTask(taskId, stackId, userId, atoken);
   3670             } else {
   3671                 task.addAppToken(addPos, atoken);
   3672             }
   3673 
   3674             mTokenMap.put(token.asBinder(), atoken);
   3675 
   3676             // Application tokens start out hidden.
   3677             atoken.hidden = true;
   3678             atoken.hiddenRequested = true;
   3679 
   3680             //dump();
   3681         }
   3682     }
   3683 
   3684     @Override
   3685     public void setAppGroupId(IBinder token, int groupId) {
   3686         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
   3687                 "setAppGroupId()")) {
   3688             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   3689         }
   3690 
   3691         synchronized(mWindowMap) {
   3692             final AppWindowToken atoken = findAppWindowToken(token);
   3693             if (atoken == null) {
   3694                 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
   3695                 return;
   3696             }
   3697             final Task oldTask = mTaskIdToTask.get(atoken.groupId);
   3698             oldTask.removeAppToken(atoken);
   3699 
   3700             atoken.groupId = groupId;
   3701             Task newTask = mTaskIdToTask.get(groupId);
   3702             if (newTask == null) {
   3703                 newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken);
   3704             } else {
   3705                 newTask.mAppTokens.add(atoken);
   3706             }
   3707         }
   3708     }
   3709 
   3710     public int getOrientationFromWindowsLocked() {
   3711         if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
   3712             // If the display is frozen, some activities may be in the middle
   3713             // of restarting, and thus have removed their old window.  If the
   3714             // window has the flag to hide the lock screen, then the lock screen
   3715             // can re-appear and inflict its own orientation on us.  Keep the
   3716             // orientation stable until this all settles down.
   3717             return mLastWindowForcedOrientation;
   3718         }
   3719 
   3720         // TODO(multidisplay): Change to the correct display.
   3721         final WindowList windows = getDefaultWindowListLocked();
   3722         int pos = windows.size() - 1;
   3723         while (pos >= 0) {
   3724             WindowState win = windows.get(pos);
   3725             pos--;
   3726             if (win.mAppToken != null) {
   3727                 // We hit an application window. so the orientation will be determined by the
   3728                 // app window. No point in continuing further.
   3729                 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
   3730             }
   3731             if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
   3732                 continue;
   3733             }
   3734             int req = win.mAttrs.screenOrientation;
   3735             if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
   3736                     (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
   3737                 continue;
   3738             }
   3739 
   3740             if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req);
   3741             return (mLastWindowForcedOrientation=req);
   3742         }
   3743         return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
   3744     }
   3745 
   3746     public int getOrientationFromAppTokensLocked() {
   3747         int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
   3748         boolean findingBehind = false;
   3749         boolean lastFullscreen = false;
   3750         // TODO: Multi win