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