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