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