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