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;
RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d)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 
SettingsObserver()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
onChange(boolean selfChange, Uri uri)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 
DragInputEventReceiver(InputChannel inputChannel, Looper looper)724         public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
725             super(inputChannel, looper);
726         }
727 
728         @Override
onInputEvent(InputEvent event)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 {
windowsChanged()818         public void windowsChanged();
focusChanged()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 
main(final Context context, final InputManagerService im, final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore)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 
initPolicy()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 
WindowManagerService(Context context, InputManagerService inputManager, boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore)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 
getInputMonitor()1003     public InputMonitor getInputMonitor() {
1004         return mInputMonitor;
1005     }
1006 
1007     @Override
onTransact(int code, Parcel data, Parcel reply, int flags)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 
placeWindowAfter(WindowState pos, WindowState window)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 
placeWindowBefore(WindowState pos, WindowState window)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
findIdxBasedOnAppTokens(WindowState win)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      */
getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent)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      */
indexOfWinInWindowList(WindowState targetWin, WindowList windows)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 
addAppWindowToListLocked(final WindowState win)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 
addFreeWindowToListLocked(final WindowState win)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 
addAttachedWindowToListLocked(final WindowState win, boolean addToToken)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 
addWindowToListInOrderLocked(final WindowState win, boolean addToToken)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 
canBeImeTarget(WindowState w)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      */
findDesiredInputMethodWindowIndexLocked(boolean willMove)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 
addInputMethodWindowToListLocked(WindowState win)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 
setInputMethodAnimLayerAdjustment(int adj)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 
tmpRemoveWindowLocked(int interestingPos, WindowState win)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 
reAddWindowToListInOrderLocked(WindowState win)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 
logWindowList(final WindowList windows, String prefix)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 
moveInputMethodDialogsLocked(int pos)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 
moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers)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 
isWallpaperVisible(WindowState wallpaperTarget)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 
hideWallpapersLocked(final WindowState winGoingAway)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 
adjustWallpaperWindowsLocked()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 
setWallpaperAnimLayerAdjustmentLocked(int adj)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 
updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh, boolean sync)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 
wallpaperOffsetsComplete(IBinder window)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 
updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync)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      */
dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible)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 
updateWallpaperVisibilityLocked()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 
addWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel)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      */
isScreenCaptureDisabledLocked(int userId)2652     boolean isScreenCaptureDisabledLocked(int userId) {
2653         Boolean disabled = mScreenCaptureDisabled.get(userId);
2654         if (disabled == null) {
2655             return false;
2656         }
2657         return disabled;
2658     }
2659 
isSecureLocked(WindowState w)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
setScreenCaptureDisabled(int userId, boolean disabled)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 
removeWindow(Session session, IWindow client)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 
removeWindowLocked(WindowState win)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 
removeWindowInnerLocked(WindowState win)2795     void removeWindowInnerLocked(WindowState win) {
2796         removeWindowInnerLocked(win, true);
2797     }
2798 
removeWindowInnerLocked(WindowState win, boolean performLayout)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 
updateAppOpsState()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 
logSurface(WindowState w, String msg, RuntimeException where)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 
logSurface(SurfaceControl s, String title, String msg, RuntimeException where)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 
setTransparentRegionWindow(Session session, IWindow client, Region region)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 
setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets, Rect visibleInsets, Region touchableRegion)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 
getWindowDisplayFrame(Session session, IWindow client, Rect outDisplayFrame)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 
setWindowWallpaperPositionLocked(WindowState window, float x, float y, float xStep, float yStep)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 
wallpaperCommandComplete(IBinder window, Bundle result)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 
setWindowWallpaperDisplayOffsetLocked(WindowState window, int x, int y)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 
sendWindowWallpaperCommandLocked(WindowState window, String action, int x, int y, int z, Bundle extras, boolean sync)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 
onRectangleOnScreenRequested(IBinder token, Rect rectangle)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 
getWindowId(IBinder token)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 
pokeDrawLock(Session session, IBinder token)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 
relayoutWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Configuration outConfig, Surface outSurface)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 
performDeferredDestroyWindow(Session session, IWindow client)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 
outOfMemoryWindow(Session session, IWindow client)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 
finishDrawingWindow(Session session, IWindow client)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 
applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction)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 
validateAppTokens(int stackId, List<TaskGroup> tasks)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 
validateStackOrder(Integer[] remoteStackIds)3586     public void validateStackOrder(Integer[] remoteStackIds) {
3587         // TODO:
3588     }
3589 
checkCallingPermission(String permission, String func)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 
okToDisplay()3608     boolean okToDisplay() {
3609         return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn();
3610     }
3611 
findAppWindowToken(IBinder token)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
addWindowToken(IBinder token, int type)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
removeWindowToken(IBinder token)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 
createTaskLocked(int taskId, int stackId, int userId, AppWindowToken atoken)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
addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int userId, int configChanges, boolean voiceInteraction, boolean launchTaskBehind)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
setAppTask(IBinder token, int taskId)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 
getOrientationLocked()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
updateOrientationFromAppTokens( Configuration currentConfig, IBinder freezeThisOneIfNeeded)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 
updateOrientationFromAppTokensLocked( Configuration currentConfig, IBinder freezeThisOneIfNeeded)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      */
updateOrientationFromAppTokensLocked(boolean inTransaction)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
setNewConfiguration(Configuration config)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
setAppOrientation(IApplicationToken token, int requestedOrientation)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
getAppOrientation(IApplicationToken token)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. */
setFocusedStackLayer()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 
setFocusedStackFrame()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
setFocusedApp(IBinder token, boolean moveFocusNow)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
prepareAppTransition(int transit, boolean alwaysKeepCurrent)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
getPendingAppTransition()4200     public int getPendingAppTransition() {
4201         return mAppTransition.getAppTransition();
4202     }
4203 
4204     @Override
overridePendingAppTransition(String packageName, int enterAnim, int exitAnim, IRemoteCallback startedCallback)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
overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, int startHeight)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
overridePendingAppTransitionClipReveal(int startX, int startY, int startWidth, int startHeight)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
overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY, IRemoteCallback startedCallback, boolean scaleUp)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
overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp)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
overridePendingAppTransitionInPlace(String packageName, int anim)4251     public void overridePendingAppTransitionInPlace(String packageName, int anim) {
4252         synchronized(mWindowMap) {
4253             mAppTransition.overrideInPlaceAppTransition(packageName, anim);
4254         }
4255     }
4256 
4257     @Override
executeAppTransition()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
setAppStartingWindow(IBinder token, String pkg, int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded)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 
removeAppStartingWindow(IBinder token)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
setAppWillBeHidden(IBinder token)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 
setAppFullscreen(IBinder token, boolean toOpaque)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 
setWindowOpaque(IBinder token, boolean isOpaque)4523     public void setWindowOpaque(IBinder token, boolean isOpaque) {
4524         synchronized (mWindowMap) {
4525             setWindowOpaqueLocked(token, isOpaque);
4526         }
4527     }
4528 
setWindowOpaqueLocked(IBinder token, boolean isOpaque)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 
setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction)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 
updateTokenInPlaceLocked(AppWindowToken wtoken, int transit)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
setAppVisibility(IBinder token, boolean visible)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 
unsetAppFreezingScreenLocked(AppWindowToken wtoken, boolean unfreezeSurfaceNow, boolean force)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 
startAppFreezingScreenLocked(AppWindowToken wtoken)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
startAppFreezingScreen(IBinder token, int configChanges)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
stopAppFreezingScreen(IBinder token, boolean force)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
removeAppToken(IBinder token)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 
scheduleRemoveStartingWindowLocked(AppWindowToken wtoken)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 
dumpAppTokensLocked()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 
dumpWindowsLocked()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 
reAddWindowLocked(int index, WindowState win)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 
reAddAppWindowsLocked(final DisplayContent displayContent, int index, WindowToken token)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 
moveStackWindowsLocked(DisplayContent displayContent)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 
moveTaskToTop(int taskId)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 
moveTaskToBottom(int taskId)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      */
attachStack(int stackId, int displayId)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 
detachStackLocked(DisplayContent displayContent, TaskStack stack)5180     void detachStackLocked(DisplayContent displayContent, TaskStack stack) {
5181         displayContent.detachStack(stack);
5182         stack.detachDisplay();
5183     }
5184 
detachStack(int stackId)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 
removeStack(int stackId)5201     public void removeStack(int stackId) {
5202         synchronized (mWindowMap) {
5203             mStackIdToStack.remove(stackId);
5204         }
5205     }
5206 
removeTask(int taskId)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 
addTask(int taskId, int stackId, boolean toTop)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 
moveTaskToStack(int taskId, int stackId, boolean toTop)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      */
resizeStack(int stackId, Rect bounds)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 
getStackBounds(int stackId, Rect bounds)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.*/
getStackIdWithBounds(Rect bounds)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      */
forceStackToFullscreen(int stackId, boolean forceFullscreen)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
startFreezingScreen(int exitAnim, int enterAnim)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
stopFreezingScreen()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
disableKeyguard(IBinder token, String tag)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
reenableKeyguard(IBinder token)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
exitKeyguardSecurely(final IOnKeyguardExitResult callback)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
inKeyguardRestrictedInputMode()5436     public boolean inKeyguardRestrictedInputMode() {
5437         return mPolicy.inKeyguardRestrictedKeyInputMode();
5438     }
5439 
5440     @Override
isKeyguardLocked()5441     public boolean isKeyguardLocked() {
5442         return mPolicy.isKeyguardLocked();
5443     }
5444 
5445     @Override
isKeyguardSecure()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
dismissKeyguard()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
keyguardGoingAway(boolean disableWindowAnimations, boolean keyguardGoingToNotificationShade)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 
keyguardWaitingForActivityDrawn()5483     public void keyguardWaitingForActivityDrawn() {
5484         if (DEBUG_KEYGUARD) Slog.d(TAG, "keyguardWaitingForActivityDrawn");
5485         synchronized (mWindowMap) {
5486             mKeyguardWaitingForActivityDrawn = true;
5487         }
5488     }
5489 
notifyActivityDrawnForKeyguard()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 
showGlobalActions()5501     void showGlobalActions() {
5502         mPolicy.showGlobalActions();
5503     }
5504 
5505     @Override
closeSystemDialogs(String reason)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 
fixScale(float scale)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
setAnimationScale(int which, float scale)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
setAnimationScales(float[] scales)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 
setAnimatorDurationScale(float scale)5573     private void setAnimatorDurationScale(float scale) {
5574         mAnimatorDurationScaleSetting = scale;
5575         ValueAnimator.setDurationScale(scale);
5576     }
5577 
getWindowAnimationScaleLocked()5578     public float getWindowAnimationScaleLocked() {
5579         return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting;
5580     }
5581 
getTransitionAnimationScaleLocked()5582     public float getTransitionAnimationScaleLocked() {
5583         return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting;
5584     }
5585 
5586     @Override
getAnimationScale(int which)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
getAnimationScales()5597     public float[] getAnimationScales() {
5598         return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting,
5599                 mAnimatorDurationScaleSetting };
5600     }
5601 
5602     @Override
getCurrentAnimatorScale()5603     public float getCurrentAnimatorScale() {
5604         synchronized(mWindowMap) {
5605             return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
5606         }
5607     }
5608 
dispatchNewAnimatorScaleLocked(Session session)5609     void dispatchNewAnimatorScaleLocked(Session session) {
5610         mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget();
5611     }
5612 
5613     @Override
registerPointerEventListener(PointerEventListener listener)5614     public void registerPointerEventListener(PointerEventListener listener) {
5615         mPointerEventDispatcher.registerInputEventListener(listener);
5616     }
5617 
5618     @Override
unregisterPointerEventListener(PointerEventListener listener)5619     public void unregisterPointerEventListener(PointerEventListener listener) {
5620         mPointerEventDispatcher.unregisterInputEventListener(listener);
5621     }
5622 
5623     // Called by window manager policy. Not exposed externally.
5624     @Override
getLidState()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
getCameraLensCoverState()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
switchKeyboardLayout(int deviceId, int direction)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
shutdown(boolean confirm)5665     public void shutdown(boolean confirm) {
5666         ShutdownThread.shutdown(mContext, confirm);
5667     }
5668 
5669     // Called by window manager policy.  Not exposed externally.
5670     @Override
rebootSafeMode(boolean confirm)5671     public void rebootSafeMode(boolean confirm) {
5672         ShutdownThread.rebootSafeMode(mContext, confirm);
5673     }
5674 
setCurrentProfileIds(final int[] currentProfileIds)5675     public void setCurrentProfileIds(final int[] currentProfileIds) {
5676         synchronized (mWindowMap) {
5677             mCurrentProfileIds = currentProfileIds;
5678         }
5679     }
5680 
setCurrentUser(final int newUserId, final int[] currentProfileIds)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 */
isCurrentProfileLocked(int userId)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 
enableScreenAfterBoot()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
enableScreenIfNeeded()5734     public void enableScreenIfNeeded() {
5735         synchronized (mWindowMap) {
5736             enableScreenIfNeededLocked();
5737         }
5738     }
5739 
enableScreenIfNeededLocked()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 
performBootTimeout()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 
checkWaitingForWindowsLocked()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 
performEnableScreen()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 
checkBootAnimationCompleteLocked()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 
showBootMessage(final CharSequence msg, final boolean always)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 
hideBootMessagesLocked()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
setInTouchMode(boolean mode)5945     public void setInTouchMode(boolean mode) {
5946         synchronized(mWindowMap) {
5947             mInTouchMode = mode;
5948         }
5949     }
5950 
updateCircularDisplayMaskIfNeeded()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 
showEmulatorDisplayOverlayIfNeeded()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 
showCircularMask(boolean visible)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 
showEmulatorDisplayOverlay()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
showStrictModeViolation(boolean on)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 
showStrictModeViolation(int arg, int pid)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
setStrictModeVisualIndicatorPreference(String value)6093     public void setStrictModeVisualIndicatorPreference(String value) {
6094         SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
6095     }
6096 
convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh)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
requestAssistScreenshot(final IAssistScreenshotReceiver receiver)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
screenshotApplications(IBinder appToken, int displayId, int width, int height)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 
screenshotApplicationsInner(IBinder appToken, int displayId, int width, int height, boolean includeFullDisplay)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
freezeRotation(int rotation)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
thawRotation()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
updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout)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      */
pauseRotationLocked()6502     void pauseRotationLocked() {
6503         mDeferredRotationPauseCount += 1;
6504     }
6505 
6506     /**
6507      * Resumes normal rotation changes after being paused.
6508      */
resumeRotationLocked()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 
updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout)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      */
updateRotationUncheckedLocked(boolean inTransaction)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
getRotation()6690     public int getRotation() {
6691         return mRotation;
6692     }
6693 
6694     @Override
isRotationFrozen()6695     public boolean isRotationFrozen() {
6696         return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6697     }
6698 
6699     @Override
watchRotation(IRotationWatcher watcher)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
removeRotationWatcher(IRotationWatcher watcher)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
getPreferredOptionsPanelGravity()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
startViewServer(int port)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 
isSystemSecure()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
stopViewServer()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
isViewServerRunning()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      */
viewServerListWindows(Socket client)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      */
viewServerGetFocusedWindow(Socket client)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      */
viewServerWindowCommand(Socket client, String command, String parameters)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 
addWindowChangeListener(WindowChangeListener listener)7098     public void addWindowChangeListener(WindowChangeListener listener) {
7099         synchronized(mWindowMap) {
7100             mWindowChangeListeners.add(listener);
7101         }
7102     }
7103 
removeWindowChangeListener(WindowChangeListener listener)7104     public void removeWindowChangeListener(WindowChangeListener listener) {
7105         synchronized(mWindowMap) {
7106             mWindowChangeListeners.remove(listener);
7107         }
7108     }
7109 
notifyWindowsChanged()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 
notifyFocusChanged()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 
findWindow(int hashCode)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      */
sendNewConfiguration()7167     void sendNewConfiguration() {
7168         try {
7169             mActivityManager.updateConfiguration(null);
7170         } catch (RemoteException e) {
7171         }
7172     }
7173 
computeNewConfiguration()7174     public Configuration computeNewConfiguration() {
7175         synchronized (mWindowMap) {
7176             return computeNewConfigurationLocked();
7177         }
7178     }
7179 
computeNewConfigurationLocked()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 
adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh)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 
reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh)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 
computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, int dw, int dh, float density, Configuration outConfig)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 
reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, int dw, int dh)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 
computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh)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 */
updateDisplayAndOrientationLocked()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 */
computeScreenConfigurationLocked(Configuration config)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 
isHardKeyboardAvailable()7452     public boolean isHardKeyboardAvailable() {
7453         synchronized (mWindowMap) {
7454             return mHardKeyboardAvailable;
7455         }
7456     }
7457 
updateShowImeWithHardKeyboard()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 
setOnHardKeyboardStatusChangeListener( OnHardKeyboardStatusChangeListener listener)7470     public void setOnHardKeyboardStatusChangeListener(
7471             OnHardKeyboardStatusChangeListener listener) {
7472         synchronized (mWindowMap) {
7473             mHardKeyboardStatusChangeListener = listener;
7474         }
7475     }
7476 
notifyHardKeyboardStatusChange()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 
prepareDragSurface(IWindow window, SurfaceSession session, int flags, int width, int height, Surface outSurface)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
pauseKeyDispatching(IBinder _token)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
resumeKeyDispatching(IBinder _token)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
setEventDispatching(boolean enabled)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 
getFocusedWindow()7597     private WindowState getFocusedWindow() {
7598         synchronized (mWindowMap) {
7599             return getFocusedWindowLocked();
7600         }
7601     }
7602 
getFocusedWindowLocked()7603     private WindowState getFocusedWindowLocked() {
7604         return mCurrentFocus;
7605     }
7606 
detectSafeMode()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 
displayReady()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 
displayReady(int displayId)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 
systemReady()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
handleMessage(Message msg)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
openSession(IWindowSessionCallback callback, IInputMethodClient client, IInputContext inputContext)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
inputMethodClientHasFocus(IInputMethodClient client)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
getInitialDisplaySize(int displayId, Point size)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
getBaseDisplaySize(int displayId, Point size)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
setForcedDisplaySize(int displayId, int width, int height)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
setForcedDisplayScalingMode(int displayId, int mode)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 
setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode)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 
readForcedDisplayPropertiesLocked(final DisplayContent displayContent)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
setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height)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
clearForcedDisplaySize(int displayId)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
getInitialDisplayDensity(int displayId)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
getBaseDisplayDensity(int displayId)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
setForcedDisplayDensity(int displayId, int density)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
setForcedDisplayDensityLocked(DisplayContent displayContent, int density)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
clearForcedDisplayDensity(int displayId)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
reconfigureDisplayLocked(DisplayContent displayContent)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 
configureDisplayPolicyLocked(DisplayContent displayContent)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
setOverscan(int displayId, int left, int top, int right, int bottom)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 
setOverscanLocked(DisplayContent displayContent, int left, int top, int right, int bottom)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 
windowForClientLocked(Session session, IWindow client, boolean throwOnError)8722     final WindowState windowForClientLocked(Session session, IWindow client,
8723             boolean throwOnError) {
8724         return windowForClientLocked(session, client.asBinder(), throwOnError);
8725     }
8726 
windowForClientLocked(Session session, IBinder client, boolean throwOnError)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 
rebuildAppWindowListLocked()8755     final void rebuildAppWindowListLocked() {
8756         rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
8757     }
8758 
rebuildAppWindowListLocked(final DisplayContent displayContent)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 
assignLayersLocked(WindowList windows)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 
performLayoutAndPlaceSurfacesLocked()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;
performLayoutAndPlaceSurfacesLockedLoop()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 
performLayoutLockedInner(final DisplayContent displayContent, boolean initial, boolean updateInputWindows)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 
makeWindowFreezingScreenIfNeededLocked(WindowState w)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      */
handleAppTransitionReadyLocked(WindowList windows)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      */
handleAnimatingStoppedAndTransitionLocked()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 
updateResizingWindows(final WindowState w)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      */
handleNotObscuredLocked(final WindowState w, final int innerDw, final int innerDh)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 
handleFlagDimBehind(WindowState w)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 
updateAllDrawnLocked(DisplayContent displayContent)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."
performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory)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 
toBrightnessOverride(float value)10407     private int toBrightnessOverride(float value) {
10408         return (int)(value * PowerManager.BRIGHTNESS_ON);
10409     }
10410 
checkDrawnWindowsLocked()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 
setHoldScreenLocked(final Session newHoldScreen)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 
requestTraversal()10458     void requestTraversal() {
10459         synchronized (mWindowMap) {
10460             requestTraversalLocked();
10461         }
10462     }
10463 
requestTraversalLocked()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 */
scheduleAnimationLocked()10472     void scheduleAnimationLocked() {
10473         if (!mAnimationScheduled) {
10474             mAnimationScheduled = true;
10475             mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback);
10476         }
10477     }
10478 
needsLayout()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 
copyAnimToLayoutParamsLocked()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. */
adjustAnimationBackground(WindowStateAnimator winAnimator)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 
reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, boolean secure)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 
updateFocusedWindowLocked(int mode, boolean updateInputWindows)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 
computeFocusedWindowLocked()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 
findFocusedWindowLocked(DisplayContent displayContent)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 
startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim)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 
stopFreezingDisplayLocked()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 
getPropertyInt(String[] tokens, int index, int defUnits, int defDps, DisplayMetrics dm)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 
createWatermarkInTransaction()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
statusBarVisibilityChanged(int visibility)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?
updateStatusBarVisibilityLocked(int visibility)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
reevaluateStatusBarVisibility()11045     public void reevaluateStatusBarVisibility() {
11046         synchronized (mWindowMap) {
11047             int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
11048             updateStatusBarVisibilityLocked(visibility);
11049             performLayoutAndPlaceSurfacesLocked();
11050         }
11051     }
11052 
11053     @Override
addInputConsumer(Looper looper, InputEventReceiver.Factory inputEventReceiverFactory)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 
removeInputConsumer()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.
saveLastInputMethodWindowForTransition()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 
getInputMethodWindowVisibleHeight()11085     public int getInputMethodWindowVisibleHeight() {
11086         synchronized (mWindowMap) {
11087             return mPolicy.getInputMethodWindowVisibleHeightLw();
11088         }
11089     }
11090 
11091     @Override
hasNavigationBar()11092     public boolean hasNavigationBar() {
11093         return mPolicy.hasNavigationBar();
11094     }
11095 
11096     @Override
lockNow(Bundle options)11097     public void lockNow(Bundle options) {
11098         mPolicy.lockNow(options);
11099     }
11100 
showRecentApps()11101     public void showRecentApps() {
11102         mPolicy.showRecentApps();
11103     }
11104 
11105     @Override
isSafeModeEnabled()11106     public boolean isSafeModeEnabled() {
11107         return mSafeMode;
11108     }
11109 
11110     @Override
clearWindowContentFrameStats(IBinder token)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
getWindowContentFrameStats(IBinder token)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 
dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll)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 
dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll)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 
dumpTokensLocked(PrintWriter pw, boolean dumpAll)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 
dumpSessionsLocked(PrintWriter pw, boolean dumpAll)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 
dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll)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 
dumpWindowsLocked(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows)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 
dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows)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 
dumpWindows(PrintWriter pw, String name, String[] args, int opti, boolean dumpAll)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 
dumpLastANRLocked(PrintWriter pw)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      */
saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, String reason)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
dump(FileDescriptor fd, PrintWriter pw, String[] args)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
monitor()11699     public void monitor() {
11700         synchronized (mWindowMap) { }
11701     }
11702 
11703     public interface OnHardKeyboardStatusChangeListener {
11704         public void onHardKeyboardStatusChange(boolean available);
11705     }
11706 
debugLayoutRepeats(final String msg, int pendingLayoutChanges)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 
newDisplayContentLocked(final Display display)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 
createDisplayContentLocked(final Display display)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      */
getDisplayContentLocked(final int displayId)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.
getDefaultDisplayContentLocked()11767     public DisplayContent getDefaultDisplayContentLocked() {
11768         return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
11769     }
11770 
getDefaultWindowListLocked()11771     public WindowList getDefaultWindowListLocked() {
11772         return getDefaultDisplayContentLocked().getWindowList();
11773     }
11774 
getDefaultDisplayInfoLocked()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      */
getWindowListLocked(final Display display)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      */
getWindowListLocked(final int displayId)11793     public WindowList getWindowListLocked(final int displayId) {
11794         final DisplayContent displayContent = getDisplayContentLocked(displayId);
11795         return displayContent != null ? displayContent.getWindowList() : null;
11796     }
11797 
onDisplayAdded(int displayId)11798     public void onDisplayAdded(int displayId) {
11799         mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
11800     }
11801 
handleDisplayAdded(int displayId)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 
onDisplayRemoved(int displayId)11813     public void onDisplayRemoved(int displayId) {
11814         mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
11815     }
11816 
handleDisplayRemovedLocked(int displayId)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 
onDisplayChanged(int displayId)11835     public void onDisplayChanged(int displayId) {
11836         mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
11837     }
11838 
handleDisplayChangedLocked(int displayId)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
getWindowManagerLock()11848     public Object getWindowManagerLock() {
11849         return mWindowMap;
11850     }
11851 
11852     private final class LocalService extends WindowManagerInternal {
11853         @Override
requestTraversalFromDisplayManager()11854         public void requestTraversalFromDisplayManager() {
11855             requestTraversal();
11856         }
11857 
11858         @Override
setMagnificationSpec(MagnificationSpec spec)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
getCompatibleMagnificationSpecForWindow(IBinder windowToken)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
setMagnificationCallbacks(MagnificationCallbacks callbacks)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
setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback)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
setInputFilter(IInputFilter filter)11921         public void setInputFilter(IInputFilter filter) {
11922             mInputManager.setInputFilter(filter);
11923         }
11924 
11925         @Override
getFocusedWindowToken()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
isKeyguardLocked()11937         public boolean isKeyguardLocked() {
11938             return WindowManagerService.this.isKeyguardLocked();
11939         }
11940 
11941         @Override
showGlobalActions()11942         public void showGlobalActions() {
11943             WindowManagerService.this.showGlobalActions();
11944         }
11945 
11946         @Override
getWindowFrame(IBinder token, Rect outBounds)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
waitForAllWindowsDrawn(Runnable callback, long timeout)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
addWindowToken(IBinder token, int type)11985         public void addWindowToken(IBinder token, int type) {
11986             WindowManagerService.this.addWindowToken(token, type);
11987         }
11988 
11989         @Override
removeWindowToken(IBinder token, boolean removeWindows)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
registerAppTransitionListener(AppTransitionListener listener)12003         public void registerAppTransitionListener(AppTransitionListener listener) {
12004             synchronized (mWindowMap) {
12005                 mAppTransition.registerListenerLocked(listener);
12006             }
12007         }
12008     }
12009 }
12010