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