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