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