2 * Copyright (C) 2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server;
19 import static android.os.LocalPowerManager.CHEEK_EVENT;
20 import static android.os.LocalPowerManager.OTHER_EVENT;
21 import static android.os.LocalPowerManager.TOUCH_EVENT;
22 import static android.os.LocalPowerManager.LONG_TOUCH_EVENT;
23 import static android.os.LocalPowerManager.TOUCH_UP_EVENT;
24 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
25 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
26 import static android.view.WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
27 import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
28 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
29 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
30 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
31 import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
32 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
33 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
34 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
35 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
36 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
37 import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_PUSH_BUFFERS;
38 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
39 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
40 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
41 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
42 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
44 import com.android.internal.app.IBatteryStats;
45 import com.android.internal.policy.PolicyManager;
46 import com.android.internal.policy.impl.PhoneWindowManager;
47 import com.android.internal.view.IInputContext;
48 import com.android.internal.view.IInputMethodClient;
49 import com.android.internal.view.IInputMethodManager;
50 import com.android.internal.view.WindowManagerPolicyThread;
51 import com.android.server.KeyInputQueue.QueuedEvent;
52 import com.android.server.am.BatteryStatsService;
54 import android.Manifest;
55 import android.app.ActivityManagerNative;
56 import android.app.IActivityManager;
57 import android.app.admin.DevicePolicyManager;
58 import android.content.BroadcastReceiver;
59 import android.content.Context;
60 import android.content.Intent;
61 import android.content.IntentFilter;
62 import android.content.pm.ActivityInfo;
63 import android.content.pm.PackageManager;
64 import android.content.res.CompatibilityInfo;
65 import android.content.res.Configuration;
66 import android.graphics.Matrix;
67 import android.graphics.PixelFormat;
68 import android.graphics.Rect;
69 import android.graphics.Region;
70 import android.os.BatteryStats;
71 import android.os.Binder;
72 import android.os.Bundle;
73 import android.os.Debug;
74 import android.os.Handler;
75 import android.os.IBinder;
76 import android.os.LatencyTimer;
77 import android.os.LocalPowerManager;
78 import android.os.Looper;
79 import android.os.Message;
80 import android.os.Parcel;
81 import android.os.ParcelFileDescriptor;
82 import android.os.Power;
83 import android.os.PowerManager;
84 import android.os.Process;
85 import android.os.RemoteException;
86 import android.os.ServiceManager;
87 import android.os.SystemClock;
88 import android.os.SystemProperties;
89 import android.os.TokenWatcher;
90 import android.provider.Settings;
91 import android.util.DisplayMetrics;
92 import android.util.EventLog;
93 import android.util.Log;
94 import android.util.Slog;
95 import android.util.SparseIntArray;
96 import android.view.Display;
97 import android.view.Gravity;
98 import android.view.IApplicationToken;
99 import android.view.IOnKeyguardExitResult;
100 import android.view.IRotationWatcher;
101 import android.view.IWindow;
102 import android.view.IWindowManager;
103 import android.view.IWindowSession;
104 import android.view.KeyEvent;
105 import android.view.MotionEvent;
106 import android.view.RawInputEvent;
107 import android.view.Surface;
108 import android.view.SurfaceSession;
109 import android.view.View;
110 import android.view.ViewConfiguration;
111 import android.view.ViewTreeObserver;
112 import android.view.WindowManager;
113 import android.view.WindowManagerImpl;
114 import android.view.WindowManagerPolicy;
115 import android.view.WindowManager.LayoutParams;
116 import android.view.animation.AccelerateInterpolator;
117 import android.view.animation.Animation;
118 import android.view.animation.AnimationUtils;
119 import android.view.animation.Transformation;
121 import java.io.BufferedWriter;
123 import java.io.FileDescriptor;
124 import java.io.IOException;
125 import java.io.OutputStream;
126 import java.io.OutputStreamWriter;
127 import java.io.PrintWriter;
128 import java.io.StringWriter;
129 import java.net.Socket;
130 import java.util.ArrayList;
131 import java.util.HashMap;
132 import java.util.HashSet;
133 import java.util.Iterator;
134 import java.util.List;
137 public class WindowManagerService extends IWindowManager.Stub
138 implements Watchdog.Monitor, KeyInputQueue.HapticFeedbackCallback {
139 static final String TAG = "WindowManager";
140 static final boolean DEBUG = false;
141 static final boolean DEBUG_FOCUS = false;
142 static final boolean DEBUG_ANIM = false;
143 static final boolean DEBUG_LAYOUT = false;
144 static final boolean DEBUG_RESIZE = false;
145 static final boolean DEBUG_LAYERS = false;
146 static final boolean DEBUG_INPUT = false;
147 static final boolean DEBUG_INPUT_METHOD = false;
148 static final boolean DEBUG_VISIBILITY = false;
149 static final boolean DEBUG_WINDOW_MOVEMENT = false;
150 static final boolean DEBUG_ORIENTATION = false;
151 static final boolean DEBUG_CONFIGURATION = false;
152 static final boolean DEBUG_APP_TRANSITIONS = false;
153 static final boolean DEBUG_STARTING_WINDOW = false;
154 static final boolean DEBUG_REORDER = false;
155 static final boolean DEBUG_WALLPAPER = false;
156 static final boolean DEBUG_FREEZE = false;
157 static final boolean SHOW_TRANSACTIONS = false;
158 static final boolean HIDE_STACK_CRAWLS = true;
159 static final boolean MEASURE_LATENCY = false;
160 static private LatencyTimer lt;
162 static final boolean PROFILE_ORIENTATION = false;
163 static final boolean BLUR = true;
164 static final boolean localLOGV = DEBUG;
166 /** How long to wait for subsequent key repeats, in milliseconds */
167 static final int KEY_REPEAT_DELAY = 50;
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;
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;
178 /** How much to increment the layer for each window, to reserve room
179 * for effect surfaces between them.
181 static final int WINDOW_LAYER_MULTIPLIER = 5;
183 /** The maximum length we will accept for a loaded animation duration:
184 * this is 10 seconds.
186 static final int MAX_ANIMATION_DURATION = 10*1000;
188 /** Amount of time (in milliseconds) to animate the dim surface from one
189 * value to another, when no window animation is driving it.
191 static final int DEFAULT_DIM_DURATION = 200;
193 /** Amount of time (in milliseconds) to animate the fade-in-out transition for
194 * compatible windows.
196 static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
198 /** Adjustment to time to perform a dim, to make it more dramatic.
200 static final int DIM_DURATION_MULTIPLIER = 6;
202 static final int INJECT_FAILED = 0;
203 static final int INJECT_SUCCEEDED = 1;
204 static final int INJECT_NO_PERMISSION = -1;
206 static final int UPDATE_FOCUS_NORMAL = 0;
207 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
208 static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
209 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
211 /** The minimum time between dispatching touch events. */
212 int mMinWaitTimeBetweenTouchEvents = 1000 / 35;
214 // Last touch event time
215 long mLastTouchEventTime = 0;
217 // Last touch event type
218 int mLastTouchEventType = OTHER_EVENT;
220 // Time to wait before calling useractivity again. This saves CPU usage
221 // when we get a flood of touch events.
222 static final int MIN_TIME_BETWEEN_USERACTIVITIES = 1000;
224 // Last time we call user activity
225 long mLastUserActivityCallTime = 0;
227 // Last time we updated battery stats
228 long mLastBatteryStatsCallTime = 0;
230 private static final String SYSTEM_SECURE = "ro.secure";
231 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
234 * Condition waited on by {@link #reenableKeyguard} to know the call to
235 * the window policy has finished.
236 * This is set to true only if mKeyguardTokenWatcher.acquired() has
237 * actually disabled the keyguard.
239 private boolean mKeyguardDisabled = false;
241 private static final int ALLOW_DISABLE_YES = 1;
242 private static final int ALLOW_DISABLE_NO = 0;
243 private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager
244 private int mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; // sync'd by mKeyguardTokenWatcher
246 final TokenWatcher mKeyguardTokenWatcher = new TokenWatcher(
247 new Handler(), "WindowManagerService.mKeyguardTokenWatcher") {
248 public void acquired() {
249 if (shouldAllowDisableKeyguard()) {
250 mPolicy.enableKeyguard(false);
251 mKeyguardDisabled = true;
253 Log.v(TAG, "Not disabling keyguard since device policy is enforced");
256 public void released() {
257 mPolicy.enableKeyguard(true);
258 synchronized (mKeyguardTokenWatcher) {
259 mKeyguardDisabled = false;
260 mKeyguardTokenWatcher.notifyAll();
265 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
267 public void onReceive(Context context, Intent intent) {
268 mPolicy.enableKeyguard(true);
269 synchronized(mKeyguardTokenWatcher) {
270 // lazily evaluate this next time we're asked to disable keyguard
271 mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
272 mKeyguardDisabled = false;
277 final Context mContext;
279 final boolean mHaveInputMethods;
281 final boolean mLimitedAlphaCompositing;
283 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
285 final IActivityManager mActivityManager;
287 final IBatteryStats mBatteryStats;
290 * All currently active sessions with clients.
292 final HashSet<Session> mSessions = new HashSet<Session>();
295 * Mapping from an IWindow IBinder to the server's Window object.
296 * This is also used as the lock for all of our state.
298 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
301 * Mapping from a token IBinder to a WindowToken object.
303 final HashMap<IBinder, WindowToken> mTokenMap =
304 new HashMap<IBinder, WindowToken>();
307 * The same tokens as mTokenMap, stored in a list for efficient iteration
310 final ArrayList<WindowToken> mTokenList = new ArrayList<WindowToken>();
313 * Window tokens that are in the process of exiting, but still
314 * on screen for animations.
316 final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
319 * Z-ordered (bottom-most first) list of all application tokens, for
320 * controlling the ordering of windows in different applications. This
321 * contains WindowToken objects.
323 final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
326 * Application tokens that are in the process of exiting, but still
327 * on screen for animations.
329 final ArrayList<AppWindowToken> mExitingAppTokens = new ArrayList<AppWindowToken>();
332 * List of window tokens that have finished starting their application,
333 * and now need to have the policy remove their windows.
335 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
338 * This was the app token that was used to retrieve the last enter
339 * animation. It will be used for the next exit animation.
341 AppWindowToken mLastEnterAnimToken;
344 * These were the layout params used to retrieve the last enter animation.
345 * They will be used for the next exit animation.
347 LayoutParams mLastEnterAnimParams;
350 * Z-ordered (bottom-most first) list of all Window objects.
352 final ArrayList mWindows = new ArrayList();
355 * Windows that are being resized. Used so we can tell the client about
356 * the resize after closing the transaction in which we resized the
357 * underlying surface.
359 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
362 * Windows whose animations have ended and now must be removed.
364 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
367 * Windows whose surface should be destroyed.
369 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
372 * Windows that have lost input focus and are waiting for the new
373 * focus window to be displayed before they are told about this.
375 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
378 * This is set when we have run out of memory, and will either be an empty
379 * list or contain windows that need to be force removed.
381 ArrayList<WindowState> mForceRemoves;
383 IInputMethodManager mInputMethodManager;
385 SurfaceSession mFxSession;
386 private DimAnimator mDimAnimator = null;
387 Surface mBlurSurface;
390 int mTransactionSequence = 0;
392 final float[] mTmpFloats = new float[9];
395 boolean mDisplayEnabled = false;
396 boolean mSystemBooted = false;
397 int mInitialDisplayWidth = 0;
398 int mInitialDisplayHeight = 0;
400 int mRequestedRotation = 0;
401 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
402 int mLastRotationFlags;
403 ArrayList<IRotationWatcher> mRotationWatchers
404 = new ArrayList<IRotationWatcher>();
406 boolean mLayoutNeeded = true;
407 boolean mAnimationPending = false;
408 boolean mDisplayFrozen = false;
409 boolean mWaitingForConfig = false;
410 boolean mWindowsFreezingScreen = false;
411 long mFreezeGcPending = 0;
412 int mAppsFreezingScreen = 0;
416 // State while inside of layoutAndPlaceSurfacesLocked().
417 boolean mFocusMayChange;
419 Configuration mCurConfiguration = new Configuration();
421 // This is held as long as we have the screen frozen, to give us time to
422 // perform a rotation animation when turning off shows the lock screen which
423 // changes the orientation.
424 PowerManager.WakeLock mScreenFrozenLock;
426 // State management of app transitions. When we are preparing for a
427 // transition, mNextAppTransition will be the kind of transition to
428 // perform or TRANSIT_NONE if we are not waiting. If we are waiting,
429 // mOpeningApps and mClosingApps are the lists of tokens that will be
430 // made visible or hidden at the next transition.
431 int mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
432 String mNextAppTransitionPackage;
433 int mNextAppTransitionEnter;
434 int mNextAppTransitionExit;
435 boolean mAppTransitionReady = false;
436 boolean mAppTransitionRunning = false;
437 boolean mAppTransitionTimeout = false;
438 boolean mStartingIconInTransition = false;
439 boolean mSkipAppTransitionAnimation = false;
440 final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
441 final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
442 final ArrayList<AppWindowToken> mToTopApps = new ArrayList<AppWindowToken>();
443 final ArrayList<AppWindowToken> mToBottomApps = new ArrayList<AppWindowToken>();
445 //flag to detect fat touch events
446 boolean mFatTouch = false;
451 WindowState mCurrentFocus = null;
452 WindowState mLastFocus = null;
454 // This just indicates the window the input method is on top of, not
455 // necessarily the window its input is going to.
456 WindowState mInputMethodTarget = null;
457 WindowState mUpcomingInputMethodTarget = null;
458 boolean mInputMethodTargetWaitingAnim;
459 int mInputMethodAnimLayerAdjustment;
461 WindowState mInputMethodWindow = null;
462 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
464 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
466 // If non-null, this is the currently visible window that is associated
467 // with the wallpaper.
468 WindowState mWallpaperTarget = null;
469 // If non-null, we are in the middle of animating from one wallpaper target
470 // to another, and this is the lower one in Z-order.
471 WindowState mLowerWallpaperTarget = null;
472 // If non-null, we are in the middle of animating from one wallpaper target
473 // to another, and this is the higher one in Z-order.
474 WindowState mUpperWallpaperTarget = null;
475 int mWallpaperAnimLayerAdjustment;
476 float mLastWallpaperX = -1;
477 float mLastWallpaperY = -1;
478 float mLastWallpaperXStep = -1;
479 float mLastWallpaperYStep = -1;
480 boolean mSendingPointersToWallpaper = false;
481 // This is set when we are waiting for a wallpaper to tell us it is done
482 // changing its scroll position.
483 WindowState mWaitingOnWallpaper;
484 // The last time we had a timeout when waiting for a wallpaper.
485 long mLastWallpaperTimeoutTime;
486 // We give a wallpaper up to 150ms to finish scrolling.
487 static final long WALLPAPER_TIMEOUT = 150;
488 // Time we wait after a timeout before trying to wait again.
489 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
491 AppWindowToken mFocusedApp = null;
493 PowerManagerService mPowerManager;
495 float mWindowAnimationScale = 1.0f;
496 float mTransitionAnimationScale = 1.0f;
498 final KeyWaiter mKeyWaiter = new KeyWaiter();
500 final InputDispatcherThread mInputThread;
502 // Who is holding the screen on.
503 Session mHoldingScreenOn;
505 boolean mTurnOnScreen;
508 * Whether the UI is currently running in touch mode (not showing
509 * navigational focus because the user is directly pressing the screen).
511 boolean mInTouchMode = false;
513 private ViewServer mViewServer;
515 final Rect mTempRect = new Rect();
517 final Configuration mTempConfiguration = new Configuration();
518 int mScreenLayout = Configuration.SCREENLAYOUT_SIZE_UNDEFINED;
520 // The frame use to limit the size of the app running in compatibility mode.
521 Rect mCompatibleScreenFrame = new Rect();
522 // The surface used to fill the outer rim of the app running in compatibility mode.
523 Surface mBackgroundFillerSurface = null;
524 boolean mBackgroundFillerShown = false;
526 public static WindowManagerService main(Context context,
527 PowerManagerService pm, boolean haveInputMethods) {
528 WMThread thr = new WMThread(context, pm, haveInputMethods);
532 while (thr.mService == null) {
535 } catch (InterruptedException e) {
543 static class WMThread extends Thread {
544 WindowManagerService mService;
546 private final Context mContext;
547 private final PowerManagerService mPM;
548 private final boolean mHaveInputMethods;
550 public WMThread(Context context, PowerManagerService pm,
551 boolean haveInputMethods) {
552 super("WindowManager");
555 mHaveInputMethods = haveInputMethods;
560 WindowManagerService s = new WindowManagerService(mContext, mPM,
562 android.os.Process.setThreadPriority(
563 android.os.Process.THREAD_PRIORITY_DISPLAY);
565 synchronized (this) {
574 static class PolicyThread extends Thread {
575 private final WindowManagerPolicy mPolicy;
576 private final WindowManagerService mService;
577 private final Context mContext;
578 private final PowerManagerService mPM;
579 boolean mRunning = false;
581 public PolicyThread(WindowManagerPolicy policy,
582 WindowManagerService service, Context context,
583 PowerManagerService pm) {
584 super("WindowManagerPolicy");
593 WindowManagerPolicyThread.set(this, Looper.myLooper());
595 //Looper.myLooper().setMessageLogging(new LogPrinter(
596 // Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
597 android.os.Process.setThreadPriority(
598 android.os.Process.THREAD_PRIORITY_FOREGROUND);
599 mPolicy.init(mContext, mService, mPM);
601 synchronized (this) {
610 private WindowManagerService(Context context, PowerManagerService pm,
611 boolean haveInputMethods) {
612 if (MEASURE_LATENCY) {
613 lt = new LatencyTimer(100, 1000);
617 mHaveInputMethods = haveInputMethods;
618 mLimitedAlphaCompositing = context.getResources().getBoolean(
619 com.android.internal.R.bool.config_sf_limitedAlpha);
622 mPowerManager.setPolicy(mPolicy);
623 PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
624 mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
626 mScreenFrozenLock.setReferenceCounted(false);
628 mActivityManager = ActivityManagerNative.getDefault();
629 mBatteryStats = BatteryStatsService.getService();
631 // Get persisted window scale setting
632 mWindowAnimationScale = Settings.System.getFloat(context.getContentResolver(),
633 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
634 mTransitionAnimationScale = Settings.System.getFloat(context.getContentResolver(),
635 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
637 // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
638 IntentFilter filter = new IntentFilter();
639 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
640 mContext.registerReceiver(mBroadcastReceiver, filter);
642 int max_events_per_sec = 35;
644 max_events_per_sec = Integer.parseInt(SystemProperties
645 .get("windowsmgr.max_events_per_sec"));
646 if (max_events_per_sec < 1) {
647 max_events_per_sec = 35;
649 } catch (NumberFormatException e) {
651 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
655 mInputThread = new InputDispatcherThread();
657 PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
661 while (!thr.mRunning) {
664 } catch (InterruptedException e) {
669 mInputThread.start();
672 // Add ourself to the Watchdog monitors.
673 Watchdog.getInstance().addMonitor(this);
677 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
678 throws RemoteException {
680 return super.onTransact(code, data, reply, flags);
681 } catch (RuntimeException e) {
682 // The window manager only throws security exceptions, so let's
684 if (!(e instanceof SecurityException)) {
685 Slog.e(TAG, "Window Manager Crash", e);
691 private void placeWindowAfter(Object pos, WindowState window) {
692 final int i = mWindows.indexOf(pos);
693 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
694 TAG, "Adding window " + window + " at "
695 + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
696 mWindows.add(i+1, window);
699 private void placeWindowBefore(Object pos, WindowState window) {
700 final int i = mWindows.indexOf(pos);
701 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
702 TAG, "Adding window " + window + " at "
703 + i + " of " + mWindows.size() + " (before " + pos + ")");
704 mWindows.add(i, window);
707 //This method finds out the index of a window that has the same app token as
708 //win. used for z ordering the windows in mWindows
709 private int findIdxBasedOnAppTokens(WindowState win) {
710 //use a local variable to cache mWindows
711 ArrayList localmWindows = mWindows;
712 int jmax = localmWindows.size();
716 for(int j = (jmax-1); j >= 0; j--) {
717 WindowState wentry = (WindowState)localmWindows.get(j);
718 if(wentry.mAppToken == win.mAppToken) {
725 private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
726 final IWindow client = win.mClient;
727 final WindowToken token = win.mToken;
728 final ArrayList localmWindows = mWindows;
730 final int N = localmWindows.size();
731 final WindowState attached = win.mAttachedWindow;
733 if (attached == null) {
734 int tokenWindowsPos = token.windows.size();
735 if (token.appWindowToken != null) {
736 int index = tokenWindowsPos-1;
738 // If this application has existing windows, we
739 // simply place the new window on top of them... but
740 // keep the starting window on top.
741 if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
742 // Base windows go behind everything else.
743 placeWindowBefore(token.windows.get(0), win);
746 AppWindowToken atoken = win.mAppToken;
747 if (atoken != null &&
748 token.windows.get(index) == atoken.startingWindow) {
749 placeWindowBefore(token.windows.get(index), win);
752 int newIdx = findIdxBasedOnAppTokens(win);
754 //there is a window above this one associated with the same
755 //apptoken note that the window could be a floating window
756 //that was created later or a window at the top of the list of
757 //windows associated with this token.
758 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
759 TAG, "Adding window " + win + " at "
760 + (newIdx+1) + " of " + N);
761 localmWindows.add(newIdx+1, win);
766 if (localLOGV) Slog.v(
767 TAG, "Figuring out where to add app window "
768 + client.asBinder() + " (token=" + token + ")");
769 // Figure out where the window should go, based on the
770 // order of applications.
771 final int NA = mAppTokens.size();
773 for (i=NA-1; i>=0; i--) {
774 AppWindowToken t = mAppTokens.get(i);
780 // We haven't reached the token yet; if this token
781 // is not going to the bottom and has windows, we can
782 // use it as an anchor for when we do reach the token.
783 if (!t.sendingToBottom && t.windows.size() > 0) {
784 pos = t.windows.get(0);
787 // We now know the index into the apps. If we found
788 // an app window above, that gives us the position; else
789 // we need to look some more.
791 // Move behind any windows attached to this one.
793 mTokenMap.get(((WindowState)pos).mClient.asBinder());
794 if (atoken != null) {
795 final int NC = atoken.windows.size();
797 WindowState bottom = atoken.windows.get(0);
798 if (bottom.mSubLayer < 0) {
803 placeWindowBefore(pos, win);
805 // Continue looking down until we find the first
806 // token that has windows.
808 AppWindowToken t = mAppTokens.get(i);
809 final int NW = t.windows.size();
811 pos = t.windows.get(NW-1);
817 // Move in front of any windows attached to this
820 mTokenMap.get(((WindowState)pos).mClient.asBinder());
821 if (atoken != null) {
822 final int NC = atoken.windows.size();
824 WindowState top = atoken.windows.get(NC-1);
825 if (top.mSubLayer >= 0) {
830 placeWindowAfter(pos, win);
832 // Just search for the start of this layer.
833 final int myLayer = win.mBaseLayer;
834 for (i=0; i<N; i++) {
835 WindowState w = (WindowState)localmWindows.get(i);
836 if (w.mBaseLayer > myLayer) {
840 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
841 TAG, "Adding window " + win + " at "
843 localmWindows.add(i, win);
848 // Figure out where window should go, based on layer.
849 final int myLayer = win.mBaseLayer;
850 for (i=N-1; i>=0; i--) {
851 if (((WindowState)localmWindows.get(i)).mBaseLayer <= myLayer) {
857 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
858 TAG, "Adding window " + win + " at "
860 localmWindows.add(i, win);
863 token.windows.add(tokenWindowsPos, win);
867 // Figure out this window's ordering relative to the window
868 // it is attached to.
869 final int NA = token.windows.size();
870 final int sublayer = win.mSubLayer;
871 int largestSublayer = Integer.MIN_VALUE;
872 WindowState windowWithLargestSublayer = null;
873 for (i=0; i<NA; i++) {
874 WindowState w = token.windows.get(i);
875 final int wSublayer = w.mSubLayer;
876 if (wSublayer >= largestSublayer) {
877 largestSublayer = wSublayer;
878 windowWithLargestSublayer = w;
881 // For negative sublayers, we go below all windows
882 // in the same sublayer.
883 if (wSublayer >= sublayer) {
885 token.windows.add(i, win);
888 wSublayer >= 0 ? attached : w, win);
892 // For positive sublayers, we go above all windows
893 // in the same sublayer.
894 if (wSublayer > sublayer) {
896 token.windows.add(i, win);
898 placeWindowBefore(w, win);
905 token.windows.add(win);
908 placeWindowBefore(attached, win);
910 placeWindowAfter(largestSublayer >= 0
911 ? windowWithLargestSublayer
918 if (win.mAppToken != null && addToToken) {
919 win.mAppToken.allAppWindows.add(win);
923 static boolean canBeImeTarget(WindowState w) {
924 final int fl = w.mAttrs.flags
925 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
926 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) {
927 return w.isVisibleOrAdding();
932 int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
933 final ArrayList localmWindows = mWindows;
934 final int N = localmWindows.size();
935 WindowState w = null;
939 w = (WindowState)localmWindows.get(i);
941 //Slog.i(TAG, "Checking window @" + i + " " + w + " fl=0x"
942 // + Integer.toHexString(w.mAttrs.flags));
943 if (canBeImeTarget(w)) {
944 //Slog.i(TAG, "Putting input method here!");
946 // Yet more tricksyness! If this window is a "starting"
947 // window, we do actually want to be on top of it, but
948 // it is not -really- where input will go. So if the caller
949 // is not actually looking to move the IME, look down below
950 // for a real window to target...
952 && w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
954 WindowState wb = (WindowState)localmWindows.get(i-1);
955 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
964 mUpcomingInputMethodTarget = w;
966 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
967 + w + " willMove=" + willMove);
969 if (willMove && w != null) {
970 final WindowState curTarget = mInputMethodTarget;
971 if (curTarget != null && curTarget.mAppToken != null) {
973 // Now some fun for dealing with window animations that
974 // modify the Z order. We need to look at all windows below
975 // the current target that are in this app, finding the highest
976 // visible one in layering.
977 AppWindowToken token = curTarget.mAppToken;
978 WindowState highestTarget = null;
980 if (token.animating || token.animation != null) {
982 pos = localmWindows.indexOf(curTarget);
984 WindowState win = (WindowState)localmWindows.get(pos);
985 if (win.mAppToken != token) {
989 if (highestTarget == null || win.mAnimLayer >
990 highestTarget.mAnimLayer) {
999 if (highestTarget != null) {
1000 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "mNextAppTransition="
1001 + mNextAppTransition + " " + highestTarget
1002 + " animating=" + highestTarget.isAnimating()
1003 + " layer=" + highestTarget.mAnimLayer
1004 + " new layer=" + w.mAnimLayer);
1006 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
1007 // If we are currently setting up for an animation,
1008 // hold everything until we can find out what will happen.
1009 mInputMethodTargetWaitingAnim = true;
1010 mInputMethodTarget = highestTarget;
1011 return highestPos + 1;
1012 } else if (highestTarget.isAnimating() &&
1013 highestTarget.mAnimLayer > w.mAnimLayer) {
1014 // If the window we are currently targeting is involved
1015 // with an animation, and it is on top of the next target
1016 // we will be over, then hold off on moving until
1018 mInputMethodTarget = highestTarget;
1019 return highestPos + 1;
1025 //Slog.i(TAG, "Placing input method @" + (i+1));
1028 if (DEBUG_INPUT_METHOD) {
1029 RuntimeException e = null;
1030 if (!HIDE_STACK_CRAWLS) {
1031 e = new RuntimeException();
1032 e.fillInStackTrace();
1034 Slog.w(TAG, "Moving IM target from "
1035 + mInputMethodTarget + " to " + w, e);
1037 mInputMethodTarget = w;
1038 if (w.mAppToken != null) {
1039 setInputMethodAnimLayerAdjustment(w.mAppToken.animLayerAdjustment);
1041 setInputMethodAnimLayerAdjustment(0);
1047 if (DEBUG_INPUT_METHOD) {
1048 RuntimeException e = null;
1049 if (!HIDE_STACK_CRAWLS) {
1050 e = new RuntimeException();
1051 e.fillInStackTrace();
1053 Slog.w(TAG, "Moving IM target from "
1054 + mInputMethodTarget + " to null", e);
1056 mInputMethodTarget = null;
1057 setInputMethodAnimLayerAdjustment(0);
1062 void addInputMethodWindowToListLocked(WindowState win) {
1063 int pos = findDesiredInputMethodWindowIndexLocked(true);
1065 win.mTargetAppToken = mInputMethodTarget.mAppToken;
1066 if (DEBUG_WINDOW_MOVEMENT) Slog.v(
1067 TAG, "Adding input method window " + win + " at " + pos);
1068 mWindows.add(pos, win);
1069 moveInputMethodDialogsLocked(pos+1);
1072 win.mTargetAppToken = null;
1073 addWindowToListInOrderLocked(win, true);
1074 moveInputMethodDialogsLocked(pos);
1077 void setInputMethodAnimLayerAdjustment(int adj) {
1078 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj);
1079 mInputMethodAnimLayerAdjustment = adj;
1080 WindowState imw = mInputMethodWindow;
1082 imw.mAnimLayer = imw.mLayer + adj;
1083 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
1084 + " anim layer: " + imw.mAnimLayer);
1085 int wi = imw.mChildWindows.size();
1088 WindowState cw = (WindowState)imw.mChildWindows.get(wi);
1089 cw.mAnimLayer = cw.mLayer + adj;
1090 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw
1091 + " anim layer: " + cw.mAnimLayer);
1094 int di = mInputMethodDialogs.size();
1097 imw = mInputMethodDialogs.get(di);
1098 imw.mAnimLayer = imw.mLayer + adj;
1099 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
1100 + " anim layer: " + imw.mAnimLayer);
1104 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1105 int wpos = mWindows.indexOf(win);
1107 if (wpos < interestingPos) interestingPos--;
1108 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
1109 mWindows.remove(wpos);
1110 int NC = win.mChildWindows.size();
1113 WindowState cw = (WindowState)win.mChildWindows.get(NC);
1114 int cpos = mWindows.indexOf(cw);
1116 if (cpos < interestingPos) interestingPos--;
1117 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
1118 + cpos + ": " + cw);
1119 mWindows.remove(cpos);
1123 return interestingPos;
1126 private void reAddWindowToListInOrderLocked(WindowState win) {
1127 addWindowToListInOrderLocked(win, false);
1128 // This is a hack to get all of the child windows added as well
1129 // at the right position. Child windows should be rare and
1130 // this case should be rare, so it shouldn't be that big a deal.
1131 int wpos = mWindows.indexOf(win);
1133 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos
1135 mWindows.remove(wpos);
1136 reAddWindowLocked(wpos, win);
1140 void logWindowList(String prefix) {
1141 int N = mWindows.size();
1144 Slog.v(TAG, prefix + "#" + N + ": " + mWindows.get(N));
1148 void moveInputMethodDialogsLocked(int pos) {
1149 ArrayList<WindowState> dialogs = mInputMethodDialogs;
1151 final int N = dialogs.size();
1152 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
1153 for (int i=0; i<N; i++) {
1154 pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1156 if (DEBUG_INPUT_METHOD) {
1157 Slog.v(TAG, "Window list w/pos=" + pos);
1162 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1163 if (pos < mWindows.size()) {
1164 WindowState wp = (WindowState)mWindows.get(pos);
1165 if (wp == mInputMethodWindow) {
1169 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
1170 for (int i=0; i<N; i++) {
1171 WindowState win = dialogs.get(i);
1172 win.mTargetAppToken = targetAppToken;
1173 pos = reAddWindowLocked(pos, win);
1175 if (DEBUG_INPUT_METHOD) {
1176 Slog.v(TAG, "Final window list:");
1181 for (int i=0; i<N; i++) {
1182 WindowState win = dialogs.get(i);
1183 win.mTargetAppToken = null;
1184 reAddWindowToListInOrderLocked(win);
1185 if (DEBUG_INPUT_METHOD) {
1186 Slog.v(TAG, "No IM target, final list:");
1192 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1193 final WindowState imWin = mInputMethodWindow;
1194 final int DN = mInputMethodDialogs.size();
1195 if (imWin == null && DN == 0) {
1199 int imPos = findDesiredInputMethodWindowIndexLocked(true);
1201 // In this case, the input method windows are to be placed
1202 // immediately above the window they are targeting.
1204 // First check to see if the input method windows are already
1205 // located here, and contiguous.
1206 final int N = mWindows.size();
1207 WindowState firstImWin = imPos < N
1208 ? (WindowState)mWindows.get(imPos) : null;
1210 // Figure out the actual input method window that should be
1211 // at the bottom of their stack.
1212 WindowState baseImWin = imWin != null
1213 ? imWin : mInputMethodDialogs.get(0);
1214 if (baseImWin.mChildWindows.size() > 0) {
1215 WindowState cw = (WindowState)baseImWin.mChildWindows.get(0);
1216 if (cw.mSubLayer < 0) baseImWin = cw;
1219 if (firstImWin == baseImWin) {
1220 // The windows haven't moved... but are they still contiguous?
1221 // First find the top IM window.
1224 if (!((WindowState)mWindows.get(pos)).mIsImWindow) {
1230 // Now there should be no more input method windows above.
1232 if (((WindowState)mWindows.get(pos)).mIsImWindow) {
1243 if (imWin != null) {
1244 if (DEBUG_INPUT_METHOD) {
1245 Slog.v(TAG, "Moving IM from " + imPos);
1248 imPos = tmpRemoveWindowLocked(imPos, imWin);
1249 if (DEBUG_INPUT_METHOD) {
1250 Slog.v(TAG, "List after moving with new pos " + imPos + ":");
1253 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1254 reAddWindowLocked(imPos, imWin);
1255 if (DEBUG_INPUT_METHOD) {
1256 Slog.v(TAG, "List after moving IM to " + imPos + ":");
1259 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1261 moveInputMethodDialogsLocked(imPos);
1265 // In this case, the input method windows go in a fixed layer,
1266 // because they aren't currently associated with a focus window.
1268 if (imWin != null) {
1269 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos);
1270 tmpRemoveWindowLocked(0, imWin);
1271 imWin.mTargetAppToken = null;
1272 reAddWindowToListInOrderLocked(imWin);
1273 if (DEBUG_INPUT_METHOD) {
1274 Slog.v(TAG, "List with no IM target:");
1277 if (DN > 0) moveInputMethodDialogsLocked(-1);;
1279 moveInputMethodDialogsLocked(-1);;
1284 if (needAssignLayers) {
1285 assignLayersLocked();
1291 void adjustInputMethodDialogsLocked() {
1292 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
1295 final boolean isWallpaperVisible(WindowState wallpaperTarget) {
1296 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target obscured="
1297 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
1298 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
1299 ? wallpaperTarget.mAppToken.animation : null)
1300 + " upper=" + mUpperWallpaperTarget
1301 + " lower=" + mLowerWallpaperTarget);
1302 return (wallpaperTarget != null
1303 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
1304 && wallpaperTarget.mAppToken.animation != null)))
1305 || mUpperWallpaperTarget != null
1306 || mLowerWallpaperTarget != null;
1309 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
1310 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
1312 int adjustWallpaperWindowsLocked() {
1315 final int dw = mDisplay.getWidth();
1316 final int dh = mDisplay.getHeight();
1318 // First find top-most window that has asked to be on top of the
1319 // wallpaper; all wallpapers go behind it.
1320 final ArrayList localmWindows = mWindows;
1321 int N = localmWindows.size();
1322 WindowState w = null;
1323 WindowState foundW = null;
1325 WindowState topCurW = null;
1330 w = (WindowState)localmWindows.get(i);
1331 if ((w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER)) {
1332 if (topCurW == null) {
1339 if (w.mAppToken != null) {
1340 // If this window's app token is hidden and not animating,
1341 // it is of no interest to us.
1342 if (w.mAppToken.hidden && w.mAppToken.animation == null) {
1343 if (DEBUG_WALLPAPER) Slog.v(TAG,
1344 "Skipping hidden or animating token: " + w);
1349 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w + ": readyfordisplay="
1350 + w.isReadyForDisplay() + " drawpending=" + w.mDrawPending
1351 + " commitdrawpending=" + w.mCommitDrawPending);
1352 if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()
1353 && (mWallpaperTarget == w
1354 || (!w.mDrawPending && !w.mCommitDrawPending))) {
1355 if (DEBUG_WALLPAPER) Slog.v(TAG,
1356 "Found wallpaper activity: #" + i + "=" + w);
1359 if (w == mWallpaperTarget && ((w.mAppToken != null
1360 && w.mAppToken.animation != null)
1361 || w.mAnimation != null)) {
1362 // The current wallpaper target is animating, so we'll
1363 // look behind it for another possible target and figure
1364 // out what is going on below.
1365 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
1366 + ": token animating, looking behind.");
1373 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
1374 // If we are currently waiting for an app transition, and either
1375 // the current target or the next target are involved with it,
1376 // then hold off on doing anything with the wallpaper.
1377 // Note that we are checking here for just whether the target
1378 // is part of an app token... which is potentially overly aggressive
1379 // (the app token may not be involved in the transition), but good
1380 // enough (we'll just wait until whatever transition is pending
1382 if (mWallpaperTarget != null && mWallpaperTarget.mAppToken != null) {
1383 if (DEBUG_WALLPAPER) Slog.v(TAG,
1384 "Wallpaper not changing: waiting for app anim in current target");
1387 if (foundW != null && foundW.mAppToken != null) {
1388 if (DEBUG_WALLPAPER) Slog.v(TAG,
1389 "Wallpaper not changing: waiting for app anim in found target");
1394 if (mWallpaperTarget != foundW) {
1395 if (DEBUG_WALLPAPER) {
1396 Slog.v(TAG, "New wallpaper target: " + foundW
1397 + " oldTarget: " + mWallpaperTarget);
1400 mLowerWallpaperTarget = null;
1401 mUpperWallpaperTarget = null;
1403 WindowState oldW = mWallpaperTarget;
1404 mWallpaperTarget = foundW;
1406 // Now what is happening... if the current and new targets are
1407 // animating, then we are in our super special mode!
1408 if (foundW != null && oldW != null) {
1409 boolean oldAnim = oldW.mAnimation != null
1410 || (oldW.mAppToken != null && oldW.mAppToken.animation != null);
1411 boolean foundAnim = foundW.mAnimation != null
1412 || (foundW.mAppToken != null && foundW.mAppToken.animation != null);
1413 if (DEBUG_WALLPAPER) {
1414 Slog.v(TAG, "New animation: " + foundAnim
1415 + " old animation: " + oldAnim);
1417 if (foundAnim && oldAnim) {
1418 int oldI = localmWindows.indexOf(oldW);
1419 if (DEBUG_WALLPAPER) {
1420 Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
1423 if (DEBUG_WALLPAPER) {
1424 Slog.v(TAG, "Animating wallpapers: old#" + oldI
1425 + "=" + oldW + "; new#" + foundI
1429 // Set the new target correctly.
1430 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
1431 if (DEBUG_WALLPAPER) {
1432 Slog.v(TAG, "Old wallpaper still the target.");
1434 mWallpaperTarget = oldW;
1437 // Now set the upper and lower wallpaper targets
1438 // correctly, and make sure that we are positioning
1439 // the wallpaper below the lower.
1440 if (foundI > oldI) {
1441 // The new target is on top of the old one.
1442 if (DEBUG_WALLPAPER) {
1443 Slog.v(TAG, "Found target above old target.");
1445 mUpperWallpaperTarget = foundW;
1446 mLowerWallpaperTarget = oldW;
1450 // The new target is below the old one.
1451 if (DEBUG_WALLPAPER) {
1452 Slog.v(TAG, "Found target below old target.");
1454 mUpperWallpaperTarget = oldW;
1455 mLowerWallpaperTarget = foundW;
1461 } else if (mLowerWallpaperTarget != null) {
1462 // Is it time to stop animating?
1463 boolean lowerAnimating = mLowerWallpaperTarget.mAnimation != null
1464 || (mLowerWallpaperTarget.mAppToken != null
1465 && mLowerWallpaperTarget.mAppToken.animation != null);
1466 boolean upperAnimating = mUpperWallpaperTarget.mAnimation != null
1467 || (mUpperWallpaperTarget.mAppToken != null
1468 && mUpperWallpaperTarget.mAppToken.animation != null);
1469 if (!lowerAnimating || !upperAnimating) {
1470 if (DEBUG_WALLPAPER) {
1471 Slog.v(TAG, "No longer animating wallpaper targets!");
1473 mLowerWallpaperTarget = null;
1474 mUpperWallpaperTarget = null;
1478 boolean visible = foundW != null;
1480 // The window is visible to the compositor... but is it visible
1481 // to the user? That is what the wallpaper cares about.
1482 visible = isWallpaperVisible(foundW);
1483 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
1485 // If the wallpaper target is animating, we may need to copy
1486 // its layer adjustment. Only do this if we are not transfering
1487 // between two wallpaper targets.
1488 mWallpaperAnimLayerAdjustment =
1489 (mLowerWallpaperTarget == null && foundW.mAppToken != null)
1490 ? foundW.mAppToken.animLayerAdjustment : 0;
1492 final int maxLayer = mPolicy.getMaxWallpaperLayer()
1493 * TYPE_LAYER_MULTIPLIER
1494 + TYPE_LAYER_OFFSET;
1496 // Now w is the window we are supposed to be behind... but we
1497 // need to be sure to also be behind any of its attached windows,
1498 // AND any starting window associated with it, AND below the
1499 // maximum layer the policy allows for wallpapers.
1500 while (foundI > 0) {
1501 WindowState wb = (WindowState)localmWindows.get(foundI-1);
1502 if (wb.mBaseLayer < maxLayer &&
1503 wb.mAttachedWindow != foundW &&
1504 (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
1505 wb.mToken != foundW.mToken)) {
1506 // This window is not related to the previous one in any
1507 // interesting way, so stop here.
1514 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
1517 if (foundW == null && topCurW != null) {
1518 // There is no wallpaper target, so it goes at the bottom.
1519 // We will assume it is the same place as last time, if known.
1523 // Okay i is the position immediately above the wallpaper. Look at
1524 // what is below it for later.
1525 foundW = foundI > 0 ? (WindowState)localmWindows.get(foundI-1) : null;
1529 if (mWallpaperTarget.mWallpaperX >= 0) {
1530 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
1531 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
1533 if (mWallpaperTarget.mWallpaperY >= 0) {
1534 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
1535 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
1539 // Start stepping backwards from here, ensuring that our wallpaper windows
1540 // are correctly placed.
1541 int curTokenIndex = mWallpaperTokens.size();
1542 while (curTokenIndex > 0) {
1544 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1545 if (token.hidden == visible) {
1546 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
1547 token.hidden = !visible;
1548 // Need to do a layout to ensure the wallpaper now has the
1550 mLayoutNeeded = true;
1553 int curWallpaperIndex = token.windows.size();
1554 while (curWallpaperIndex > 0) {
1555 curWallpaperIndex--;
1556 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1559 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
1562 // First, make sure the client has the current visibility
1564 if (wallpaper.mWallpaperVisible != visible) {
1565 wallpaper.mWallpaperVisible = visible;
1567 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
1568 "Setting visibility of wallpaper " + wallpaper
1570 wallpaper.mClient.dispatchAppVisibility(visible);
1571 } catch (RemoteException e) {
1575 wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
1576 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win "
1577 + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
1579 // First, if this window is at the current index, then all
1581 if (wallpaper == foundW) {
1584 ? (WindowState)localmWindows.get(foundI-1) : null;
1588 // The window didn't match... the current wallpaper window,
1589 // wherever it is, is in the wrong place, so make sure it is
1591 int oldIndex = localmWindows.indexOf(wallpaper);
1592 if (oldIndex >= 0) {
1593 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
1594 + oldIndex + ": " + wallpaper);
1595 localmWindows.remove(oldIndex);
1596 if (oldIndex < foundI) {
1602 if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
1603 "Moving wallpaper " + wallpaper
1604 + " from " + oldIndex + " to " + foundI);
1606 localmWindows.add(foundI, wallpaper);
1607 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
1614 void setWallpaperAnimLayerAdjustmentLocked(int adj) {
1615 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
1616 "Setting wallpaper layer adj to " + adj);
1617 mWallpaperAnimLayerAdjustment = adj;
1618 int curTokenIndex = mWallpaperTokens.size();
1619 while (curTokenIndex > 0) {
1621 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1622 int curWallpaperIndex = token.windows.size();
1623 while (curWallpaperIndex > 0) {
1624 curWallpaperIndex--;
1625 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1626 wallpaper.mAnimLayer = wallpaper.mLayer + adj;
1627 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win "
1628 + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
1633 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
1635 boolean changed = false;
1636 boolean rawChanged = false;
1637 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
1638 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
1639 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
1640 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
1641 changed = wallpaperWin.mXOffset != offset;
1643 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
1644 + wallpaperWin + " x: " + offset);
1645 wallpaperWin.mXOffset = offset;
1647 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
1648 wallpaperWin.mWallpaperX = wpx;
1649 wallpaperWin.mWallpaperXStep = wpxs;
1653 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
1654 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
1655 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
1656 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
1657 if (wallpaperWin.mYOffset != offset) {
1658 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
1659 + wallpaperWin + " y: " + offset);
1661 wallpaperWin.mYOffset = offset;
1663 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
1664 wallpaperWin.mWallpaperY = wpy;
1665 wallpaperWin.mWallpaperYStep = wpys;
1671 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
1672 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
1673 + " y=" + wallpaperWin.mWallpaperY);
1675 mWaitingOnWallpaper = wallpaperWin;
1677 wallpaperWin.mClient.dispatchWallpaperOffsets(
1678 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
1679 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
1681 if (mWaitingOnWallpaper != null) {
1682 long start = SystemClock.uptimeMillis();
1683 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
1686 if (DEBUG_WALLPAPER) Slog.v(TAG,
1687 "Waiting for offset complete...");
1688 mWindowMap.wait(WALLPAPER_TIMEOUT);
1689 } catch (InterruptedException e) {
1691 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
1692 if ((start+WALLPAPER_TIMEOUT)
1693 < SystemClock.uptimeMillis()) {
1694 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
1696 mLastWallpaperTimeoutTime = start;
1699 mWaitingOnWallpaper = null;
1702 } catch (RemoteException e) {
1709 void wallpaperOffsetsComplete(IBinder window) {
1710 synchronized (mWindowMap) {
1711 if (mWaitingOnWallpaper != null &&
1712 mWaitingOnWallpaper.mClient.asBinder() == window) {
1713 mWaitingOnWallpaper = null;
1714 mWindowMap.notifyAll();
1719 boolean updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
1720 final int dw = mDisplay.getWidth();
1721 final int dh = mDisplay.getHeight();
1723 boolean changed = false;
1725 WindowState target = mWallpaperTarget;
1726 if (target != null) {
1727 if (target.mWallpaperX >= 0) {
1728 mLastWallpaperX = target.mWallpaperX;
1729 } else if (changingTarget.mWallpaperX >= 0) {
1730 mLastWallpaperX = changingTarget.mWallpaperX;
1732 if (target.mWallpaperY >= 0) {
1733 mLastWallpaperY = target.mWallpaperY;
1734 } else if (changingTarget.mWallpaperY >= 0) {
1735 mLastWallpaperY = changingTarget.mWallpaperY;
1739 int curTokenIndex = mWallpaperTokens.size();
1740 while (curTokenIndex > 0) {
1742 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1743 int curWallpaperIndex = token.windows.size();
1744 while (curWallpaperIndex > 0) {
1745 curWallpaperIndex--;
1746 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1747 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
1748 wallpaper.computeShownFrameLocked();
1750 // We only want to be synchronous with one wallpaper.
1759 void updateWallpaperVisibilityLocked() {
1760 final boolean visible = isWallpaperVisible(mWallpaperTarget);
1761 final int dw = mDisplay.getWidth();
1762 final int dh = mDisplay.getHeight();
1764 int curTokenIndex = mWallpaperTokens.size();
1765 while (curTokenIndex > 0) {
1767 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1768 if (token.hidden == visible) {
1769 token.hidden = !visible;
1770 // Need to do a layout to ensure the wallpaper now has the
1772 mLayoutNeeded = true;
1775 int curWallpaperIndex = token.windows.size();
1776 while (curWallpaperIndex > 0) {
1777 curWallpaperIndex--;
1778 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1780 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
1783 if (wallpaper.mWallpaperVisible != visible) {
1784 wallpaper.mWallpaperVisible = visible;
1786 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
1787 "Updating visibility of wallpaper " + wallpaper
1789 wallpaper.mClient.dispatchAppVisibility(visible);
1790 } catch (RemoteException e) {
1797 void sendPointerToWallpaperLocked(WindowState srcWin,
1798 MotionEvent pointer, long eventTime) {
1799 int curTokenIndex = mWallpaperTokens.size();
1800 while (curTokenIndex > 0) {
1802 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1803 int curWallpaperIndex = token.windows.size();
1804 while (curWallpaperIndex > 0) {
1805 curWallpaperIndex--;
1806 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1807 if ((wallpaper.mAttrs.flags &
1808 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
1812 MotionEvent ev = MotionEvent.obtainNoHistory(pointer);
1813 if (srcWin != null) {
1814 ev.offsetLocation(srcWin.mFrame.left-wallpaper.mFrame.left,
1815 srcWin.mFrame.top-wallpaper.mFrame.top);
1817 ev.offsetLocation(-wallpaper.mFrame.left, -wallpaper.mFrame.top);
1819 switch (pointer.getAction()) {
1820 case MotionEvent.ACTION_DOWN:
1821 mSendingPointersToWallpaper = true;
1823 case MotionEvent.ACTION_UP:
1824 mSendingPointersToWallpaper = false;
1827 wallpaper.mClient.dispatchPointer(ev, eventTime, false);
1828 } catch (RemoteException e) {
1829 Slog.w(TAG, "Failure sending pointer to wallpaper", e);
1835 void dispatchPointerElsewhereLocked(WindowState srcWin, WindowState relWin,
1836 MotionEvent pointer, long eventTime, boolean skipped) {
1837 if (relWin != null) {
1838 mPolicy.dispatchedPointerEventLw(pointer, relWin.mFrame.left, relWin.mFrame.top);
1840 mPolicy.dispatchedPointerEventLw(pointer, 0, 0);
1843 // If we sent an initial down to the wallpaper, then continue
1844 // sending events until the final up.
1845 if (mSendingPointersToWallpaper) {
1847 Slog.i(TAG, "Sending skipped pointer to wallpaper!");
1849 sendPointerToWallpaperLocked(relWin, pointer, eventTime);
1851 // If we are on top of the wallpaper, then the wallpaper also
1852 // gets to see this movement.
1853 } else if (srcWin != null
1854 && pointer.getAction() == MotionEvent.ACTION_DOWN
1855 && mWallpaperTarget == srcWin
1856 && srcWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
1857 sendPointerToWallpaperLocked(relWin, pointer, eventTime);
1861 public int addWindow(Session session, IWindow client,
1862 WindowManager.LayoutParams attrs, int viewVisibility,
1863 Rect outContentInsets) {
1864 int res = mPolicy.checkAddPermission(attrs);
1865 if (res != WindowManagerImpl.ADD_OKAY) {
1869 boolean reportNewConfig = false;
1870 WindowState attachedWindow = null;
1871 WindowState win = null;
1873 synchronized(mWindowMap) {
1874 // Instantiating a Display requires talking with the simulator,
1875 // so don't do it until we know the system is mostly up and
1877 if (mDisplay == null) {
1878 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1879 mDisplay = wm.getDefaultDisplay();
1880 mInitialDisplayWidth = mDisplay.getWidth();
1881 mInitialDisplayHeight = mDisplay.getHeight();
1882 mQueue.setDisplay(mDisplay);
1883 reportNewConfig = true;
1886 if (mWindowMap.containsKey(client.asBinder())) {
1887 Slog.w(TAG, "Window " + client + " is already added");
1888 return WindowManagerImpl.ADD_DUPLICATE_ADD;
1891 if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
1892 attachedWindow = windowForClientLocked(null, attrs.token, false);
1893 if (attachedWindow == null) {
1894 Slog.w(TAG, "Attempted to add window with token that is not a window: "
1895 + attrs.token + ". Aborting.");
1896 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1898 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
1899 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
1900 Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
1901 + attrs.token + ". Aborting.");
1902 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1906 boolean addToken = false;
1907 WindowToken token = mTokenMap.get(attrs.token);
1908 if (token == null) {
1909 if (attrs.type >= FIRST_APPLICATION_WINDOW
1910 && attrs.type <= LAST_APPLICATION_WINDOW) {
1911 Slog.w(TAG, "Attempted to add application window with unknown token "
1912 + attrs.token + ". Aborting.");
1913 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1915 if (attrs.type == TYPE_INPUT_METHOD) {
1916 Slog.w(TAG, "Attempted to add input method window with unknown token "
1917 + attrs.token + ". Aborting.");
1918 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1920 if (attrs.type == TYPE_WALLPAPER) {
1921 Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
1922 + attrs.token + ". Aborting.");
1923 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1925 token = new WindowToken(attrs.token, -1, false);
1927 } else if (attrs.type >= FIRST_APPLICATION_WINDOW
1928 && attrs.type <= LAST_APPLICATION_WINDOW) {
1929 AppWindowToken atoken = token.appWindowToken;
1930 if (atoken == null) {
1931 Slog.w(TAG, "Attempted to add window with non-application token "
1932 + token + ". Aborting.");
1933 return WindowManagerImpl.ADD_NOT_APP_TOKEN;
1934 } else if (atoken.removed) {
1935 Slog.w(TAG, "Attempted to add window with exiting application token "
1936 + token + ". Aborting.");
1937 return WindowManagerImpl.ADD_APP_EXITING;
1939 if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
1940 // No need for this guy!
1941 if (localLOGV) Slog.v(
1942 TAG, "**** NO NEED TO START: " + attrs.getTitle());
1943 return WindowManagerImpl.ADD_STARTING_NOT_NEEDED;
1945 } else if (attrs.type == TYPE_INPUT_METHOD) {
1946 if (token.windowType != TYPE_INPUT_METHOD) {
1947 Slog.w(TAG, "Attempted to add input method window with bad token "
1948 + attrs.token + ". Aborting.");
1949 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1951 } else if (attrs.type == TYPE_WALLPAPER) {
1952 if (token.windowType != TYPE_WALLPAPER) {
1953 Slog.w(TAG, "Attempted to add wallpaper window with bad token "
1954 + attrs.token + ". Aborting.");
1955 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1959 win = new WindowState(session, client, token,
1960 attachedWindow, attrs, viewVisibility);
1961 if (win.mDeathRecipient == null) {
1962 // Client has apparently died, so there is no reason to
1964 Slog.w(TAG, "Adding window client " + client.asBinder()
1965 + " that is dead, aborting.");
1966 return WindowManagerImpl.ADD_APP_EXITING;
1969 mPolicy.adjustWindowParamsLw(win.mAttrs);
1971 res = mPolicy.prepareAddWindowLw(win, attrs);
1972 if (res != WindowManagerImpl.ADD_OKAY) {
1976 // From now on, no exceptions or errors allowed!
1978 res = WindowManagerImpl.ADD_OKAY;
1980 final long origId = Binder.clearCallingIdentity();
1983 mTokenMap.put(attrs.token, token);
1984 mTokenList.add(token);
1987 mWindowMap.put(client.asBinder(), win);
1989 if (attrs.type == TYPE_APPLICATION_STARTING &&
1990 token.appWindowToken != null) {
1991 token.appWindowToken.startingWindow = win;
1994 boolean imMayMove = true;
1996 if (attrs.type == TYPE_INPUT_METHOD) {
1997 mInputMethodWindow = win;
1998 addInputMethodWindowToListLocked(win);
2000 } else if (attrs.type == TYPE_INPUT_METHOD_DIALOG) {
2001 mInputMethodDialogs.add(win);
2002 addWindowToListInOrderLocked(win, true);
2003 adjustInputMethodDialogsLocked();
2006 addWindowToListInOrderLocked(win, true);
2007 if (attrs.type == TYPE_WALLPAPER) {
2008 mLastWallpaperTimeoutTime = 0;
2009 adjustWallpaperWindowsLocked();
2010 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2011 adjustWallpaperWindowsLocked();
2015 win.mEnterAnimationPending = true;
2017 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
2020 res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
2022 if (win == null || win.mAppToken == null || !win.mAppToken.clientHidden) {
2023 res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
2026 boolean focusChanged = false;
2027 if (win.canReceiveKeys()) {
2028 if ((focusChanged=updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS))
2035 moveInputMethodWindowsIfNeededLocked(false);
2038 assignLayersLocked();
2039 // Don't do layout here, the window must call
2040 // relayout to be displayed, so we'll do it there.
2045 if (mCurrentFocus != null) {
2046 mKeyWaiter.handleNewWindowLocked(mCurrentFocus);
2049 if (localLOGV) Slog.v(
2050 TAG, "New client " + client.asBinder()
2051 + ": window=" + win);
2053 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked()) {
2054 reportNewConfig = true;
2058 // sendNewConfiguration() checks caller permissions so we must call it with
2059 // privilege. updateOrientationFromAppTokens() clears and resets the caller
2060 // identity anyway, so it's safe to just clear & restore around this whole
2062 final long origId = Binder.clearCallingIdentity();
2063 if (reportNewConfig) {
2064 sendNewConfiguration();
2066 Binder.restoreCallingIdentity(origId);
2071 public void removeWindow(Session session, IWindow client) {
2072 synchronized(mWindowMap) {
2073 WindowState win = windowForClientLocked(session, client, false);
2077 removeWindowLocked(session, win);
2081 public void removeWindowLocked(Session session, WindowState win) {
2083 if (localLOGV || DEBUG_FOCUS) Slog.v(
2084 TAG, "Remove " + win + " client="
2085 + Integer.toHexString(System.identityHashCode(
2086 win.mClient.asBinder()))
2087 + ", surface=" + win.mSurface);
2089 final long origId = Binder.clearCallingIdentity();
2091 if (DEBUG_APP_TRANSITIONS) Slog.v(
2092 TAG, "Remove " + win + ": mSurface=" + win.mSurface
2093 + " mExiting=" + win.mExiting
2094 + " isAnimating=" + win.isAnimating()
2096 + (win.mAppToken != null ? win.mAppToken.animation : null)
2097 + " inPendingTransaction="
2098 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
2099 + " mDisplayFrozen=" + mDisplayFrozen);
2100 // Visibility of the removed window. Will be used later to update orientation later on.
2101 boolean wasVisible = false;
2102 // First, see if we need to run an animation. If we do, we have
2103 // to hold off on removing the window until the animation is done.
2104 // If the display is frozen, just remove immediately, since the
2105 // animation wouldn't be seen.
2106 if (win.mSurface != null && !mDisplayFrozen && mPolicy.isScreenOn()) {
2107 // If we are not currently running the exit animation, we
2108 // need to see about starting one.
2109 if (wasVisible=win.isWinVisibleLw()) {
2111 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2112 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2113 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2115 // Try starting an animation.
2116 if (applyAnimationLocked(win, transit, false)) {
2117 win.mExiting = true;
2120 if (win.mExiting || win.isAnimating()) {
2121 // The exit animation is running... wait for it!
2122 //Slog.i(TAG, "*** Running exit animation...");
2123 win.mExiting = true;
2124 win.mRemoveOnExit = true;
2125 mLayoutNeeded = true;
2126 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
2127 performLayoutAndPlaceSurfacesLocked();
2128 if (win.mAppToken != null) {
2129 win.mAppToken.updateReportedVisibilityLocked();
2132 Binder.restoreCallingIdentity(origId);
2137 removeWindowInnerLocked(session, win);
2138 // Removing a visible window will effect the computed orientation
2139 // So just update orientation if needed.
2140 if (wasVisible && computeForcedAppOrientationLocked()
2141 != mForcedAppOrientation
2142 && updateOrientationFromAppTokensLocked()) {
2143 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
2145 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2146 Binder.restoreCallingIdentity(origId);
2149 private void removeWindowInnerLocked(Session session, WindowState win) {
2150 mKeyWaiter.finishedKey(session, win.mClient, true,
2151 KeyWaiter.RETURN_NOTHING);
2152 mKeyWaiter.releasePendingPointerLocked(win.mSession);
2153 mKeyWaiter.releasePendingTrackballLocked(win.mSession);
2155 win.mRemoved = true;
2157 if (mInputMethodTarget == win) {
2158 moveInputMethodWindowsIfNeededLocked(false);
2162 RuntimeException e = new RuntimeException("here");
2163 e.fillInStackTrace();
2164 Slog.w(TAG, "Removing window " + win, e);
2167 mPolicy.removeWindowLw(win);
2170 mWindowMap.remove(win.mClient.asBinder());
2171 mWindows.remove(win);
2172 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
2174 if (mInputMethodWindow == win) {
2175 mInputMethodWindow = null;
2176 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2177 mInputMethodDialogs.remove(win);
2180 final WindowToken token = win.mToken;
2181 final AppWindowToken atoken = win.mAppToken;
2182 token.windows.remove(win);
2183 if (atoken != null) {
2184 atoken.allAppWindows.remove(win);
2186 if (localLOGV) Slog.v(
2187 TAG, "**** Removing window " + win + ": count="
2188 + token.windows.size());
2189 if (token.windows.size() == 0) {
2190 if (!token.explicit) {
2191 mTokenMap.remove(token.token);
2192 mTokenList.remove(token);
2193 } else if (atoken != null) {
2194 atoken.firstWindowDrawn = false;
2198 if (atoken != null) {
2199 if (atoken.startingWindow == win) {
2200 atoken.startingWindow = null;
2201 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2202 // If this is the last window and we had requested a starting
2203 // transition window, well there is no point now.
2204 atoken.startingData = null;
2205 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2206 // If this is the last window except for a starting transition
2207 // window, we need to get rid of the starting transition.
2208 if (DEBUG_STARTING_WINDOW) {
2209 Slog.v(TAG, "Schedule remove starting " + token
2210 + ": no more real windows");
2212 Message m = mH.obtainMessage(H.REMOVE_STARTING, atoken);
2217 if (win.mAttrs.type == TYPE_WALLPAPER) {
2218 mLastWallpaperTimeoutTime = 0;
2219 adjustWallpaperWindowsLocked();
2220 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2221 adjustWallpaperWindowsLocked();
2225 assignLayersLocked();
2226 mLayoutNeeded = true;
2227 performLayoutAndPlaceSurfacesLocked();
2228 if (win.mAppToken != null) {
2229 win.mAppToken.updateReportedVisibilityLocked();
2234 private static void logSurface(WindowState w, String msg, RuntimeException where) {
2235 String str = " SURFACE " + Integer.toHexString(w.hashCode())
2236 + ": " + msg + " / " + w.mAttrs.getTitle();
2237 if (where != null) {
2238 Slog.i(TAG, str, where);
2244 private void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2245 long origId = Binder.clearCallingIdentity();
2247 synchronized (mWindowMap) {
2248 WindowState w = windowForClientLocked(session, client, false);
2249 if ((w != null) && (w.mSurface != null)) {
2250 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
2251 Surface.openTransaction();
2253 if (SHOW_TRANSACTIONS) logSurface(w,
2254 "transparentRegionHint=" + region, null);
2255 w.mSurface.setTransparentRegionHint(region);
2257 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
2258 Surface.closeTransaction();
2263 Binder.restoreCallingIdentity(origId);
2267 void setInsetsWindow(Session session, IWindow client,
2268 int touchableInsets, Rect contentInsets,
2269 Rect visibleInsets) {
2270 long origId = Binder.clearCallingIdentity();
2272 synchronized (mWindowMap) {
2273 WindowState w = windowForClientLocked(session, client, false);
2275 w.mGivenInsetsPending = false;
2276 w.mGivenContentInsets.set(contentInsets);
2277 w.mGivenVisibleInsets.set(visibleInsets);
2278 w.mTouchableInsets = touchableInsets;
2279 mLayoutNeeded = true;
2280 performLayoutAndPlaceSurfacesLocked();
2284 Binder.restoreCallingIdentity(origId);
2288 public void getWindowDisplayFrame(Session session, IWindow client,
2289 Rect outDisplayFrame) {
2290 synchronized(mWindowMap) {
2291 WindowState win = windowForClientLocked(session, client, false);
2293 outDisplayFrame.setEmpty();
2296 outDisplayFrame.set(win.mDisplayFrame);
2300 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
2301 float xStep, float yStep) {
2302 if (window.mWallpaperX != x || window.mWallpaperY != y) {
2303 window.mWallpaperX = x;
2304 window.mWallpaperY = y;
2305 window.mWallpaperXStep = xStep;
2306 window.mWallpaperYStep = yStep;
2307 if (updateWallpaperOffsetLocked(window, true)) {
2308 performLayoutAndPlaceSurfacesLocked();
2313 void wallpaperCommandComplete(IBinder window, Bundle result) {
2314 synchronized (mWindowMap) {
2315 if (mWaitingOnWallpaper != null &&
2316 mWaitingOnWallpaper.mClient.asBinder() == window) {
2317 mWaitingOnWallpaper = null;
2318 mWindowMap.notifyAll();
2323 public Bundle sendWindowWallpaperCommandLocked(WindowState window,
2324 String action, int x, int y, int z, Bundle extras, boolean sync) {
2325 if (window == mWallpaperTarget || window == mLowerWallpaperTarget
2326 || window == mUpperWallpaperTarget) {
2327 boolean doWait = sync;
2328 int curTokenIndex = mWallpaperTokens.size();
2329 while (curTokenIndex > 0) {
2331 WindowToken token = mWallpaperTokens.get(curTokenIndex);
2332 int curWallpaperIndex = token.windows.size();
2333 while (curWallpaperIndex > 0) {
2334 curWallpaperIndex--;
2335 WindowState wallpaper = token.windows.get(curWallpaperIndex);
2337 wallpaper.mClient.dispatchWallpaperCommand(action,
2338 x, y, z, extras, sync);
2339 // We only want to be synchronous with one wallpaper.
2341 } catch (RemoteException e) {
2347 // XXX Need to wait for result.
2354 public int relayoutWindow(Session session, IWindow client,
2355 WindowManager.LayoutParams attrs, int requestedWidth,
2356 int requestedHeight, int viewVisibility, boolean insetsPending,
2357 Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
2358 Configuration outConfig, Surface outSurface) {
2359 boolean displayed = false;
2360 boolean inTouchMode;
2361 boolean configChanged;
2362 long origId = Binder.clearCallingIdentity();
2364 synchronized(mWindowMap) {
2365 WindowState win = windowForClientLocked(session, client, false);
2369 win.mRequestedWidth = requestedWidth;
2370 win.mRequestedHeight = requestedHeight;
2372 if (attrs != null) {
2373 mPolicy.adjustWindowParamsLw(attrs);
2376 int attrChanges = 0;
2377 int flagChanges = 0;
2378 if (attrs != null) {
2379 flagChanges = win.mAttrs.flags ^= attrs.flags;
2380 attrChanges = win.mAttrs.copyFrom(attrs);
2383 if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": " + win.mAttrs);
2385 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2386 win.mAlpha = attrs.alpha;
2389 final boolean scaledWindow =
2390 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
2393 // requested{Width|Height} Surface's physical size
2394 // attrs.{width|height} Size on screen
2395 win.mHScale = (attrs.width != requestedWidth) ?
2396 (attrs.width / (float)requestedWidth) : 1.0f;
2397 win.mVScale = (attrs.height != requestedHeight) ?
2398 (attrs.height / (float)requestedHeight) : 1.0f;
2400 win.mHScale = win.mVScale = 1;
2403 boolean imMayMove = (flagChanges&(
2404 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
2405 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)) != 0;
2407 boolean focusMayChange = win.mViewVisibility != viewVisibility
2408 || ((flagChanges&WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0)
2409 || (!win.mRelayoutCalled);
2411 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2412 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
2414 win.mRelayoutCalled = true;
2415 final int oldVisibility = win.mViewVisibility;
2416 win.mViewVisibility = viewVisibility;
2417 if (viewVisibility == View.VISIBLE &&
2418 (win.mAppToken == null || !win.mAppToken.clientHidden)) {
2419 displayed = !win.isVisibleLw();
2421 win.mExiting = false;
2422 win.mAnimation = null;
2424 if (win.mDestroying) {
2425 win.mDestroying = false;
2426 mDestroySurface.remove(win);
2428 if (oldVisibility == View.GONE) {
2429 win.mEnterAnimationPending = true;
2432 if (win.mSurface != null && !win.mDrawPending
2433 && !win.mCommitDrawPending && !mDisplayFrozen
2434 && mPolicy.isScreenOn()) {
2435 applyEnterAnimationLocked(win);
2437 if ((win.mAttrs.flags
2438 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
2439 if (DEBUG_VISIBILITY) Slog.v(TAG,
2440 "Relayout window turning screen on: " + win);
2441 win.mTurnOnScreen = true;
2444 if (win.mConfiguration != mCurConfiguration
2445 && (win.mConfiguration == null
2446 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0)) {
2447 win.mConfiguration = mCurConfiguration;
2448 if (DEBUG_CONFIGURATION) {
2449 Slog.i(TAG, "Window " + win + " visible with new config: "
2450 + win.mConfiguration + " / 0x"
2451 + Integer.toHexString(diff));
2453 outConfig.setTo(mCurConfiguration);
2456 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
2457 // To change the format, we need to re-build the surface.
2458 win.destroySurfaceLocked();
2462 Surface surface = win.createSurfaceLocked();
2463 if (surface != null) {
2464 outSurface.copyFrom(surface);
2465 win.mReportDestroySurface = false;
2466 win.mSurfacePendingDestroy = false;
2467 if (SHOW_TRANSACTIONS) Slog.i(TAG,
2468 " OUT SURFACE " + outSurface + ": copied");
2470 // For some reason there isn't a surface. Clear the
2471 // caller's object so they see the same state.
2472 outSurface.release();
2474 } catch (Exception e) {
2475 Slog.w(TAG, "Exception thrown when creating surface for client "
2476 + client + " (" + win.mAttrs.getTitle() + ")",
2478 Binder.restoreCallingIdentity(origId);
2482 focusMayChange = true;
2484 if (win.mAttrs.type == TYPE_INPUT_METHOD
2485 && mInputMethodWindow == null) {
2486 mInputMethodWindow = win;
2489 if (win.mAttrs.type == TYPE_BASE_APPLICATION
2490 && win.mAppToken != null
2491 && win.mAppToken.startingWindow != null) {
2492 // Special handling of starting window over the base
2493 // window of the app: propagate lock screen flags to it,
2494 // to provide the correct semantics while starting.
2496 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
2497 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
2498 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
2499 WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
2500 sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
2503 win.mEnterAnimationPending = false;
2504 if (win.mSurface != null) {
2505 if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
2506 + ": mExiting=" + win.mExiting
2507 + " mSurfacePendingDestroy=" + win.mSurfacePendingDestroy);
2508 // If we are not currently running the exit animation, we
2509 // need to see about starting one.
2510 if (!win.mExiting || win.mSurfacePendingDestroy) {
2511 // Try starting an animation; if there isn't one, we
2512 // can destroy the surface right away.
2513 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2514 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2515 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2517 if (!win.mSurfacePendingDestroy && win.isWinVisibleLw() &&
2518 applyAnimationLocked(win, transit, false)) {
2519 focusMayChange = true;
2520 win.mExiting = true;
2521 mKeyWaiter.finishedKey(session, client, true,
2522 KeyWaiter.RETURN_NOTHING);
2523 } else if (win.isAnimating()) {
2524 // Currently in a hide animation... turn this into
2526 win.mExiting = true;
2527 } else if (win == mWallpaperTarget) {
2528 // If the wallpaper is currently behind this
2529 // window, we need to change both of them inside
2530 // of a transaction to avoid artifacts.
2531 win.mExiting = true;
2532 win.mAnimating = true;
2534 if (mInputMethodWindow == win) {
2535 mInputMethodWindow = null;
2537 win.destroySurfaceLocked();
2542 if (win.mSurface == null || (win.getAttrs().flags
2543 & WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING) == 0
2544 || win.mSurfacePendingDestroy) {
2545 // We are being called from a local process, which
2546 // means outSurface holds its current surface. Ensure the
2547 // surface object is cleared, but we don't want it actually
2548 // destroyed at this point.
2549 win.mSurfacePendingDestroy = false;
2550 outSurface.release();
2551 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
2552 } else if (win.mSurface != null) {
2553 if (DEBUG_VISIBILITY) Slog.i(TAG,
2554 "Keeping surface, will report destroy: " + win);
2555 win.mReportDestroySurface = true;
2556 outSurface.copyFrom(win.mSurface);
2560 if (focusMayChange) {
2561 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2562 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
2565 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2568 // updateFocusedWindowLocked() already assigned layers so we only need to
2569 // reassign them at this point if the IM window state gets shuffled
2570 boolean assignLayers = false;
2573 if (moveInputMethodWindowsIfNeededLocked(false) || displayed) {
2574 // Little hack here -- we -should- be able to rely on the
2575 // function to return true if the IME has moved and needs
2576 // its layer recomputed. However, if the IME was hidden
2577 // and isn't actually moved in the list, its layer may be
2578 // out of data so we make sure to recompute it.
2579 assignLayers = true;
2582 if (wallpaperMayMove) {
2583 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
2584 assignLayers = true;
2588 mLayoutNeeded = true;
2589 win.mGivenInsetsPending = insetsPending;
2591 assignLayersLocked();
2593 configChanged = updateOrientationFromAppTokensLocked();
2594 performLayoutAndPlaceSurfacesLocked();
2595 if (displayed && win.mIsWallpaper) {
2596 updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
2597 mDisplay.getHeight(), false);
2599 if (win.mAppToken != null) {
2600 win.mAppToken.updateReportedVisibilityLocked();
2602 outFrame.set(win.mFrame);
2603 outContentInsets.set(win.mContentInsets);
2604 outVisibleInsets.set(win.mVisibleInsets);
2605 if (localLOGV) Slog.v(
2606 TAG, "Relayout given client " + client.asBinder()
2607 + ", requestedWidth=" + requestedWidth
2608 + ", requestedHeight=" + requestedHeight
2609 + ", viewVisibility=" + viewVisibility
2610 + "\nRelayout returning frame=" + outFrame
2611 + ", surface=" + outSurface);
2613 if (localLOGV || DEBUG_FOCUS) Slog.v(
2614 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
2616 inTouchMode = mInTouchMode;
2619 if (configChanged) {
2620 sendNewConfiguration();
2623 Binder.restoreCallingIdentity(origId);
2625 return (inTouchMode ? WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE : 0)
2626 | (displayed ? WindowManagerImpl.RELAYOUT_FIRST_TIME : 0);
2629 public void finishDrawingWindow(Session session, IWindow client) {
2630 final long origId = Binder.clearCallingIdentity();
2631 synchronized(mWindowMap) {
2632 WindowState win = windowForClientLocked(session, client, false);
2633 if (win != null && win.finishDrawingLocked()) {
2634 if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2635 adjustWallpaperWindowsLocked();
2637 mLayoutNeeded = true;
2638 performLayoutAndPlaceSurfacesLocked();
2641 Binder.restoreCallingIdentity(origId);
2644 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
2645 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: params package="
2646 + (lp != null ? lp.packageName : null)
2647 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
2648 if (lp != null && lp.windowAnimations != 0) {
2649 // If this is a system resource, don't try to load it from the
2650 // application resources. It is nice to avoid loading application
2651 // resources if we can.
2652 String packageName = lp.packageName != null ? lp.packageName : "android";
2653 int resId = lp.windowAnimations;
2654 if ((resId&0xFF000000) == 0x01000000) {
2655 packageName = "android";
2657 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
2659 return AttributeCache.instance().get(packageName, resId,
2660 com.android.internal.R.styleable.WindowAnimation);
2665 private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
2666 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: params package="
2667 + packageName + " resId=0x" + Integer.toHexString(resId));
2668 if (packageName != null) {
2669 if ((resId&0xFF000000) == 0x01000000) {
2670 packageName = "android";
2672 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
2674 return AttributeCache.instance().get(packageName, resId,
2675 com.android.internal.R.styleable.WindowAnimation);
2680 private void applyEnterAnimationLocked(WindowState win) {
2681 int transit = WindowManagerPolicy.TRANSIT_SHOW;
2682 if (win.mEnterAnimationPending) {
2683 win.mEnterAnimationPending = false;
2684 transit = WindowManagerPolicy.TRANSIT_ENTER;
2687 applyAnimationLocked(win, transit, true);
2690 private boolean applyAnimationLocked(WindowState win,
2691 int transit, boolean isEntrance) {
2692 if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) {
2693 // If we are trying to apply an animation, but already running
2694 // an animation of the same type, then just leave that one alone.
2698 // Only apply an animation if the display isn't frozen. If it is
2699 // frozen, there is no reason to animate and it can cause strange
2700 // artifacts when we unfreeze the display if some different animation
2702 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
2703 int anim = mPolicy.selectAnimationLw(win, transit);
2707 a = AnimationUtils.loadAnimation(mContext, anim);
2710 case WindowManagerPolicy.TRANSIT_ENTER:
2711 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
2713 case WindowManagerPolicy.TRANSIT_EXIT:
2714 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
2716 case WindowManagerPolicy.TRANSIT_SHOW:
2717 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
2719 case WindowManagerPolicy.TRANSIT_HIDE:
2720 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
2724 a = loadAnimation(win.mAttrs, attr);
2727 if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: win=" + win
2728 + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
2729 + " mAnimation=" + win.mAnimation
2730 + " isEntrance=" + isEntrance);
2733 RuntimeException e = null;
2734 if (!HIDE_STACK_CRAWLS) {
2735 e = new RuntimeException();
2736 e.fillInStackTrace();
2738 Slog.v(TAG, "Loaded animation " + a + " for " + win, e);
2740 win.setAnimation(a);
2741 win.mAnimationIsEntrance = isEntrance;
2744 win.clearAnimation();
2747 return win.mAnimation != null;
2750 private Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
2752 Context context = mContext;
2753 if (animAttr >= 0) {
2754 AttributeCache.Entry ent = getCachedAnimations(lp);
2756 context = ent.context;
2757 anim = ent.array.getResourceId(animAttr, 0);
2761 return AnimationUtils.loadAnimation(context, anim);
2766 private Animation loadAnimation(String packageName, int resId) {
2768 Context context = mContext;
2770 AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
2772 context = ent.context;
2777 return AnimationUtils.loadAnimation(context, anim);
2782 private boolean applyAnimationLocked(AppWindowToken wtoken,
2783 WindowManager.LayoutParams lp, int transit, boolean enter) {
2784 // Only apply an animation if the display isn't frozen. If it is
2785 // frozen, there is no reason to animate and it can cause strange
2786 // artifacts when we unfreeze the display if some different animation
2788 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
2790 if (lp != null && (lp.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
2791 a = new FadeInOutAnimation(enter);
2792 if (DEBUG_ANIM) Slog.v(TAG,
2793 "applying FadeInOutAnimation for a window in compatibility mode");
2794 } else if (mNextAppTransitionPackage != null) {
2795 a = loadAnimation(mNextAppTransitionPackage, enter ?
2796 mNextAppTransitionEnter : mNextAppTransitionExit);
2800 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
2802 ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation
2803 : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
2805 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
2807 ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation
2808 : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
2810 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
2812 ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation
2813 : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
2815 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
2817 ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation
2818 : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
2820 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
2822 ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation
2823 : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
2825 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
2827 ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation
2828 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
2830 case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN:
2832 ? com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation
2833 : com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
2835 case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE:
2837 ? com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation
2838 : com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
2840 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN:
2842 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation
2843 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
2845 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE:
2847 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation
2848 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
2851 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null;
2852 if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
2854 + " animAttr=0x" + Integer.toHexString(animAttr)
2855 + " transit=" + transit);
2859 RuntimeException e = null;
2860 if (!HIDE_STACK_CRAWLS) {
2861 e = new RuntimeException();
2862 e.fillInStackTrace();
2864 Slog.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
2866 wtoken.setAnimation(a);
2869 wtoken.clearAnimation();
2872 return wtoken.animation != null;
2875 // -------------------------------------------------------------
2876 // Application Window Tokens
2877 // -------------------------------------------------------------
2879 public void validateAppTokens(List tokens) {
2880 int v = tokens.size()-1;
2881 int m = mAppTokens.size()-1;
2882 while (v >= 0 && m >= 0) {
2883 AppWindowToken wtoken = mAppTokens.get(m);
2884 if (wtoken.removed) {
2888 if (tokens.get(v) != wtoken.token) {
2889 Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
2890 + " @ " + v + ", internal is " + wtoken.token + " @ " + m);
2896 Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
2900 AppWindowToken wtoken = mAppTokens.get(m);
2901 if (!wtoken.removed) {
2902 Slog.w(TAG, "Invalid internal token: " + wtoken.token + " @ " + m);
2908 boolean checkCallingPermission(String permission, String func) {
2909 // Quick check: if the calling permission is me, it's all okay.
2910 if (Binder.getCallingPid() == Process.myPid()) {
2914 if (mContext.checkCallingPermission(permission)
2915 == PackageManager.PERMISSION_GRANTED) {
2918 String msg = "Permission Denial: " + func + " from pid="
2919 + Binder.getCallingPid()
2920 + ", uid=" + Binder.getCallingUid()
2921 + " requires " + permission;
2926 AppWindowToken findAppWindowToken(IBinder token) {
2927 WindowToken wtoken = mTokenMap.get(token);
2928 if (wtoken == null) {
2931 return wtoken.appWindowToken;
2934 public void addWindowToken(IBinder token, int type) {
2935 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2936 "addWindowToken()")) {
2937 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2940 synchronized(mWindowMap) {
2941 WindowToken wtoken = mTokenMap.get(token);
2942 if (wtoken != null) {
2943 Slog.w(TAG, "Attempted to add existing input method token: " + token);
2946 wtoken = new WindowToken(token, type, true);
2947 mTokenMap.put(token, wtoken);
2948 mTokenList.add(wtoken);
2949 if (type == TYPE_WALLPAPER) {
2950 mWallpaperTokens.add(wtoken);
2955 public void removeWindowToken(IBinder token) {
2956 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2957 "removeWindowToken()")) {
2958 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2961 final long origId = Binder.clearCallingIdentity();
2962 synchronized(mWindowMap) {
2963 WindowToken wtoken = mTokenMap.remove(token);
2964 mTokenList.remove(wtoken);
2965 if (wtoken != null) {
2966 boolean delayed = false;
2967 if (!wtoken.hidden) {
2968 wtoken.hidden = true;
2970 final int N = wtoken.windows.size();
2971 boolean changed = false;
2973 for (int i=0; i<N; i++) {
2974 WindowState win = wtoken.windows.get(i);
2976 if (win.isAnimating()) {
2980 if (win.isVisibleNow()) {
2981 applyAnimationLocked(win,
2982 WindowManagerPolicy.TRANSIT_EXIT, false);
2983 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
2984 KeyWaiter.RETURN_NOTHING);
2990 mLayoutNeeded = true;
2991 performLayoutAndPlaceSurfacesLocked();
2992 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2996 mExitingTokens.add(wtoken);
2997 } else if (wtoken.windowType == TYPE_WALLPAPER) {
2998 mWallpaperTokens.remove(wtoken);
3003 Slog.w(TAG, "Attempted to remove non-existing token: " + token);
3006 Binder.restoreCallingIdentity(origId);
3009 public void addAppToken(int addPos, IApplicationToken token,
3010 int groupId, int requestedOrientation, boolean fullscreen) {
3011 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3013 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3016 synchronized(mWindowMap) {
3017 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3018 if (wtoken != null) {
3019 Slog.w(TAG, "Attempted to add existing app token: " + token);
3022 wtoken = new AppWindowToken(token);
3023 wtoken.groupId = groupId;
3024 wtoken.appFullscreen = fullscreen;
3025 wtoken.requestedOrientation = requestedOrientation;
3026 mAppTokens.add(addPos, wtoken);
3027 if (localLOGV) Slog.v(TAG, "Adding new app token: " + wtoken);
3028 mTokenMap.put(token.asBinder(), wtoken);
3029 mTokenList.add(wtoken);
3031 // Application tokens start out hidden.
3032 wtoken.hidden = true;
3033 wtoken.hiddenRequested = true;
3039 public void setAppGroupId(IBinder token, int groupId) {
3040 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3041 "setAppStartingIcon()")) {
3042 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3045 synchronized(mWindowMap) {
3046 AppWindowToken wtoken = findAppWindowToken(token);
3047 if (wtoken == null) {
3048 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
3051 wtoken.groupId = groupId;
3055 public int getOrientationFromWindowsLocked() {
3056 int pos = mWindows.size() - 1;
3058 WindowState wtoken = (WindowState) mWindows.get(pos);
3060 if (wtoken.mAppToken != null) {
3061 // We hit an application window. so the orientation will be determined by the
3062 // app window. No point in continuing further.
3063 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3065 if (!wtoken.isVisibleLw() || !wtoken.mPolicyVisibilityAfterAnim) {
3068 int req = wtoken.mAttrs.screenOrientation;
3069 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
3070 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
3076 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3079 public int getOrientationFromAppTokensLocked() {
3080 int pos = mAppTokens.size() - 1;
3082 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3083 boolean findingBehind = false;
3084 boolean haveGroup = false;
3085 boolean lastFullscreen = false;
3087 AppWindowToken wtoken = mAppTokens.get(pos);
3089 // if we're about to tear down this window and not seek for
3090 // the behind activity, don't use it for orientation
3092 && (!wtoken.hidden && wtoken.hiddenRequested)) {
3097 // We ignore any hidden applications on the top.
3098 if (wtoken.hiddenRequested || wtoken.willBeHidden) {
3102 curGroup = wtoken.groupId;
3103 lastOrientation = wtoken.requestedOrientation;
3104 } else if (curGroup != wtoken.groupId) {
3105 // If we have hit a new application group, and the bottom
3106 // of the previous group didn't explicitly say to use
3107 // the orientation behind it, and the last app was
3108 // full screen, then we'll stick with the
3109 // user's orientation.
3110 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
3111 && lastFullscreen) {
3112 return lastOrientation;
3115 int or = wtoken.requestedOrientation;
3116 // If this application is fullscreen, and didn't explicitly say
3117 // to use the orientation behind it, then just take whatever
3118 // orientation it has and ignores whatever is under it.
3119 lastFullscreen = wtoken.appFullscreen;
3121 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3124 // If this application has requested an explicit orientation,
3126 if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
3127 or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
3128 or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
3129 or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
3130 or == ActivityInfo.SCREEN_ORIENTATION_USER) {
3133 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
3135 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3138 public Configuration updateOrientationFromAppTokens(
3139 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3140 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3141 "updateOrientationFromAppTokens()")) {
3142 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3145 Configuration config = null;
3146 long ident = Binder.clearCallingIdentity();
3148 synchronized(mWindowMap) {
3149 if (updateOrientationFromAppTokensLocked()) {
3150 if (freezeThisOneIfNeeded != null) {
3151 AppWindowToken wtoken = findAppWindowToken(
3152 freezeThisOneIfNeeded);
3153 if (wtoken != null) {
3154 startAppFreezingScreenLocked(wtoken,
3155 ActivityInfo.CONFIG_ORIENTATION);
3158 config = computeNewConfigurationLocked();
3160 } else if (currentConfig != null) {
3161 // No obvious action we need to take, but if our current
3162 // state mismatches the activity maanager's, update it
3163 mTempConfiguration.setToDefaults();
3164 if (computeNewConfigurationLocked(mTempConfiguration)) {
3165 if (currentConfig.diff(mTempConfiguration) != 0) {
3166 mWaitingForConfig = true;
3167 mLayoutNeeded = true;
3168 startFreezingDisplayLocked();
3169 config = new Configuration(mTempConfiguration);
3175 Binder.restoreCallingIdentity(ident);
3180 * Determine the new desired orientation of the display, returning
3181 * a non-null new Configuration if it has changed from the current
3182 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL
3183 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3184 * SCREEN. This will typically be done for you if you call
3185 * sendNewConfiguration().
3187 * The orientation is computed from non-application windows first. If none of
3188 * the non-application windows specify orientation, the orientation is computed from
3189 * application tokens.
3190 * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3191 * android.os.IBinder)
3193 boolean updateOrientationFromAppTokensLocked() {
3194 if (mDisplayFrozen) {
3195 // If the display is frozen, some activities may be in the middle
3196 // of restarting, and thus have removed their old window. If the
3197 // window has the flag to hide the lock screen, then the lock screen
3198 // can re-appear and inflict its own orientation on us. Keep the
3199 // orientation stable until this all settles down.
3203 boolean changed = false;
3204 long ident = Binder.clearCallingIdentity();
3206 int req = computeForcedAppOrientationLocked();
3208 if (req != mForcedAppOrientation) {
3209 mForcedAppOrientation = req;
3210 //send a message to Policy indicating orientation change to take
3211 //action like disabling/enabling sensors etc.,
3212 mPolicy.setCurrentOrientationLw(req);
3213 if (setRotationUncheckedLocked(WindowManagerPolicy.USE_LAST_ROTATION,
3214 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE)) {
3221 Binder.restoreCallingIdentity(ident);
3225 int computeForcedAppOrientationLocked() {
3226 int req = getOrientationFromWindowsLocked();
3227 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
3228 req = getOrientationFromAppTokensLocked();
3233 public void setNewConfiguration(Configuration config) {
3234 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3235 "setNewConfiguration()")) {
3236 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3239 synchronized(mWindowMap) {
3240 mCurConfiguration = new Configuration(config);
3241 mWaitingForConfig = false;
3242 performLayoutAndPlaceSurfacesLocked();
3246 public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3247 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3248 "setAppOrientation()")) {
3249 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3252 synchronized(mWindowMap) {
3253 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3254 if (wtoken == null) {
3255 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
3259 wtoken.requestedOrientation = requestedOrientation;
3263 public int getAppOrientation(IApplicationToken token) {
3264 synchronized(mWindowMap) {
3265 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3266 if (wtoken == null) {
3267 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3270 return wtoken.requestedOrientation;
3274 public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3275 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3276 "setFocusedApp()")) {
3277 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3280 synchronized(mWindowMap) {
3281 boolean changed = false;
3282 if (token == null) {
3283 if (DEBUG_FOCUS) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
3284 changed = mFocusedApp != null;
3286 mKeyWaiter.tickle();
3288 AppWindowToken newFocus = findAppWindowToken(token);
3289 if (newFocus == null) {
3290 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
3293 changed = mFocusedApp != newFocus;
3294 mFocusedApp = newFocus;
3295 if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp);
3296 mKeyWaiter.tickle();
3299 if (moveFocusNow && changed) {
3300 final long origId = Binder.clearCallingIdentity();
3301 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3302 Binder.restoreCallingIdentity(origId);
3307 public void prepareAppTransition(int transit) {
3308 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3309 "prepareAppTransition()")) {
3310 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3313 synchronized(mWindowMap) {
3314 if (DEBUG_APP_TRANSITIONS) Slog.v(
3315 TAG, "Prepare app transition: transit=" + transit
3316 + " mNextAppTransition=" + mNextAppTransition);
3317 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
3318 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET
3319 || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) {
3320 mNextAppTransition = transit;
3321 } else if (transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
3322 && mNextAppTransition == WindowManagerPolicy.TRANSIT_TASK_CLOSE) {
3323 // Opening a new task always supersedes a close for the anim.
3324 mNextAppTransition = transit;
3325 } else if (transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
3326 && mNextAppTransition == WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE) {
3327 // Opening a new activity always supersedes a close for the anim.
3328 mNextAppTransition = transit;
3330 mAppTransitionReady = false;
3331 mAppTransitionTimeout = false;
3332 mStartingIconInTransition = false;
3333 mSkipAppTransitionAnimation = false;
3334 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
3335 mH.sendMessageDelayed(mH.obtainMessage(H.APP_TRANSITION_TIMEOUT),
3341 public int getPendingAppTransition() {
3342 return mNextAppTransition;
3345 public void overridePendingAppTransition(String packageName,
3346 int enterAnim, int exitAnim) {
3347 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
3348 mNextAppTransitionPackage = packageName;
3349 mNextAppTransitionEnter = enterAnim;
3350 mNextAppTransitionExit = exitAnim;
3354 public void executeAppTransition() {
3355 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3356 "executeAppTransition()")) {
3357 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3360 synchronized(mWindowMap) {
3361 if (DEBUG_APP_TRANSITIONS) {
3362 RuntimeException e = new RuntimeException("here");
3363 e.fillInStackTrace();
3364 Slog.w(TAG, "Execute app transition: mNextAppTransition="
3365 + mNextAppTransition, e);
3367 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
3368 mAppTransitionReady = true;
3369 final long origId = Binder.clearCallingIdentity();
3370 performLayoutAndPlaceSurfacesLocked();
3371 Binder.restoreCallingIdentity(origId);
3376 public void setAppStartingWindow(IBinder token, String pkg,
3377 int theme, CharSequence nonLocalizedLabel, int labelRes, int icon,
3378 IBinder transferFrom, boolean createIfNeeded) {
3379 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3380 "setAppStartingIcon()")) {
3381 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3384 synchronized(mWindowMap) {
3385 if (DEBUG_STARTING_WINDOW) Slog.v(
3386 TAG, "setAppStartingIcon: token=" + token + " pkg=" + pkg
3387 + " transferFrom=" + transferFrom);
3389 AppWindowToken wtoken = findAppWindowToken(token);
3390 if (wtoken == null) {
3391 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
3395 // If the display is frozen, we won't do anything until the
3396 // actual window is displayed so there is no reason to put in
3397 // the starting window.
3398 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
3402 if (wtoken.startingData != null) {
3406 if (transferFrom != null) {
3407 AppWindowToken ttoken = findAppWindowToken(transferFrom);
3408 if (ttoken != null) {
3409 WindowState startingWindow = ttoken.startingWindow;
3410 if (startingWindow != null) {
3411 if (mStartingIconInTransition) {
3412 // In this case, the starting icon has already
3413 // been displayed, so start letting windows get
3414 // shown immediately without any more transitions.
3415 mSkipAppTransitionAnimation = true;
3417 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
3418 "Moving existing starting from " + ttoken
3420 final long origId = Binder.clearCallingIdentity();
3422 // Transfer the starting window over to the new
3424 wtoken.startingData = ttoken.startingData;
3425 wtoken.startingView = ttoken.startingView;
3426 wtoken.startingWindow = startingWindow;
3427 ttoken.startingData = null;
3428 ttoken.startingView = null;
3429 ttoken.startingWindow = null;
3430 ttoken.startingMoved = true;
3431 startingWindow.mToken = wtoken;
3432 startingWindow.mRootToken = wtoken;
3433 startingWindow.mAppToken = wtoken;
3434 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
3435 "Removing starting window: " + startingWindow);
3436 mWindows.remove(startingWindow);
3437 ttoken.windows.remove(startingWindow);
3438 ttoken.allAppWindows.remove(startingWindow);
3439 addWindowToListInOrderLocked(startingWindow, true);
3441 // Propagate other interesting state between the
3442 // tokens. If the old token is displayed, we should
3443 // immediately force the new one to be displayed. If
3444 // it is animating, we need to move that animation to
3446 if (ttoken.allDrawn) {
3447 wtoken.allDrawn = true;
3449 if (ttoken.firstWindowDrawn) {
3450 wtoken.firstWindowDrawn = true;
3452 if (!ttoken.hidden) {
3453 wtoken.hidden = false;
3454 wtoken.hiddenRequested = false;
3455 wtoken.willBeHidden = false;
3457 if (wtoken.clientHidden != ttoken.clientHidden) {
3458 wtoken.clientHidden = ttoken.clientHidden;
3459 wtoken.sendAppVisibilityToClients();
3461 if (ttoken.animation != null) {
3462 wtoken.animation = ttoken.animation;
3463 wtoken.animating = ttoken.animating;
3464 wtoken.animLayerAdjustment = ttoken.animLayerAdjustment;
3465 ttoken.animation = null;
3466 ttoken.animLayerAdjustment = 0;
3467 wtoken.updateLayers();
3468 ttoken.updateLayers();
3471 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
3472 mLayoutNeeded = true;
3473 performLayoutAndPlaceSurfacesLocked();
3474 Binder.restoreCallingIdentity(origId);
3476 } else if (ttoken.startingData != null) {
3477 // The previous app was getting ready to show a
3478 // starting window, but hasn't yet done so. Steal it!
3479 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
3480 "Moving pending starting from " + ttoken
3482 wtoken.startingData = ttoken.startingData;
3483 ttoken.startingData = null;
3484 ttoken.startingMoved = true;
3485 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3486 // Note: we really want to do sendMessageAtFrontOfQueue() because we
3487 // want to process the message ASAP, before any other queued
3489 mH.sendMessageAtFrontOfQueue(m);
3495 // There is no existing starting window, and the caller doesn't
3496 // want us to create one, so that's it!
3497 if (!createIfNeeded) {
3501 // If this is a translucent or wallpaper window, then don't
3502 // show a starting window -- the current effect (a full-screen
3503 // opaque starting window that fades away to the real contents
3504 // when it is ready) does not work for this.
3506 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
3507 com.android.internal.R.styleable.Window);
3508 if (ent.array.getBoolean(
3509 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
3512 if (ent.array.getBoolean(
3513 com.android.internal.R.styleable.Window_windowIsFloating, false)) {
3516 if (ent.array.getBoolean(
3517 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
3522 mStartingIconInTransition = true;
3523 wtoken.startingData = new StartingData(
3524 pkg, theme, nonLocalizedLabel,
3526 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3527 // Note: we really want to do sendMessageAtFrontOfQueue() because we
3528 // want to process the message ASAP, before any other queued
3530 mH.sendMessageAtFrontOfQueue(m);
3534 public void setAppWillBeHidden(IBinder token) {
3535 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3536 "setAppWillBeHidden()")) {
3537 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3540 AppWindowToken wtoken;
3542 synchronized(mWindowMap) {
3543 wtoken = findAppWindowToken(token);
3544 if (wtoken == null) {
3545 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
3548 wtoken.willBeHidden = true;
3552 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
3553 boolean visible, int transit, boolean performLayout) {
3554 boolean delayed = false;
3556 if (wtoken.clientHidden == visible) {
3557 wtoken.clientHidden = !visible;
3558 wtoken.sendAppVisibilityToClients();
3561 wtoken.willBeHidden = false;
3562 if (wtoken.hidden == visible) {
3563 final int N = wtoken.allAppWindows.size();
3564 boolean changed = false;
3565 if (DEBUG_APP_TRANSITIONS) Slog.v(
3566 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
3567 + " performLayout=" + performLayout);
3569 boolean runningAppAnimation = false;
3571 if (transit != WindowManagerPolicy.TRANSIT_UNSET) {
3572 if (wtoken.animation == sDummyAnimation) {
3573 wtoken.animation = null;
3575 applyAnimationLocked(wtoken, lp, transit, visible);
3577 if (wtoken.animation != null) {
3578 delayed = runningAppAnimation = true;
3582 for (int i=0; i<N; i++) {
3583 WindowState win = wtoken.allAppWindows.get(i);
3584 if (win == wtoken.startingWindow) {
3588 if (win.isAnimating()) {
3592 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
3595 if (!win.isVisibleNow()) {
3596 if (!runningAppAnimation) {
3597 applyAnimationLocked(win,
3598 WindowManagerPolicy.TRANSIT_ENTER, true);
3602 } else if (win.isVisibleNow()) {
3603 if (!runningAppAnimation) {
3604 applyAnimationLocked(win,
3605 WindowManagerPolicy.TRANSIT_EXIT, false);
3607 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
3608 KeyWaiter.RETURN_NOTHING);
3613 wtoken.hidden = wtoken.hiddenRequested = !visible;
3615 unsetAppFreezingScreenLocked(wtoken, true, true);
3617 // If we are being set visible, and the starting window is
3618 // not yet displayed, then make sure it doesn't get displayed.
3619 WindowState swin = wtoken.startingWindow;
3620 if (swin != null && (swin.mDrawPending
3621 || swin.mCommitDrawPending)) {
3622 swin.mPolicyVisibility = false;
3623 swin.mPolicyVisibilityAfterAnim = false;
3627 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
3628 + ": hidden=" + wtoken.hidden + " hiddenRequested="
3629 + wtoken.hiddenRequested);
3632 mLayoutNeeded = true;
3633 if (performLayout) {
3634 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
3635 performLayoutAndPlaceSurfacesLocked();
3640 if (wtoken.animation != null) {
3647 public void setAppVisibility(IBinder token, boolean visible) {
3648 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3649 "setAppVisibility()")) {
3650 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3653 AppWindowToken wtoken;
3655 synchronized(mWindowMap) {
3656 wtoken = findAppWindowToken(token);
3657 if (wtoken == null) {
3658 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
3662 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
3663 RuntimeException e = null;
3664 if (!HIDE_STACK_CRAWLS) {
3665 e = new RuntimeException();
3666 e.fillInStackTrace();
3668 Slog.v(TAG, "setAppVisibility(" + token + ", " + visible
3669 + "): mNextAppTransition=" + mNextAppTransition
3670 + " hidden=" + wtoken.hidden
3671 + " hiddenRequested=" + wtoken.hiddenRequested, e);
3674 // If we are preparing an app transition, then delay changing
3675 // the visibility of this token until we execute that transition.
3676 if (!mDisplayFrozen && mPolicy.isScreenOn()
3677 && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
3678 // Already in requested state, don't do anything more.
3679 if (wtoken.hiddenRequested != visible) {
3682 wtoken.hiddenRequested = !visible;
3684 if (DEBUG_APP_TRANSITIONS) Slog.v(
3685 TAG, "Setting dummy animation on: " + wtoken);
3686 wtoken.setDummyAnimation();
3687 mOpeningApps.remove(wtoken);
3688 mClosingApps.remove(wtoken);
3689 wtoken.waitingToShow = wtoken.waitingToHide = false;
3690 wtoken.inPendingTransaction = true;
3692 mOpeningApps.add(wtoken);
3693 wtoken.startingDisplayed = false;
3694 wtoken.startingMoved = false;
3696 // If the token is currently hidden (should be the
3697 // common case), then we need to set up to wait for
3698 // its windows to be ready.
3699 if (wtoken.hidden) {
3700 wtoken.allDrawn = false;
3701 wtoken.waitingToShow = true;
3703 if (wtoken.clientHidden) {
3704 // In the case where we are making an app visible
3705 // but holding off for a transition, we still need
3706 // to tell the client to make its windows visible so
3707 // they get drawn. Otherwise, we will wait on
3708 // performing the transition until all windows have
3709 // been drawn, they never will be, and we are sad.
3710 wtoken.clientHidden = false;
3711 wtoken.sendAppVisibilityToClients();
3715 mClosingApps.add(wtoken);
3717 // If the token is currently visible (should be the
3718 // common case), then set up to wait for it to be hidden.
3719 if (!wtoken.hidden) {
3720 wtoken.waitingToHide = true;
3726 final long origId = Binder.clearCallingIdentity();
3727 setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_UNSET, true);
3728 wtoken.updateReportedVisibilityLocked();
3729 Binder.restoreCallingIdentity(origId);
3733 void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
3734 boolean unfreezeSurfaceNow, boolean force) {
3735 if (wtoken.freezingScreen) {
3736 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
3737 + " force=" + force);
3738 final int N = wtoken.allAppWindows.size();
3739 boolean unfrozeWindows = false;
3740 for (int i=0; i<N; i++) {
3741 WindowState w = wtoken.allAppWindows.get(i);
3742 if (w.mAppFreezing) {
3743 w.mAppFreezing = false;
3744 if (w.mSurface != null && !w.mOrientationChanging) {
3745 w.mOrientationChanging = true;
3747 unfrozeWindows = true;
3750 if (force || unfrozeWindows) {
3751 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
3752 wtoken.freezingScreen = false;
3753 mAppsFreezingScreen--;
3755 if (unfreezeSurfaceNow) {
3756 if (unfrozeWindows) {
3757 mLayoutNeeded = true;
3758 performLayoutAndPlaceSurfacesLocked();
3760 stopFreezingDisplayLocked();
3765 public void startAppFreezingScreenLocked(AppWindowToken wtoken,
3766 int configChanges) {
3767 if (DEBUG_ORIENTATION) {
3768 RuntimeException e = null;
3769 if (!HIDE_STACK_CRAWLS) {
3770 e = new RuntimeException();
3771 e.fillInStackTrace();
3773 Slog.i(TAG, "Set freezing of " + wtoken.appToken
3774 + ": hidden=" + wtoken.hidden + " freezing="
3775 + wtoken.freezingScreen, e);
3777 if (!wtoken.hiddenRequested) {
3778 if (!wtoken.freezingScreen) {
3779 wtoken.freezingScreen = true;
3780 mAppsFreezingScreen++;
3781 if (mAppsFreezingScreen == 1) {
3782 startFreezingDisplayLocked();
3783 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
3784 mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT),
3788 final int N = wtoken.allAppWindows.size();
3789 for (int i=0; i<N; i++) {
3790 WindowState w = wtoken.allAppWindows.get(i);
3791 w.mAppFreezing = true;
3796 public void startAppFreezingScreen(IBinder token, int configChanges) {
3797 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3798 "setAppFreezingScreen()")) {
3799 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3802 synchronized(mWindowMap) {
3803 if (configChanges == 0 && !mDisplayFrozen && mPolicy.isScreenOn()) {
3804 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
3808 AppWindowToken wtoken = findAppWindowToken(token);
3809 if (wtoken == null || wtoken.appToken == null) {
3810 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
3813 final long origId = Binder.clearCallingIdentity();
3814 startAppFreezingScreenLocked(wtoken, configChanges);
3815 Binder.restoreCallingIdentity(origId);
3819 public void stopAppFreezingScreen(IBinder token, boolean force) {
3820 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3821 "setAppFreezingScreen()")) {
3822 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3825 synchronized(mWindowMap) {
3826 AppWindowToken wtoken = findAppWindowToken(token);
3827 if (wtoken == null || wtoken.appToken == null) {
3830 final long origId = Binder.clearCallingIdentity();
3831 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
3832 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.freezingScreen);
3833 unsetAppFreezingScreenLocked(wtoken, true, force);
3834 Binder.restoreCallingIdentity(origId);
3838 public void removeAppToken(IBinder token) {
3839 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3840 "removeAppToken()")) {
3841 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3844 AppWindowToken wtoken = null;
3845 AppWindowToken startingToken = null;
3846 boolean delayed = false;
3848 final long origId = Binder.clearCallingIdentity();
3849 synchronized(mWindowMap) {
3850 WindowToken basewtoken = mTokenMap.remove(token);
3851 mTokenList.remove(basewtoken);
3852 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
3853 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
3854 delayed = setTokenVisibilityLocked(wtoken, null, false, WindowManagerPolicy.TRANSIT_UNSET, true);
3855 wtoken.inPendingTransaction = false;
3856 mOpeningApps.remove(wtoken);
3857 wtoken.waitingToShow = false;
3858 if (mClosingApps.contains(wtoken)) {
3860 } else if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
3861 mClosingApps.add(wtoken);
3862 wtoken.waitingToHide = true;
3865 if (DEBUG_APP_TRANSITIONS) Slog.v(
3866 TAG, "Removing app " + wtoken + " delayed=" + delayed
3867 + " animation=" + wtoken.animation
3868 + " animating=" + wtoken.animating);
3870 // set the token aside because it has an active animation to be finished
3871 mExitingAppTokens.add(wtoken);
3873 // Make sure there is no animation running on this token,
3874 // so any windows associated with it will be removed as
3875 // soon as their animations are complete
3876 wtoken.animation = null;
3877 wtoken.animating = false;
3879 mAppTokens.remove(wtoken);
3880 if (mLastEnterAnimToken == wtoken) {
3881 mLastEnterAnimToken = null;
3882 mLastEnterAnimParams = null;
3884 wtoken.removed = true;
3885 if (wtoken.startingData != null) {
3886 startingToken = wtoken;
3888 unsetAppFreezingScreenLocked(wtoken, true, true);
3889 if (mFocusedApp == wtoken) {
3890 if (DEBUG_FOCUS) Slog.v(TAG, "Removing focused app token:" + wtoken);
3892 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3893 mKeyWaiter.tickle();
3896 Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
3899 if (!delayed && wtoken != null) {
3900 wtoken.updateReportedVisibilityLocked();
3903 Binder.restoreCallingIdentity(origId);
3905 if (startingToken != null) {
3906 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Schedule remove starting "
3907 + startingToken + ": app token removed");
3908 Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken);
3913 private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
3914 final int NW = token.windows.size();
3915 for (int i=0; i<NW; i++) {
3916 WindowState win = token.windows.get(i);
3917 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
3918 mWindows.remove(win);
3919 int j = win.mChildWindows.size();
3922 WindowState cwin = (WindowState)win.mChildWindows.get(j);
3923 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
3924 "Tmp removing child window " + cwin);
3925 mWindows.remove(cwin);
3931 void dumpAppTokensLocked() {
3932 for (int i=mAppTokens.size()-1; i>=0; i--) {
3933 Slog.v(TAG, " #" + i + ": " + mAppTokens.get(i).token);
3937 void dumpWindowsLocked() {
3938 for (int i=mWindows.size()-1; i>=0; i--) {
3939 Slog.v(TAG, " #" + i + ": " + mWindows.get(i));
3943 private int findWindowOffsetLocked(int tokenPos) {
3944 final int NW = mWindows.size();
3946 if (tokenPos >= mAppTokens.size()) {
3950 WindowState win = (WindowState)mWindows.get(i);
3951 if (win.getAppToken() != null) {
3957 while (tokenPos > 0) {
3958 // Find the first app token below the new position that has
3959 // a window displayed.
3960 final AppWindowToken wtoken = mAppTokens.get(tokenPos-1);
3961 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ "
3962 + tokenPos + " -- " + wtoken.token);
3963 if (wtoken.sendingToBottom) {
3964 if (DEBUG_REORDER) Slog.v(TAG,
3965 "Skipping token -- currently sending to bottom");
3969 int i = wtoken.windows.size();
3972 WindowState win = wtoken.windows.get(i);
3973 int j = win.mChildWindows.size();
3976 WindowState cwin = (WindowState)win.mChildWindows.get(j);
3977 if (cwin.mSubLayer >= 0) {
3978 for (int pos=NW-1; pos>=0; pos--) {
3979 if (mWindows.get(pos) == cwin) {
3980 if (DEBUG_REORDER) Slog.v(TAG,
3981 "Found child win @" + (pos+1));
3987 for (int pos=NW-1; pos>=0; pos--) {
3988 if (mWindows.get(pos) == win) {
3989 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos+1));
4000 private final int reAddWindowLocked(int index, WindowState win) {
4001 final int NCW = win.mChildWindows.size();
4002 boolean added = false;
4003 for (int j=0; j<NCW; j++) {
4004 WindowState cwin = (WindowState)win.mChildWindows.get(j);
4005 if (!added && cwin.mSubLayer >= 0) {
4006 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
4007 + index + ": " + cwin);
4008 mWindows.add(index, win);
4012 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4013 + index + ": " + cwin);
4014 mWindows.add(index, cwin);
4018 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4019 + index + ": " + win);
4020 mWindows.add(index, win);
4026 private final int reAddAppWindowsLocked(int index, WindowToken token) {
4027 final int NW = token.windows.size();
4028 for (int i=0; i<NW; i++) {
4029 index = reAddWindowLocked(index, token.windows.get(i));
4034 public void moveAppToken(int index, IBinder token) {
4035 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4036 "moveAppToken()")) {
4037 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4040 synchronized(mWindowMap) {
4041 if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:");
4042 if (DEBUG_REORDER) dumpAppTokensLocked();
4043 final AppWindowToken wtoken = findAppWindowToken(token);
4044 if (wtoken == null || !mAppTokens.remove(wtoken)) {
4045 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
4046 + token + " (" + wtoken + ")");
4049 mAppTokens.add(index, wtoken);
4050 if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":");
4051 if (DEBUG_REORDER) dumpAppTokensLocked();
4053 final long origId = Binder.clearCallingIdentity();
4054 if (DEBUG_REORDER) Slog.v(TAG, "Removing windows in " + token + ":");
4055 if (DEBUG_REORDER) dumpWindowsLocked();
4056 if (tmpRemoveAppWindowsLocked(wtoken)) {
4057 if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:");
4058 if (DEBUG_REORDER) dumpWindowsLocked();
4059 reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken);
4060 if (DEBUG_REORDER) Slog.v(TAG, "Final window list:");
4061 if (DEBUG_REORDER) dumpWindowsLocked();
4062 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
4063 mLayoutNeeded = true;
4064 performLayoutAndPlaceSurfacesLocked();
4066 Binder.restoreCallingIdentity(origId);
4070 private void removeAppTokensLocked(List<IBinder> tokens) {
4071 // XXX This should be done more efficiently!
4072 // (take advantage of the fact that both lists should be
4073 // ordered in the same way.)
4074 int N = tokens.size();
4075 for (int i=0; i<N; i++) {
4076 IBinder token = tokens.get(i);
4077 final AppWindowToken wtoken = findAppWindowToken(token);
4078 if (!mAppTokens.remove(wtoken)) {
4079 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
4080 + token + " (" + wtoken + ")");
4087 private void moveAppWindowsLocked(AppWindowToken wtoken, int tokenPos,
4088 boolean updateFocusAndLayout) {
4089 // First remove all of the windows from the list.
4090 tmpRemoveAppWindowsLocked(wtoken);
4092 // Where to start adding?
4093 int pos = findWindowOffsetLocked(tokenPos);
4095 // And now add them back at the correct place.
4096 pos = reAddAppWindowsLocked(pos, wtoken);
4098 if (updateFocusAndLayout) {
4099 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
4100 assignLayersLocked();
4102 mLayoutNeeded = true;
4103 performLayoutAndPlaceSurfacesLocked();
4107 private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) {
4108 // First remove all of the windows from the list.
4109 final int N = tokens.size();
4111 for (i=0; i<N; i++) {
4112 WindowToken token = mTokenMap.get(tokens.get(i));
4113 if (token != null) {
4114 tmpRemoveAppWindowsLocked(token);
4118 // Where to start adding?
4119 int pos = findWindowOffsetLocked(tokenPos);
4121 // And now add them back at the correct place.
4122 for (i=0; i<N; i++) {
4123 WindowToken token = mTokenMap.get(tokens.get(i));
4124 if (token != null) {
4125 pos = reAddAppWindowsLocked(pos, token);
4129 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
4130 assignLayersLocked();
4132 mLayoutNeeded = true;
4133 performLayoutAndPlaceSurfacesLocked();
4138 public void moveAppTokensToTop(List<IBinder> tokens) {
4139 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4140 "moveAppTokensToTop()")) {
4141 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4144 final long origId = Binder.clearCallingIdentity();
4145 synchronized(mWindowMap) {
4146 removeAppTokensLocked(tokens);
4147 final int N = tokens.size();
4148 for (int i=0; i<N; i++) {
4149 AppWindowToken wt = findAppWindowToken(tokens.get(i));
4152 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
4153 mToTopApps.remove(wt);
4154 mToBottomApps.remove(wt);
4156 wt.sendingToBottom = false;
4157 wt.sendingToTop = true;
4162 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
4163 moveAppWindowsLocked(tokens, mAppTokens.size());
4166 Binder.restoreCallingIdentity(origId);
4169 public void moveAppTokensToBottom(List<IBinder> tokens) {
4170 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4171 "moveAppTokensToBottom()")) {
4172 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4175 final long origId = Binder.clearCallingIdentity();
4176 synchronized(mWindowMap) {
4177 removeAppTokensLocked(tokens);
4178 final int N = tokens.size();
4180 for (int i=0; i<N; i++) {
4181 AppWindowToken wt = findAppWindowToken(tokens.get(i));
4183 mAppTokens.add(pos, wt);
4184 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
4185 mToTopApps.remove(wt);
4186 mToBottomApps.remove(wt);
4187 mToBottomApps.add(i, wt);
4188 wt.sendingToTop = false;
4189 wt.sendingToBottom = true;
4195 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
4196 moveAppWindowsLocked(tokens, 0);
4199 Binder.restoreCallingIdentity(origId);
4202 // -------------------------------------------------------------
4203 // Misc IWindowSession methods
4204 // -------------------------------------------------------------
4206 private boolean shouldAllowDisableKeyguard()
4208 // We fail safe and prevent disabling keyguard in the unlikely event this gets
4209 // called before DevicePolicyManagerService has started.
4210 if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) {
4211 DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
4212 Context.DEVICE_POLICY_SERVICE);
4214 mAllowDisableKeyguard = dpm.getPasswordQuality(null)
4215 == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
4216 ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
4219 return mAllowDisableKeyguard == ALLOW_DISABLE_YES;
4222 public void disableKeyguard(IBinder token, String tag) {
4223 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
4224 != PackageManager.PERMISSION_GRANTED) {
4225 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4228 synchronized (mKeyguardTokenWatcher) {
4229 mKeyguardTokenWatcher.acquire(token, tag);
4233 public void reenableKeyguard(IBinder token) {
4234 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
4235 != PackageManager.PERMISSION_GRANTED) {
4236 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4239 synchronized (mKeyguardTokenWatcher) {
4240 mKeyguardTokenWatcher.release(token);
4242 if (!mKeyguardTokenWatcher.isAcquired()) {
4243 // If we are the last one to reenable the keyguard wait until
4244 // we have actually finished reenabling until returning.
4245 // It is possible that reenableKeyguard() can be called before
4246 // the previous disableKeyguard() is handled, in which case
4247 // neither mKeyguardTokenWatcher.acquired() or released() would
4248 // be called. In that case mKeyguardDisabled will be false here
4249 // and we have nothing to wait for.
4250 while (mKeyguardDisabled) {
4252 mKeyguardTokenWatcher.wait();
4253 } catch (InterruptedException e) {
4254 Thread.currentThread().interrupt();
4262 * @see android.app.KeyguardManager#exitKeyguardSecurely
4264 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
4265 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
4266 != PackageManager.PERMISSION_GRANTED) {
4267 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4269 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
4270 public void onKeyguardExitResult(boolean success) {
4272 callback.onKeyguardExitResult(success);
4273 } catch (RemoteException e) {
4274 // Client has died, we don't care.
4280 public boolean inKeyguardRestrictedInputMode() {
4281 return mPolicy.inKeyguardRestrictedKeyInputMode();
4284 public void closeSystemDialogs(String reason) {
4285 synchronized(mWindowMap) {
4286 for (int i=mWindows.size()-1; i>=0; i--) {
4287 WindowState w = (WindowState)mWindows.get(i);
4288 if (w.mSurface != null) {
4290 w.mClient.closeSystemDialogs(reason);
4291 } catch (RemoteException e) {
4298 static float fixScale(float scale) {
4299 if (scale < 0) scale = 0;
4300 else if (scale > 20) scale = 20;
4301 return Math.abs(scale);
4304 public void setAnimationScale(int which, float scale) {
4305 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4306 "setAnimationScale()")) {
4307 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
4310 if (scale < 0) scale = 0;
4311 else if (scale > 20) scale = 20;
4312 scale = Math.abs(scale);
4314 case 0: mWindowAnimationScale = fixScale(scale); break;
4315 case 1: mTransitionAnimationScale = fixScale(scale); break;
4319 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
4322 public void setAnimationScales(float[] scales) {
4323 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4324 "setAnimationScale()")) {
4325 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
4328 if (scales != null) {
4329 if (scales.length >= 1) {
4330 mWindowAnimationScale = fixScale(scales[0]);
4332 if (scales.length >= 2) {
4333 mTransitionAnimationScale = fixScale(scales[1]);
4338 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
4341 public float getAnimationScale(int which) {
4343 case 0: return mWindowAnimationScale;
4344 case 1: return mTransitionAnimationScale;
4349 public float[] getAnimationScales() {
4350 return new float[] { mWindowAnimationScale, mTransitionAnimationScale };
4353 public int getSwitchState(int sw) {
4354 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4355 "getSwitchState()")) {
4356 throw new SecurityException("Requires READ_INPUT_STATE permission");
4358 return KeyInputQueue.getSwitchState(sw);
4361 public int getSwitchStateForDevice(int devid, int sw) {
4362 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4363 "getSwitchStateForDevice()")) {
4364 throw new SecurityException("Requires READ_INPUT_STATE permission");
4366 return KeyInputQueue.getSwitchState(devid, sw);
4369 public int getScancodeState(int sw) {
4370 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4371 "getScancodeState()")) {
4372 throw new SecurityException("Requires READ_INPUT_STATE permission");
4374 return mQueue.getScancodeState(sw);
4377 public int getScancodeStateForDevice(int devid, int sw) {
4378 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4379 "getScancodeStateForDevice()")) {
4380 throw new SecurityException("Requires READ_INPUT_STATE permission");
4382 return mQueue.getScancodeState(devid, sw);
4385 public int getTrackballScancodeState(int sw) {
4386 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4387 "getTrackballScancodeState()")) {
4388 throw new SecurityException("Requires READ_INPUT_STATE permission");
4390 return mQueue.getTrackballScancodeState(sw);
4393 public int getDPadScancodeState(int sw) {
4394 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4395 "getDPadScancodeState()")) {
4396 throw new SecurityException("Requires READ_INPUT_STATE permission");
4398 return mQueue.getDPadScancodeState(sw);
4401 public int getKeycodeState(int sw) {
4402 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4403 "getKeycodeState()")) {
4404 throw new SecurityException("Requires READ_INPUT_STATE permission");
4406 return mQueue.getKeycodeState(sw);
4409 public int getKeycodeStateForDevice(int devid, int sw) {
4410 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4411 "getKeycodeStateForDevice()")) {
4412 throw new SecurityException("Requires READ_INPUT_STATE permission");
4414 return mQueue.getKeycodeState(devid, sw);
4417 public int getTrackballKeycodeState(int sw) {
4418 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4419 "getTrackballKeycodeState()")) {
4420 throw new SecurityException("Requires READ_INPUT_STATE permission");
4422 return mQueue.getTrackballKeycodeState(sw);
4425 public int getDPadKeycodeState(int sw) {
4426 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4427 "getDPadKeycodeState()")) {
4428 throw new SecurityException("Requires READ_INPUT_STATE permission");
4430 return mQueue.getDPadKeycodeState(sw);
4433 public boolean hasKeys(int[] keycodes, boolean[] keyExists) {
4434 return KeyInputQueue.hasKeys(keycodes, keyExists);
4437 public void enableScreenAfterBoot() {
4438 synchronized(mWindowMap) {
4439 if (mSystemBooted) {
4442 mSystemBooted = true;
4445 performEnableScreen();
4448 public void enableScreenIfNeededLocked() {
4449 if (mDisplayEnabled) {
4452 if (!mSystemBooted) {
4455 mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN));
4458 public void performEnableScreen() {
4459 synchronized(mWindowMap) {
4460 if (mDisplayEnabled) {
4463 if (!mSystemBooted) {
4467 // Don't enable the screen until all existing windows
4469 final int N = mWindows.size();
4470 for (int i=0; i<N; i++) {
4471 WindowState w = (WindowState)mWindows.get(i);
4472 if (w.isVisibleLw() && !w.mObscured
4473 && (w.mOrientationChanging || !w.isDrawnLw())) {
4478 mDisplayEnabled = true;
4480 Slog.i(TAG, "ENABLING SCREEN!");
4481 StringWriter sw = new StringWriter();
4482 PrintWriter pw = new PrintWriter(sw);
4483 this.dump(null, pw, null);
4484 Slog.i(TAG, sw.toString());
4487 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
4488 if (surfaceFlinger != null) {
4489 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
4490 Parcel data = Parcel.obtain();
4491 data.writeInterfaceToken("android.ui.ISurfaceComposer");
4492 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,
4496 } catch (RemoteException ex) {
4497 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
4501 mPolicy.enableScreenAfterBoot();
4503 // Make sure the last requested orientation has been applied.
4504 setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false,
4505 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
4508 public void setInTouchMode(boolean mode) {
4509 synchronized(mWindowMap) {
4510 mInTouchMode = mode;
4514 public void setRotation(int rotation,
4515 boolean alwaysSendConfiguration, int animFlags) {
4516 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
4518 throw new SecurityException("Requires SET_ORIENTATION permission");
4521 setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags);
4524 public void setRotationUnchecked(int rotation,
4525 boolean alwaysSendConfiguration, int animFlags) {
4526 if(DEBUG_ORIENTATION) Slog.v(TAG,
4527 "alwaysSendConfiguration set to "+alwaysSendConfiguration);
4529 long origId = Binder.clearCallingIdentity();
4531 synchronized(mWindowMap) {
4532 changed = setRotationUncheckedLocked(rotation, animFlags);
4535 if (changed || alwaysSendConfiguration) {
4536 sendNewConfiguration();
4539 Binder.restoreCallingIdentity(origId);
4543 * Apply a new rotation to the screen, respecting the requests of
4544 * applications. Use WindowManagerPolicy.USE_LAST_ROTATION to simply
4545 * re-evaluate the desired rotation.
4547 * Returns null if the rotation has been changed. In this case YOU
4548 * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN.
4550 public boolean setRotationUncheckedLocked(int rotation, int animFlags) {
4552 if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {
4553 rotation = mRequestedRotation;
4555 mRequestedRotation = rotation;
4556 mLastRotationFlags = animFlags;
4558 if (DEBUG_ORIENTATION) Slog.v(TAG, "Overwriting rotation value from " + rotation);
4559 rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation,
4560 mRotation, mDisplayEnabled);
4561 if (DEBUG_ORIENTATION) Slog.v(TAG, "new rotation is set to " + rotation);
4562 changed = mDisplayEnabled && mRotation != rotation;
4565 if (DEBUG_ORIENTATION) Slog.v(TAG,
4566 "Rotation changed to " + rotation
4567 + " from " + mRotation
4568 + " (forceApp=" + mForcedAppOrientation
4569 + ", req=" + mRequestedRotation + ")");
4570 mRotation = rotation;
4571 mWindowsFreezingScreen = true;
4572 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
4573 mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
4575 mWaitingForConfig = true;
4576 mLayoutNeeded = true;
4577 startFreezingDisplayLocked();
4578 Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
4579 mQueue.setOrientation(rotation);
4580 if (mDisplayEnabled) {
4581 Surface.setOrientation(0, rotation, animFlags);
4583 for (int i=mWindows.size()-1; i>=0; i--) {
4584 WindowState w = (WindowState)mWindows.get(i);
4585 if (w.mSurface != null) {
4586 w.mOrientationChanging = true;
4589 for (int i=mRotationWatchers.size()-1; i>=0; i--) {
4591 mRotationWatchers.get(i).onRotationChanged(rotation);
4592 } catch (RemoteException e) {
4600 public int getRotation() {
4604 public int watchRotation(IRotationWatcher watcher) {
4605 final IBinder watcherBinder = watcher.asBinder();
4606 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
4607 public void binderDied() {
4608 synchronized (mWindowMap) {
4609 for (int i=0; i<mRotationWatchers.size(); i++) {
4610 if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
4611 IRotationWatcher removed = mRotationWatchers.remove(i);
4612 if (removed != null) {
4613 removed.asBinder().unlinkToDeath(this, 0);
4622 synchronized (mWindowMap) {
4624 watcher.asBinder().linkToDeath(dr, 0);
4625 mRotationWatchers.add(watcher);
4626 } catch (RemoteException e) {
4627 // Client died, no cleanup needed.
4635 * Starts the view server on the specified port.
4637 * @param port The port to listener to.
4639 * @return True if the server was successfully started, false otherwise.
4641 * @see com.android.server.ViewServer
4642 * @see com.android.server.ViewServer#VIEW_SERVER_DEFAULT_PORT
4644 public boolean startViewServer(int port) {
4645 if (isSystemSecure()) {
4649 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
4657 if (mViewServer != null) {
4658 if (!mViewServer.isRunning()) {
4660 return mViewServer.start();
4661 } catch (IOException e) {
4662 Slog.w(TAG, "View server did not start");
4669 mViewServer = new ViewServer(this, port);
4670 return mViewServer.start();
4671 } catch (IOException e) {
4672 Slog.w(TAG, "View server did not start");
4677 private boolean isSystemSecure() {
4678 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
4679 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
4683 * Stops the view server if it exists.
4685 * @return True if the server stopped, false if it wasn't started or
4686 * couldn't be stopped.
4688 * @see com.android.server.ViewServer
4690 public boolean stopViewServer() {
4691 if (isSystemSecure()) {
4695 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
4699 if (mViewServer != null) {
4700 return mViewServer.stop();
4706 * Indicates whether the view server is running.
4708 * @return True if the server is running, false otherwise.
4710 * @see com.android.server.ViewServer
4712 public boolean isViewServerRunning() {
4713 if (isSystemSecure()) {
4717 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
4721 return mViewServer != null && mViewServer.isRunning();
4725 * Lists all availble windows in the system. The listing is written in the
4726 * specified Socket's output stream with the following syntax:
4727 * windowHashCodeInHexadecimal windowName
4728 * Each line of the ouput represents a different window.
4730 * @param client The remote client to send the listing to.
4731 * @return False if an error occured, true otherwise.
4733 boolean viewServerListWindows(Socket client) {
4734 if (isSystemSecure()) {
4738 boolean result = true;
4741 synchronized (mWindowMap) {
4742 windows = new Object[mWindows.size()];
4743 //noinspection unchecked
4744 windows = mWindows.toArray(windows);
4747 BufferedWriter out = null;
4749 // Any uncaught exception will crash the system process
4751 OutputStream clientStream = client.getOutputStream();
4752 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4754 final int count = windows.length;
4755 for (int i = 0; i < count; i++) {
4756 final WindowState w = (WindowState) windows[i];
4757 out.write(Integer.toHexString(System.identityHashCode(w)));
4759 out.append(w.mAttrs.getTitle());
4763 out.write("DONE.\n");
4765 } catch (Exception e) {
4771 } catch (IOException e) {
4781 * Sends a command to a target window. The result of the command, if any, will be
4782 * written in the output stream of the specified socket.
4784 * The parameters must follow this syntax:
4785 * windowHashcode extra
4787 * Where XX is the length in characeters of the windowTitle.
4789 * The first parameter is the target window. The window with the specified hashcode
4790 * will be the target. If no target can be found, nothing happens. The extra parameters
4791 * will be delivered to the target window and as parameters to the command itself.
4793 * @param client The remote client to sent the result, if any, to.
4794 * @param command The command to execute.
4795 * @param parameters The command parameters.
4797 * @return True if the command was successfully delivered, false otherwise. This does
4798 * not indicate whether the command itself was successful.
4800 boolean viewServerWindowCommand(Socket client, String command, String parameters) {
4801 if (isSystemSecure()) {
4805 boolean success = true;
4807 Parcel reply = null;
4809 // Any uncaught exception will crash the system process
4811 // Find the hashcode of the window
4812 int index = parameters.indexOf(' ');
4814 index = parameters.length();
4816 final String code = parameters.substring(0, index);
4817 int hashCode = (int) Long.parseLong(code, 16);
4819 // Extract the command's parameter after the window description
4820 if (index < parameters.length()) {
4821 parameters = parameters.substring(index + 1);
4826 final WindowManagerService.WindowState window = findWindow(hashCode);
4827 if (window == null) {
4831 data = Parcel.obtain();
4832 data.writeInterfaceToken("android.view.IWindow");
4833 data.writeString(command);
4834 data.writeString(parameters);
4836 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
4838 reply = Parcel.obtain();
4840 final IBinder binder = window.mClient.asBinder();
4841 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
4842 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
4844 reply.readException();
4846 } catch (Exception e) {
4847 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
4853 if (reply != null) {
4861 private WindowState findWindow(int hashCode) {
4862 if (hashCode == -1) {
4863 return getFocusedWindow();
4866 synchronized (mWindowMap) {
4867 final ArrayList windows = mWindows;
4868 final int count = windows.size();
4870 for (int i = 0; i < count; i++) {
4871 WindowState w = (WindowState) windows.get(i);
4872 if (System.identityHashCode(w) == hashCode) {
4882 * Instruct the Activity Manager to fetch the current configuration and broadcast
4883 * that to config-changed listeners if appropriate.
4885 void sendNewConfiguration() {
4887 mActivityManager.updateConfiguration(null);
4888 } catch (RemoteException e) {
4892 public Configuration computeNewConfiguration() {
4893 synchronized (mWindowMap) {
4894 return computeNewConfigurationLocked();
4898 Configuration computeNewConfigurationLocked() {
4899 Configuration config = new Configuration();
4900 if (!computeNewConfigurationLocked(config)) {
4906 boolean computeNewConfigurationLocked(Configuration config) {
4907 if (mDisplay == null) {
4910 mQueue.getInputConfiguration(config);
4912 // Use the effective "visual" dimensions based on current rotation
4913 final boolean rotated = (mRotation == Surface.ROTATION_90
4914 || mRotation == Surface.ROTATION_270);
4915 final int dw = rotated ? mInitialDisplayHeight : mInitialDisplayWidth;
4916 final int dh = rotated ? mInitialDisplayWidth : mInitialDisplayHeight;
4918 int orientation = Configuration.ORIENTATION_SQUARE;
4920 orientation = Configuration.ORIENTATION_PORTRAIT;
4921 } else if (dw > dh) {
4922 orientation = Configuration.ORIENTATION_LANDSCAPE;
4924 config.orientation = orientation;
4926 DisplayMetrics dm = new DisplayMetrics();
4927 mDisplay.getMetrics(dm);
4928 CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame);
4930 if (mScreenLayout == Configuration.SCREENLAYOUT_SIZE_UNDEFINED) {
4931 // Note we only do this once because at this point we don't
4932 // expect the screen to change in this way at runtime, and want
4933 // to avoid all of this computation for every config change.
4936 if (longSize < shortSize) {
4938 longSize = shortSize;
4941 longSize = (int)(longSize/dm.density);
4942 shortSize = (int)(shortSize/dm.density);
4944 // These semi-magic numbers define our compatibility modes for
4945 // applications with different screens. Don't change unless you
4946 // make sure to test lots and lots of apps!
4947 if (longSize < 470) {
4948 // This is shorter than an HVGA normal density screen (which
4949 // is 480 pixels on its long side).
4950 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL
4951 | Configuration.SCREENLAYOUT_LONG_NO;
4953 // Is this a large screen?
4954 if (longSize > 640 && shortSize >= 480) {
4955 // VGA or larger screens at medium density are the point
4956 // at which we consider it to be a large screen.
4957 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
4959 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL;
4961 // If this screen is wider than normal HVGA, or taller
4962 // than FWVGA, then for old apps we want to run in size
4963 // compatibility mode.
4964 if (shortSize > 321 || longSize > 570) {
4965 mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
4969 // Is this a long screen?
4970 if (((longSize*3)/5) >= (shortSize-1)) {
4971 // Anything wider than WVGA (5:3) is considering to be long.
4972 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_YES;
4974 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_NO;
4978 config.screenLayout = mScreenLayout;
4980 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
4981 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
4982 mPolicy.adjustConfigurationLw(config);
4986 // -------------------------------------------------------------
4987 // Input Events and Focus Management
4988 // -------------------------------------------------------------
4990 private final void wakeupIfNeeded(WindowState targetWin, int eventType) {
4991 long curTime = SystemClock.uptimeMillis();
4993 if (eventType == TOUCH_EVENT || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) {
4994 if (mLastTouchEventType == eventType &&
4995 (curTime - mLastUserActivityCallTime) < MIN_TIME_BETWEEN_USERACTIVITIES) {
4998 mLastUserActivityCallTime = curTime;
4999 mLastTouchEventType = eventType;
5002 if (targetWin == null
5003 || targetWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
5004 mPowerManager.userActivity(curTime, false, eventType, false);
5008 // tells if it's a cheek event or not -- this function is stateful
5009 private static final int EVENT_NONE = 0;
5010 private static final int EVENT_UNKNOWN = 0;
5011 private static final int EVENT_CHEEK = 0;
5012 private static final int EVENT_IGNORE_DURATION = 300; // ms
5013 private static final float CHEEK_THRESHOLD = 0.6f;
5014 private int mEventState = EVENT_NONE;
5015 private float mEventSize;
5017 private int eventType(MotionEvent ev) {
5018 float size = ev.getSize();
5019 switch (ev.getAction()) {
5020 case MotionEvent.ACTION_DOWN:
5022 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_EVENT;
5023 case MotionEvent.ACTION_UP:
5024 if (size > mEventSize) mEventSize = size;
5025 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_UP_EVENT;
5026 case MotionEvent.ACTION_MOVE:
5027 final int N = ev.getHistorySize();
5028 if (size > mEventSize) mEventSize = size;
5029 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
5030 for (int i=0; i<N; i++) {
5031 size = ev.getHistoricalSize(i);
5032 if (size > mEventSize) mEventSize = size;
5033 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
5035 if (ev.getEventTime() < ev.getDownTime() + EVENT_IGNORE_DURATION) {
5038 return LONG_TOUCH_EVENT;
5047 * @return Returns true if event was dispatched, false if it was dropped for any reason
5049 private int dispatchPointer(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
5050 if (DEBUG_INPUT || WindowManagerPolicy.WATCH_POINTER) Slog.v(TAG,
5051 "dispatchPointer " + ev);
5053 if (MEASURE_LATENCY) {
5054 lt.sample("3 Wait for last dispatch ", System.nanoTime() - qev.whenNano);
5057 Object targetObj = mKeyWaiter.waitForNextEventTarget(null, qev,
5058 ev, true, false, pid, uid);
5060 if (MEASURE_LATENCY) {
5061 lt.sample("3 Last dispatch finished ", System.nanoTime() - qev.whenNano);
5064 int action = ev.getAction();
5066 if (action == MotionEvent.ACTION_UP) {
5067 // let go of our target
5068 mKeyWaiter.mMotionTarget = null;
5069 mPowerManager.logPointerUpEvent();
5070 } else if (action == MotionEvent.ACTION_DOWN) {
5071 mPowerManager.logPointerDownEvent();
5074 if (targetObj == null) {
5075 // In this case we are either dropping the event, or have received
5076 // a move or up without a down. It is common to receive move
5077 // events in such a way, since this means the user is moving the
5078 // pointer without actually pressing down. All other cases should
5079 // be atypical, so let's log them.
5080 if (action != MotionEvent.ACTION_MOVE) {
5081 Slog.w(TAG, "No window to dispatch pointer action " + ev.getAction());
5083 synchronized (mWindowMap) {
5084 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true);
5087 mQueue.recycleEvent(qev);
5090 return INJECT_FAILED;
5092 if (targetObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
5093 synchronized (mWindowMap) {
5094 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true);
5097 mQueue.recycleEvent(qev);
5100 return INJECT_SUCCEEDED;
5103 WindowState target = (WindowState)targetObj;
5105 final long eventTime = ev.getEventTime();
5106 final long eventTimeNano = ev.getEventTimeNano();
5108 //Slog.i(TAG, "Sending " + ev + " to " + target);
5110 if (uid != 0 && uid != target.mSession.mUid) {
5111 if (mContext.checkPermission(
5112 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5113 != PackageManager.PERMISSION_GRANTED) {
5114 Slog.w(TAG, "Permission denied: injecting pointer event from pid "
5115 + pid + " uid " + uid + " to window " + target
5116 + " owned by uid " + target.mSession.mUid);
5118 mQueue.recycleEvent(qev);
5121 return INJECT_NO_PERMISSION;
5125 if (MEASURE_LATENCY) {
5126 lt.sample("4 in dispatchPointer ", System.nanoTime() - eventTimeNano);
5129 if ((target.mAttrs.flags &
5130 WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) != 0) {
5131 //target wants to ignore fat touch events
5132 boolean cheekPress = mPolicy.isCheekPressedAgainstScreen(ev);
5133 //explicit flag to return without processing event further
5134 boolean returnFlag = false;
5135 if((action == MotionEvent.ACTION_DOWN)) {
5142 if(action == MotionEvent.ACTION_UP) {
5144 //earlier even was invalid doesnt matter if current up is cheekpress or not
5147 } else if(cheekPress) {
5148 //cancel the earlier event
5149 ev.setAction(MotionEvent.ACTION_CANCEL);
5150 action = MotionEvent.ACTION_CANCEL;
5152 } else if(action == MotionEvent.ACTION_MOVE) {
5155 //an invalid down followed by 0 or moves(valid or invalid)
5156 //a valid down, invalid move, more moves. want to ignore till up
5158 } else if(cheekPress) {
5159 //valid down followed by invalid moves
5160 //an invalid move have to cancel earlier action
5161 ev.setAction(MotionEvent.ACTION_CANCEL);
5162 action = MotionEvent.ACTION_CANCEL;
5163 if (DEBUG_INPUT) Slog.v(TAG, "Sending cancel for invalid ACTION_MOVE");
5164 //note that the subsequent invalid moves will not get here
5172 mQueue.recycleEvent(qev);
5175 return INJECT_FAILED;
5179 // Enable this for testing the "right" value
5180 if (false && action == MotionEvent.ACTION_DOWN) {
5181 int max_events_per_sec = 35;
5183 max_events_per_sec = Integer.parseInt(SystemProperties
5184 .get("windowsmgr.max_events_per_sec"));
5185 if (max_events_per_sec < 1) {
5186 max_events_per_sec = 35;
5188 } catch (NumberFormatException e) {
5190 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
5194 * Throttle events to minimize CPU usage when there's a flood of events
5195 * e.g. constant contact with the screen
5197 if (action == MotionEvent.ACTION_MOVE) {
5198 long nextEventTime = mLastTouchEventTime + mMinWaitTimeBetweenTouchEvents;
5199 long now = SystemClock.uptimeMillis();
5200 if (now < nextEventTime) {
5202 Thread.sleep(nextEventTime - now);
5203 } catch (InterruptedException e) {
5205 mLastTouchEventTime = nextEventTime;
5207 mLastTouchEventTime = now;
5211 if (MEASURE_LATENCY) {
5212 lt.sample("5 in dispatchPointer ", System.nanoTime() - eventTimeNano);
5215 synchronized(mWindowMap) {
5216 if (!target.isVisibleLw()) {
5217 // During this motion dispatch, the target window has become
5219 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), false);
5221 mQueue.recycleEvent(qev);
5224 return INJECT_SUCCEEDED;
5227 if (qev != null && action == MotionEvent.ACTION_MOVE) {
5228 mKeyWaiter.bindTargetWindowLocked(target,
5229 KeyWaiter.RETURN_PENDING_POINTER, qev);
5232 if (action == MotionEvent.ACTION_DOWN) {
5233 WindowState out = mKeyWaiter.mOutsideTouchTargets;
5235 MotionEvent oev = MotionEvent.obtain(ev);
5236 oev.setAction(MotionEvent.ACTION_OUTSIDE);
5238 final Rect frame = out.mFrame;
5239 oev.offsetLocation(-(float)frame.left, -(float)frame.top);
5241 out.mClient.dispatchPointer(oev, eventTime, false);
5242 } catch (android.os.RemoteException e) {
5243 Slog.i(TAG, "WINDOW DIED during outside motion dispatch: " + out);
5245 oev.offsetLocation((float)frame.left, (float)frame.top);
5246 out = out.mNextOutsideTouch;
5247 } while (out != null);
5248 mKeyWaiter.mOutsideTouchTargets = null;
5252 dispatchPointerElsewhereLocked(target, null, ev, ev.getEventTime(), false);
5254 final Rect frame = target.mFrame;
5255 ev.offsetLocation(-(float)frame.left, -(float)frame.top);
5256 mKeyWaiter.bindTargetWindowLocked(target);
5260 // finally offset the event to the target's coordinate system and
5261 // dispatch the event.
5263 if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) {
5264 Slog.v(TAG, "Delivering pointer " + qev + " to " + target);
5267 if (MEASURE_LATENCY) {
5268 lt.sample("6 before svr->client ipc ", System.nanoTime() - eventTimeNano);
5271 target.mClient.dispatchPointer(ev, eventTime, true);
5273 if (MEASURE_LATENCY) {
5274 lt.sample("7 after svr->client ipc ", System.nanoTime() - eventTimeNano);
5276 return INJECT_SUCCEEDED;
5277 } catch (android.os.RemoteException e) {
5278 Slog.i(TAG, "WINDOW DIED during motion dispatch: " + target);
5279 mKeyWaiter.mMotionTarget = null;
5281 removeWindow(target.mSession, target.mClient);
5282 } catch (java.util.NoSuchElementException ex) {
5283 // This will happen if the window has already been
5287 return INJECT_FAILED;
5291 * @return Returns true if event was dispatched, false if it was dropped for any reason
5293 private int dispatchTrackball(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
5294 if (DEBUG_INPUT) Slog.v(
5295 TAG, "dispatchTrackball [" + ev.getAction() +"] <" + ev.getX() + ", " + ev.getY() + ">");
5297 Object focusObj = mKeyWaiter.waitForNextEventTarget(null, qev,
5298 ev, false, false, pid, uid);
5299 if (focusObj == null) {
5300 Slog.w(TAG, "No focus window, dropping trackball: " + ev);
5302 mQueue.recycleEvent(qev);
5305 return INJECT_FAILED;
5307 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
5309 mQueue.recycleEvent(qev);
5312 return INJECT_SUCCEEDED;
5315 WindowState focus = (WindowState)focusObj;
5317 if (uid != 0 && uid != focus.mSession.mUid) {
5318 if (mContext.checkPermission(
5319 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5320 != PackageManager.PERMISSION_GRANTED) {
5321 Slog.w(TAG, "Permission denied: injecting key event from pid "
5322 + pid + " uid " + uid + " to window " + focus
5323 + " owned by uid " + focus.mSession.mUid);
5325 mQueue.recycleEvent(qev);
5328 return INJECT_NO_PERMISSION;
5332 final long eventTime = ev.getEventTime();
5334 synchronized(mWindowMap) {
5335 if (qev != null && ev.getAction() == MotionEvent.ACTION_MOVE) {
5336 mKeyWaiter.bindTargetWindowLocked(focus,
5337 KeyWaiter.RETURN_PENDING_TRACKBALL, qev);
5338 // We don't deliver movement events to the client, we hold
5339 // them and wait for them to call back.
5342 mKeyWaiter.bindTargetWindowLocked(focus);
5347 focus.mClient.dispatchTrackball(ev, eventTime, true);
5348 return INJECT_SUCCEEDED;
5349 } catch (android.os.RemoteException e) {
5350 Slog.i(TAG, "WINDOW DIED during key dispatch: " + focus);
5352 removeWindow(focus.mSession, focus.mClient);
5353 } catch (java.util.NoSuchElementException ex) {
5354 // This will happen if the window has already been
5359 return INJECT_FAILED;
5363 * @return Returns true if event was dispatched, false if it was dropped for any reason
5365 private int dispatchKey(KeyEvent event, int pid, int uid) {
5366 if (DEBUG_INPUT) Slog.v(TAG, "Dispatch key: " + event);
5368 Object focusObj = mKeyWaiter.waitForNextEventTarget(event, null,
5369 null, false, false, pid, uid);
5370 if (focusObj == null) {
5371 Slog.w(TAG, "No focus window, dropping: " + event);
5372 return INJECT_FAILED;
5374 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
5375 return INJECT_SUCCEEDED;
5378 // Okay we have finished waiting for the last event to be processed.
5379 // First off, if this is a repeat event, check to see if there is
5380 // a corresponding up event in the queue. If there is, we will
5381 // just drop the repeat, because it makes no sense to repeat after
5382 // the user has released a key. (This is especially important for
5384 if (event.getRepeatCount() > 0 && mQueue.hasKeyUpEvent(event)) {
5385 return INJECT_SUCCEEDED;
5388 WindowState focus = (WindowState)focusObj;
5390 if (DEBUG_INPUT) Slog.v(
5391 TAG, "Dispatching to " + focus + ": " + event);
5393 if (uid != 0 && uid != focus.mSession.mUid) {
5394 if (mContext.checkPermission(
5395 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5396 != PackageManager.PERMISSION_GRANTED) {
5397 Slog.w(TAG, "Permission denied: injecting key event from pid "
5398 + pid + " uid " + uid + " to window " + focus
5399 + " owned by uid " + focus.mSession.mUid);
5400 return INJECT_NO_PERMISSION;
5404 synchronized(mWindowMap) {
5405 mKeyWaiter.bindTargetWindowLocked(focus);
5408 // NOSHIP extra state logging
5409 mKeyWaiter.recordDispatchState(event, focus);
5413 if (DEBUG_INPUT || DEBUG_FOCUS) {
5414 Slog.v(TAG, "Delivering key " + event.getKeyCode()
5417 focus.mClient.dispatchKey(event);
5418 return INJECT_SUCCEEDED;
5419 } catch (android.os.RemoteException e) {
5420 Slog.i(TAG, "WINDOW DIED during key dispatch: " + focus);
5422 removeWindow(focus.mSession, focus.mClient);
5423 } catch (java.util.NoSuchElementException ex) {
5424 // This will happen if the window has already been
5429 return INJECT_FAILED;
5432 public void pauseKeyDispatching(IBinder _token) {
5433 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5434 "pauseKeyDispatching()")) {
5435 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
5438 synchronized (mWindowMap) {
5439 WindowToken token = mTokenMap.get(_token);
5440 if (token != null) {
5441 mKeyWaiter.pauseDispatchingLocked(token);
5446 public void resumeKeyDispatching(IBinder _token) {
5447 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5448 "resumeKeyDispatching()")) {
5449 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
5452 synchronized (mWindowMap) {
5453 WindowToken token = mTokenMap.get(_token);
5454 if (token != null) {
5455 mKeyWaiter.resumeDispatchingLocked(token);
5460 public void setEventDispatching(boolean enabled) {
5461 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5462 "resumeKeyDispatching()")) {
5463 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
5466 synchronized (mWindowMap) {
5467 mKeyWaiter.setEventDispatchingLocked(enabled);
5472 * Injects a keystroke event into the UI.
5474 * @param ev A motion event describing the keystroke action. (Be sure to use
5475 * {@link SystemClock#uptimeMillis()} as the timebase.)
5476 * @param sync If true, wait for the event to be completed before returning to the caller.
5477 * @return Returns true if event was dispatched, false if it was dropped for any reason
5479 public boolean injectKeyEvent(KeyEvent ev, boolean sync) {
5480 long downTime = ev.getDownTime();
5481 long eventTime = ev.getEventTime();
5483 int action = ev.getAction();
5484 int code = ev.getKeyCode();
5485 int repeatCount = ev.getRepeatCount();
5486 int metaState = ev.getMetaState();
5487 int deviceId = ev.getDeviceId();
5488 int scancode = ev.getScanCode();
5490 if (eventTime == 0) eventTime = SystemClock.uptimeMillis();
5491 if (downTime == 0) downTime = eventTime;
5493 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
5494 deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM);
5496 final int pid = Binder.getCallingPid();
5497 final int uid = Binder.getCallingUid();
5498 final long ident = Binder.clearCallingIdentity();
5499 final int result = dispatchKey(newEvent, pid, uid);
5501 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
5503 Binder.restoreCallingIdentity(ident);
5505 case INJECT_NO_PERMISSION:
5506 throw new SecurityException(
5507 "Injecting to another application requires INJECT_EVENTS permission");
5508 case INJECT_SUCCEEDED:
5515 * Inject a pointer (touch) event into the UI.
5517 * @param ev A motion event describing the pointer (touch) action. (As noted in
5518 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
5519 * {@link SystemClock#uptimeMillis()} as the timebase.)
5520 * @param sync If true, wait for the event to be completed before returning to the caller.
5521 * @return Returns true if event was dispatched, false if it was dropped for any reason
5523 public boolean injectPointerEvent(MotionEvent ev, boolean sync) {
5524 final int pid = Binder.getCallingPid();
5525 final int uid = Binder.getCallingUid();
5526 final long ident = Binder.clearCallingIdentity();
5527 final int result = dispatchPointer(null, ev, pid, uid);
5529 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
5531 Binder.restoreCallingIdentity(ident);
5533 case INJECT_NO_PERMISSION:
5534 throw new SecurityException(
5535 "Injecting to another application requires INJECT_EVENTS permission");
5536 case INJECT_SUCCEEDED:
5543 * Inject a trackball (navigation device) event into the UI.
5545 * @param ev A motion event describing the trackball action. (As noted in
5546 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
5547 * {@link SystemClock#uptimeMillis()} as the timebase.)
5548 * @param sync If true, wait for the event to be completed before returning to the caller.
5549 * @return Returns true if event was dispatched, false if it was dropped for any reason
5551 public boolean injectTrackballEvent(MotionEvent ev, boolean sync) {
5552 final int pid = Binder.getCallingPid();
5553 final int uid = Binder.getCallingUid();
5554 final long ident = Binder.clearCallingIdentity();
5555 final int result = dispatchTrackball(null, ev, pid, uid);
5557 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
5559 Binder.restoreCallingIdentity(ident);
5561 case INJECT_NO_PERMISSION:
5562 throw new SecurityException(
5563 "Injecting to another application requires INJECT_EVENTS permission");
5564 case INJECT_SUCCEEDED:
5570 private WindowState getFocusedWindow() {
5571 synchronized (mWindowMap) {
5572 return getFocusedWindowLocked();
5576 private WindowState getFocusedWindowLocked() {
5577 return mCurrentFocus;
5581 * This class holds the state for dispatching key events. This state
5582 * is protected by the KeyWaiter instance, NOT by the window lock. You
5583 * can be holding the main window lock while acquire the KeyWaiter lock,
5584 * but not the other way around.
5586 final class KeyWaiter {
5588 public class DispatchState {
5589 private KeyEvent event;
5590 private WindowState focus;
5592 private WindowState lastWin;
5593 private IBinder lastBinder;
5594 private boolean finished;
5595 private boolean gotFirstWindow;
5596 private boolean eventDispatching;
5597 private long timeToSwitch;
5598 private boolean wasFrozen;
5599 private boolean focusPaused;
5600 private WindowState curFocus;
5602 DispatchState(KeyEvent theEvent, WindowState theFocus) {
5605 time = System.currentTimeMillis();
5606 // snapshot KeyWaiter state
5608 lastBinder = mLastBinder;
5609 finished = mFinished;
5610 gotFirstWindow = mGotFirstWindow;
5611 eventDispatching = mEventDispatching;
5612 timeToSwitch = mTimeToSwitch;
5613 wasFrozen = mWasFrozen;
5614 curFocus = mCurrentFocus;
5615 // cache the paused state at ctor time as well
5616 if (theFocus == null || theFocus.mToken == null) {
5617 focusPaused = false;
5619 focusPaused = theFocus.mToken.paused;
5623 public String toString() {
5624 return "{{" + event + " to " + focus + " @ " + time
5625 + " lw=" + lastWin + " lb=" + lastBinder
5626 + " fin=" + finished + " gfw=" + gotFirstWindow
5627 + " ed=" + eventDispatching + " tts=" + timeToSwitch
5628 + " wf=" + wasFrozen + " fp=" + focusPaused
5629 + " mcf=" + curFocus + "}}";
5632 private DispatchState mDispatchState = null;
5633 public void recordDispatchState(KeyEvent theEvent, WindowState theFocus) {
5634 mDispatchState = new DispatchState(theEvent, theFocus);
5638 public static final int RETURN_NOTHING = 0;
5639 public static final int RETURN_PENDING_POINTER = 1;
5640 public static final int RETURN_PENDING_TRACKBALL = 2;
5642 final Object SKIP_TARGET_TOKEN = new Object();
5643 final Object CONSUMED_EVENT_TOKEN = new Object();
5645 private WindowState mLastWin = null;
5646 private IBinder mLastBinder = null;
5647 private boolean mFinished = true;
5648 private boolean mGotFirstWindow = false;
5649 private boolean mEventDispatching = true;
5650 private long mTimeToSwitch = 0;
5651 /* package */ boolean mWasFrozen = false;
5653 // Target of Motion events
5654 WindowState mMotionTarget;
5656 // Windows above the target who would like to receive an "outside"
5657 // touch event for any down events outside of them.
5658 WindowState mOutsideTouchTargets;
5661 * Wait for the last event dispatch to complete, then find the next
5662 * target that should receive the given event and wait for that one
5663 * to be ready to receive it.
5665 Object waitForNextEventTarget(KeyEvent nextKey, QueuedEvent qev,
5666 MotionEvent nextMotion, boolean isPointerEvent,
5667 boolean failIfTimeout, int callingPid, int callingUid) {
5668 long startTime = SystemClock.uptimeMillis();
5669 long keyDispatchingTimeout = 5 * 1000;
5673 // Figure out which window we care about. It is either the
5674 // last window we are waiting to have process the event or,
5675 // if none, then the next window we think the event should go
5676 // to. Note: we retrieve mLastWin outside of the lock, so
5677 // it may change before we lock. Thus we must check it again.
5678 WindowState targetWin = mLastWin;
5679 boolean targetIsNew = targetWin == null;
5680 if (DEBUG_INPUT) Slog.v(
5681 TAG, "waitForLastKey: mFinished=" + mFinished +
5682 ", mLastWin=" + mLastWin);
5684 Object target = findTargetWindow(nextKey, qev, nextMotion,
5685 isPointerEvent, callingPid, callingUid);
5686 if (target == SKIP_TARGET_TOKEN) {
5687 // The user has pressed a special key, and we are
5688 // dropping all pending events before it.
5689 if (DEBUG_INPUT) Slog.v(TAG, "Skipping: " + nextKey
5690 + " " + nextMotion);
5693 if (target == CONSUMED_EVENT_TOKEN) {
5694 if (DEBUG_INPUT) Slog.v(TAG, "Consumed: " + nextKey
5695 + " " + nextMotion);
5698 targetWin = (WindowState)target;
5701 AppWindowToken targetApp = null;
5703 // Now: is it okay to send the next event to this window?
5704 synchronized (this) {
5705 // First: did we come here based on the last window not
5706 // being null, but it changed by the time we got here?
5707 // If so, try again.
5708 if (!targetIsNew && mLastWin == null) {
5712 // We never dispatch events if not finished with the
5713 // last one, or the display is frozen.
5714 if (mFinished && !mDisplayFrozen) {
5715 // If event dispatching is disabled, then we
5716 // just consume the events.
5717 if (!mEventDispatching) {
5718 if (DEBUG_INPUT) Slog.v(TAG,
5719 "Skipping event; dispatching disabled: "
5720 + nextKey + " " + nextMotion);
5723 if (targetWin != null) {
5724 // If this is a new target, and that target is not
5725 // paused or unresponsive, then all looks good to
5726 // handle the event.
5727 if (targetIsNew && !targetWin.mToken.paused) {
5731 // If we didn't find a target window, and there is no
5732 // focused app window, then just eat the events.
5733 } else if (mFocusedApp == null) {
5734 if (DEBUG_INPUT) Slog.v(TAG,
5735 "Skipping event; no focused app: "
5736 + nextKey + " " + nextMotion);
5741 if (DEBUG_INPUT) Slog.v(
5742 TAG, "Waiting for last key in " + mLastBinder
5743 + " target=" + targetWin
5744 + " mFinished=" + mFinished
5745 + " mDisplayFrozen=" + mDisplayFrozen
5746 + " targetIsNew=" + targetIsNew
5748 + (targetWin != null ? targetWin.mToken.paused : false)
5749 + " mFocusedApp=" + mFocusedApp
5750 + " mCurrentFocus=" + mCurrentFocus);
5752 targetApp = targetWin != null
5753 ? targetWin.mAppToken : mFocusedApp;
5755 long curTimeout = keyDispatchingTimeout;
5756 if (mTimeToSwitch != 0) {
5757 long now = SystemClock.uptimeMillis();
5758 if (mTimeToSwitch <= now) {
5759 // If an app switch key has been pressed, and we have
5760 // waited too long for the current app to finish
5761 // processing keys, then wait no more!
5762 doFinishedKeyLocked(false);
5765 long switchTimeout = mTimeToSwitch - now;
5766 if (curTimeout > switchTimeout) {
5767 curTimeout = switchTimeout;
5772 // after that continue
5773 // processing keys, so we don't get stuck.
5774 if (DEBUG_INPUT) Slog.v(
5775 TAG, "Waiting for key dispatch: " + curTimeout);
5777 if (DEBUG_INPUT) Slog.v(TAG, "Finished waiting @"
5778 + SystemClock.uptimeMillis() + " startTime="
5779 + startTime + " switchTime=" + mTimeToSwitch
5780 + " target=" + targetWin + " mLW=" + mLastWin
5781 + " mLB=" + mLastBinder + " fin=" + mFinished
5782 + " mCurrentFocus=" + mCurrentFocus);
5783 } catch (InterruptedException e) {
5787 // If we were frozen during configuration change, restart the
5788 // timeout checks from now; otherwise look at whether we timed
5789 // out before awakening.
5794 waitedFor = SystemClock.uptimeMillis() - startTime;
5797 if (waitedFor >= keyDispatchingTimeout && mTimeToSwitch == 0) {
5798 IApplicationToken at = null;
5799 synchronized (this) {
5800 Slog.w(TAG, "Key dispatching timed out sending to " +
5801 (targetWin != null ? targetWin.mAttrs.getTitle()
5802 : "<null>: no window ready for key dispatch"));
5804 Slog.w(TAG, "Previous dispatch state: " + mDispatchState);
5805 Slog.w(TAG, "Current dispatch state: " +
5806 new DispatchState(nextKey, targetWin));
5809 if (targetWin != null) {
5810 at = targetWin.getAppToken();
5811 } else if (targetApp != null) {
5812 at = targetApp.appToken;
5816 boolean abort = true;
5819 long timeout = at.getKeyDispatchingTimeout();
5820 if (timeout > waitedFor) {
5821 // we did not wait the proper amount of time for this application.
5822 // set the timeout to be the real timeout and wait again.
5823 keyDispatchingTimeout = timeout - waitedFor;
5826 abort = at.keyDispatchingTimedOut();
5828 } catch (RemoteException ex) {
5832 synchronized (this) {
5833 if (abort && (mLastWin == targetWin || targetWin == null)) {
5835 if (mLastWin != null) {
5836 if (DEBUG_INPUT) Slog.v(TAG,
5837 "Window " + mLastWin +
5838 " timed out on key input");
5839 if (mLastWin.mToken.paused) {
5840 Slog.w(TAG, "Un-pausing dispatching to this window");
5841 mLastWin.mToken.paused = false;
5844 if (mMotionTarget == targetWin) {
5845 mMotionTarget = null;
5849 if (failIfTimeout || targetWin == null) {
5853 Slog.w(TAG, "Continuing to wait for key to be dispatched");
5854 startTime = SystemClock.uptimeMillis();
5861 Object findTargetWindow(KeyEvent nextKey, QueuedEvent qev,
5862 MotionEvent nextMotion, boolean isPointerEvent,
5863 int callingPid, int callingUid) {
5864 mOutsideTouchTargets = null;
5866 if (nextKey != null) {
5867 // Find the target window for a normal key event.
5868 final int keycode = nextKey.getKeyCode();
5869 final int repeatCount = nextKey.getRepeatCount();
5870 final boolean down = nextKey.getAction() != KeyEvent.ACTION_UP;
5871 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(keycode);
5874 if (callingUid == 0 ||
5875 mContext.checkPermission(
5876 android.Manifest.permission.INJECT_EVENTS,
5877 callingPid, callingUid)
5878 == PackageManager.PERMISSION_GRANTED) {
5879 mPolicy.interceptKeyTi(null, keycode,
5880 nextKey.getMetaState(), down, repeatCount,
5881 nextKey.getFlags());
5883 Slog.w(TAG, "Event timeout during app switch: dropping "
5885 return SKIP_TARGET_TOKEN;
5888 // System.out.println("##### [" + SystemClock.uptimeMillis() + "] WindowManagerService.dispatchKey(" + keycode + ", " + down + ", " + repeatCount + ")");
5890 WindowState focus = null;
5891 synchronized(mWindowMap) {
5892 focus = getFocusedWindowLocked();
5895 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
5897 if (callingUid == 0 ||
5898 (focus != null && callingUid == focus.mSession.mUid) ||
5899 mContext.checkPermission(
5900 android.Manifest.permission.INJECT_EVENTS,
5901 callingPid, callingUid)
5902 == PackageManager.PERMISSION_GRANTED) {
5903 if (mPolicy.interceptKeyTi(focus,
5904 keycode, nextKey.getMetaState(), down, repeatCount,
5905 nextKey.getFlags())) {
5906 return CONSUMED_EVENT_TOKEN;
5912 } else if (!isPointerEvent) {
5913 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(-1);
5915 Slog.w(TAG, "Event timeout during app switch: dropping trackball "
5917 return SKIP_TARGET_TOKEN;
5920 WindowState focus = null;
5921 synchronized(mWindowMap) {
5922 focus = getFocusedWindowLocked();
5925 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
5929 if (nextMotion == null) {
5930 return SKIP_TARGET_TOKEN;
5933 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(
5934 KeyEvent.KEYCODE_UNKNOWN);
5936 Slog.w(TAG, "Event timeout during app switch: dropping pointer "
5938 return SKIP_TARGET_TOKEN;
5941 // Find the target window for a pointer event.
5942 int action = nextMotion.getAction();
5943 final float xf = nextMotion.getX();
5944 final float yf = nextMotion.getY();
5945 final long eventTime = nextMotion.getEventTime();
5947 final boolean screenWasOff = qev != null
5948 && (qev.flags&WindowManagerPolicy.FLAG_BRIGHT_HERE) != 0;
5950 WindowState target = null;
5952 synchronized(mWindowMap) {
5953 synchronized (this) {
5954 if (action == MotionEvent.ACTION_DOWN) {
5955 if (mMotionTarget != null) {
5956 // this is weird, we got a pen down, but we thought it was
5958 // XXX: We should probably send an ACTION_UP to the current
5960 Slog.w(TAG, "Pointer down received while already down in: "
5962 mMotionTarget = null;
5965 // ACTION_DOWN is special, because we need to lock next events to
5966 // the window we'll land onto.
5967 final int x = (int)xf;
5968 final int y = (int)yf;
5970 final ArrayList windows = mWindows;
5971 final int N = windows.size();
5972 WindowState topErrWindow = null;
5973 final Rect tmpRect = mTempRect;
5974 for (int i=N-1; i>=0; i--) {
5975 WindowState child = (WindowState)windows.get(i);
5976 //Slog.i(TAG, "Checking dispatch to: " + child);
5977 final int flags = child.mAttrs.flags;
5978 if ((flags & WindowManager.LayoutParams.FLAG_SYSTEM_ERROR) != 0) {
5979 if (topErrWindow == null) {
5980 topErrWindow = child;
5983 if (!child.isVisibleLw()) {
5984 //Slog.i(TAG, "Not visible!");
5987 if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
5988 //Slog.i(TAG, "Not touchable!");
5989 if ((flags & WindowManager.LayoutParams
5990 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
5991 child.mNextOutsideTouch = mOutsideTouchTargets;
5992 mOutsideTouchTargets = child;
5996 tmpRect.set(child.mFrame);
5997 if (child.mTouchableInsets == ViewTreeObserver
5998 .InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT) {
5999 // The touch is inside of the window if it is
6000 // inside the frame, AND the content part of that
6001 // frame that was given by the application.
6002 tmpRect.left += child.mGivenContentInsets.left;
6003 tmpRect.top += child.mGivenContentInsets.top;
6004 tmpRect.right -= child.mGivenContentInsets.right;
6005 tmpRect.bottom -= child.mGivenContentInsets.bottom;
6006 } else if (child.mTouchableInsets == ViewTreeObserver
6007 .InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE) {
6008 // The touch is inside of the window if it is
6009 // inside the frame, AND the visible part of that
6010 // frame that was given by the application.
6011 tmpRect.left += child.mGivenVisibleInsets.left;
6012 tmpRect.top += child.mGivenVisibleInsets.top;
6013 tmpRect.right -= child.mGivenVisibleInsets.right;
6014 tmpRect.bottom -= child.mGivenVisibleInsets.bottom;
6016 final int touchFlags = flags &
6017 (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6018 |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
6019 if (tmpRect.contains(x, y) || touchFlags == 0) {
6020 //Slog.i(TAG, "Using this target!");
6021 if (!screenWasOff || (flags &
6022 WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING) != 0) {
6023 mMotionTarget = child;
6025 //Slog.i(TAG, "Waking, skip!");
6026 mMotionTarget = null;
6031 if ((flags & WindowManager.LayoutParams
6032 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
6033 child.mNextOutsideTouch = mOutsideTouchTargets;
6034 mOutsideTouchTargets = child;
6035 //Slog.i(TAG, "Adding to outside target list: " + child);
6039 // if there's an error window but it's not accepting
6040 // focus (typically because it is not yet visible) just
6041 // wait for it -- any other focused window may in fact
6043 if (topErrWindow != null && mMotionTarget != topErrWindow) {
6044 mMotionTarget = null;
6048 target = mMotionTarget;
6052 wakeupIfNeeded(target, eventType(nextMotion));
6054 // Pointer events are a little different -- if there isn't a
6055 // target found for any event, then just drop it.
6056 return target != null ? target : SKIP_TARGET_TOKEN;
6059 boolean checkShouldDispatchKey(int keycode) {
6060 synchronized (this) {
6061 if (mPolicy.isAppSwitchKeyTqTiLwLi(keycode)) {
6065 if (mTimeToSwitch != 0
6066 && mTimeToSwitch < SystemClock.uptimeMillis()) {
6073 void bindTargetWindowLocked(WindowState win,
6074 int pendingWhat, QueuedEvent pendingMotion) {
6075 synchronized (this) {
6076 bindTargetWindowLockedLocked(win, pendingWhat, pendingMotion);
6080 void bindTargetWindowLocked(WindowState win) {
6081 synchronized (this) {
6082 bindTargetWindowLockedLocked(win, RETURN_NOTHING, null);
6086 void bindTargetWindowLockedLocked(WindowState win,
6087 int pendingWhat, QueuedEvent pendingMotion) {
6089 mLastBinder = win.mClient.asBinder();
6091 if (pendingMotion != null) {
6092 final Session s = win.mSession;
6093 if (pendingWhat == RETURN_PENDING_POINTER) {
6094 releasePendingPointerLocked(s);
6095 s.mPendingPointerMove = pendingMotion;
6096 s.mPendingPointerWindow = win;
6097 if (DEBUG_INPUT) Slog.v(TAG,
6098 "bindTargetToWindow " + s.mPendingPointerMove);
6099 } else if (pendingWhat == RETURN_PENDING_TRACKBALL) {
6100 releasePendingTrackballLocked(s);
6101 s.mPendingTrackballMove = pendingMotion;
6102 s.mPendingTrackballWindow = win;
6107 void releasePendingPointerLocked(Session s) {
6108 if (DEBUG_INPUT) Slog.v(TAG,
6109 "releasePendingPointer " + s.mPendingPointerMove);
6110 if (s.mPendingPointerMove != null) {
6111 mQueue.recycleEvent(s.mPendingPointerMove);
6112 s.mPendingPointerMove = null;
6116 void releasePendingTrackballLocked(Session s) {
6117 if (s.mPendingTrackballMove != null) {
6118 mQueue.recycleEvent(s.mPendingTrackballMove);
6119 s.mPendingTrackballMove = null;
6123 MotionEvent finishedKey(Session session, IWindow client, boolean force,
6125 if (DEBUG_INPUT) Slog.v(
6126 TAG, "finishedKey: client=" + client + ", force=" + force);
6128 if (client == null) {
6132 MotionEvent res = null;
6133 QueuedEvent qev = null;
6134 WindowState win = null;
6136 synchronized (this) {
6137 if (DEBUG_INPUT) Slog.v(
6138 TAG, "finishedKey: client=" + client.asBinder()
6139 + ", force=" + force + ", last=" + mLastBinder
6140 + " (token=" + (mLastWin != null ? mLastWin.mToken : null) + ")");
6142 if (returnWhat == RETURN_PENDING_POINTER) {
6143 qev = session.mPendingPointerMove;
6144 win = session.mPendingPointerWindow;
6145 session.mPendingPointerMove = null;
6146 session.mPendingPointerWindow = null;
6147 } else if (returnWhat == RETURN_PENDING_TRACKBALL) {
6148 qev = session.mPendingTrackballMove;
6149 win = session.mPendingTrackballWindow;
6150 session.mPendingTrackballMove = null;
6151 session.mPendingTrackballWindow = null;
6154 if (mLastBinder == client.asBinder()) {
6155 if (DEBUG_INPUT) Slog.v(
6156 TAG, "finishedKey: last paused="
6157 + ((mLastWin != null) ? mLastWin.mToken.paused : "null"));
6158 if (mLastWin != null && (!mLastWin.mToken.paused || force
6159 || !mEventDispatching)) {
6160 doFinishedKeyLocked(true);
6162 // Make sure to wake up anyone currently waiting to
6163 // dispatch a key, so they can re-evaluate their
6164 // current situation.
6171 res = (MotionEvent)qev.event;
6172 if (DEBUG_INPUT) Slog.v(TAG,
6173 "Returning pending motion: " + res);
6174 mQueue.recycleEvent(qev);
6175 if (win != null && returnWhat == RETURN_PENDING_POINTER) {
6176 res.offsetLocation(-win.mFrame.left, -win.mFrame.top);
6181 if (res != null && returnWhat == RETURN_PENDING_POINTER) {
6182 synchronized (mWindowMap) {
6183 dispatchPointerElsewhereLocked(win, win, res, res.getEventTime(), false);
6191 synchronized (this) {
6196 void handleNewWindowLocked(WindowState newWindow) {
6197 if (!newWindow.canReceiveKeys()) {
6200 synchronized (this) {
6201 if (DEBUG_INPUT) Slog.v(
6202 TAG, "New key dispatch window: win="
6203 + newWindow.mClient.asBinder()
6204 + ", last=" + mLastBinder
6205 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
6206 + "), finished=" + mFinished + ", paused="
6207 + newWindow.mToken.paused);
6209 // Displaying a window implicitly causes dispatching to
6210 // be unpaused. (This is to protect against bugs if someone
6211 // pauses dispatching but forgets to resume.)
6212 newWindow.mToken.paused = false;
6214 mGotFirstWindow = true;
6216 if ((newWindow.mAttrs.flags & FLAG_SYSTEM_ERROR) != 0) {
6217 if (DEBUG_INPUT) Slog.v(TAG,
6218 "New SYSTEM_ERROR window; resetting state");
6221 mMotionTarget = null;
6223 } else if (mLastWin != null) {
6224 // If the new window is above the window we are
6225 // waiting on, then stop waiting and let key dispatching
6226 // start on the new guy.
6227 if (DEBUG_INPUT) Slog.v(
6228 TAG, "Last win layer=" + mLastWin.mLayer
6229 + ", new win layer=" + newWindow.mLayer);
6230 if (newWindow.mLayer >= mLastWin.mLayer) {
6231 // The new window is above the old; finish pending input to the last
6232 // window and start directing it to the new one.
6233 mLastWin.mToken.paused = false;
6234 doFinishedKeyLocked(false); // does a notifyAll()
6239 // Now that we've put a new window state in place, make the event waiter
6240 // take notice and retarget its attentions.
6245 void pauseDispatchingLocked(WindowToken token) {
6248 if (DEBUG_INPUT) Slog.v(TAG, "Pausing WindowToken " + token);
6249 token.paused = true;
6252 if (mLastWin != null && !mFinished && mLastWin.mBaseLayer <= layer) {
6255 if (mLastWin == null) {
6256 Slog.i(TAG, "Key dispatching not paused: no last window.");
6257 } else if (mFinished) {
6258 Slog.i(TAG, "Key dispatching not paused: finished last key.");
6260 Slog.i(TAG, "Key dispatching not paused: window in higher layer.");
6267 void resumeDispatchingLocked(WindowToken token) {
6268 synchronized (this) {
6270 if (DEBUG_INPUT) Slog.v(
6271 TAG, "Resuming WindowToken " + token
6272 + ", last=" + mLastBinder
6273 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
6274 + "), finished=" + mFinished + ", paused="
6276 token.paused = false;
6277 if (mLastWin != null && mLastWin.mToken == token && mFinished) {
6278 doFinishedKeyLocked(false);
6286 void setEventDispatchingLocked(boolean enabled) {
6287 synchronized (this) {
6288 mEventDispatching = enabled;
6293 void appSwitchComing() {
6294 synchronized (this) {
6295 // Don't wait for more than .5 seconds for app to finish
6296 // processing the pending events.
6297 long now = SystemClock.uptimeMillis() + 500;
6298 if (DEBUG_INPUT) Slog.v(TAG, "appSwitchComing: " + now);
6299 if (mTimeToSwitch == 0 || now < mTimeToSwitch) {
6300 mTimeToSwitch = now;
6306 private final void doFinishedKeyLocked(boolean force) {
6307 if (mLastWin != null) {
6308 releasePendingPointerLocked(mLastWin.mSession);
6309 releasePendingTrackballLocked(mLastWin.mSession);
6312 if (force || mLastWin == null || !mLastWin.mToken.paused
6313 || !mLastWin.isVisibleLw()) {
6314 // If the current window has been paused, we aren't -really-
6315 // finished... so let the waiters still wait.
6324 private class KeyQ extends KeyInputQueue
6325 implements KeyInputQueue.FilterCallback {
6326 PowerManager.WakeLock mHoldingScreen;
6329 super(mContext, WindowManagerService.this);
6330 PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
6331 mHoldingScreen = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
6332 "KEEP_SCREEN_ON_FLAG");
6333 mHoldingScreen.setReferenceCounted(false);
6337 boolean preprocessEvent(InputDevice device, RawInputEvent event) {
6338 if (mPolicy.preprocessInputEventTq(event)) {
6342 switch (event.type) {
6343 case RawInputEvent.EV_KEY: {
6346 if (event.keycode == KeyEvent.KEYCODE_G) {
6347 if (event.value != 0) {
6349 mPolicy.screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
6353 if (event.keycode == KeyEvent.KEYCODE_D) {
6354 if (event.value != 0) {
6362 boolean screenIsOff = !mPowerManager.isScreenOn();
6363 boolean screenIsDim = !mPowerManager.isScreenBright();
6364 int actions = mPolicy.interceptKeyTq(event, !screenIsOff);
6366 if ((actions & WindowManagerPolicy.ACTION_GO_TO_SLEEP) != 0) {
6367 mPowerManager.goToSleep(event.when);
6371 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6374 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6376 if ((actions & WindowManagerPolicy.ACTION_POKE_USER_ACTIVITY) != 0) {
6377 mPowerManager.userActivity(event.when, false,
6378 LocalPowerManager.BUTTON_EVENT, false);
6381 if ((actions & WindowManagerPolicy.ACTION_PASS_TO_USER) != 0) {
6382 if (event.value != 0 && mPolicy.isAppSwitchKeyTqTiLwLi(event.keycode)) {
6384 mKeyWaiter.appSwitchComing();
6392 case RawInputEvent.EV_REL: {
6393 boolean screenIsOff = !mPowerManager.isScreenOn();
6394 boolean screenIsDim = !mPowerManager.isScreenBright();
6396 if (!mPolicy.isWakeRelMovementTq(event.deviceId,
6397 device.classes, event)) {
6398 //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey");
6401 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6404 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6409 case RawInputEvent.EV_ABS: {
6410 boolean screenIsOff = !mPowerManager.isScreenOn();
6411 boolean screenIsDim = !mPowerManager.isScreenBright();
6413 if (!mPolicy.isWakeAbsMovementTq(event.deviceId,
6414 device.classes, event)) {
6415 //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey");
6418 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6421 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6431 public int filterEvent(QueuedEvent ev) {
6432 switch (ev.classType) {
6433 case RawInputEvent.CLASS_KEYBOARD:
6434 KeyEvent ke = (KeyEvent)ev.event;
6435 if (mPolicy.isMovementKeyTi(ke.getKeyCode())) {
6436 Slog.w(TAG, "Dropping movement key during app switch: "
6437 + ke.getKeyCode() + ", action=" + ke.getAction());
6438 return FILTER_REMOVE;
6440 return FILTER_ABORT;
6447 * Must be called with the main window manager lock held.
6449 void setHoldScreenLocked(boolean holding) {
6450 boolean state = mHoldingScreen.isHeld();
6451 if (holding != state) {
6453 mHoldingScreen.acquire();
6455 mPolicy.screenOnStoppedLw();
6456 mHoldingScreen.release();
6462 public boolean detectSafeMode() {
6463 mSafeMode = mPolicy.detectSafeMode();
6467 public void systemReady() {
6468 mPolicy.systemReady();
6471 private final class InputDispatcherThread extends Thread {
6472 // Time to wait when there is nothing to do: 9999 seconds.
6473 static final int LONG_WAIT=9999*1000;
6475 public InputDispatcherThread() {
6476 super("InputDispatcher");
6484 } catch (Exception e) {
6485 Slog.e(TAG, "Exception in input dispatcher", e);
6490 private void process() {
6491 android.os.Process.setThreadPriority(
6492 android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
6494 // The last key event we saw
6495 KeyEvent lastKey = null;
6497 // Last keydown time for auto-repeating keys
6498 long lastKeyTime = SystemClock.uptimeMillis();
6499 long nextKeyTime = lastKeyTime+LONG_WAIT;
6502 // How many successive repeats we generated
6503 int keyRepeatCount = 0;
6505 // Need to report that configuration has changed?
6506 boolean configChanged = false;
6509 long curTime = SystemClock.uptimeMillis();
6511 if (DEBUG_INPUT) Slog.v(
6512 TAG, "Waiting for next key: now=" + curTime
6513 + ", repeat @ " + nextKeyTime);
6515 // Retrieve next event, waiting only as long as the next
6516 // repeat timeout. If the configuration has changed, then
6517 // don't wait at all -- we'll report the change as soon as
6518 // we have processed all events.
6519 QueuedEvent ev = mQueue.getEvent(
6520 (int)((!configChanged && curTime < nextKeyTime)
6521 ? (nextKeyTime-curTime) : 0));
6523 if (DEBUG_INPUT && ev != null) Slog.v(
6524 TAG, "Event: type=" + ev.classType + " data=" + ev.event);
6526 if (MEASURE_LATENCY) {
6527 lt.sample("2 got event ", System.nanoTime() - ev.whenNano);
6530 if (lastKey != null && !mPolicy.allowKeyRepeat()) {
6531 // cancel key repeat at the request of the policy.
6534 lastKeyTime = curTime;
6535 nextKeyTime = curTime + LONG_WAIT;
6539 curTime = SystemClock.uptimeMillis();
6541 if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
6542 eventType = eventType((MotionEvent)ev.event);
6543 } else if (ev.classType == RawInputEvent.CLASS_KEYBOARD ||
6544 ev.classType == RawInputEvent.CLASS_TRACKBALL) {
6545 eventType = LocalPowerManager.BUTTON_EVENT;
6547 eventType = LocalPowerManager.OTHER_EVENT;
6550 if ((curTime - mLastBatteryStatsCallTime)
6551 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
6552 mLastBatteryStatsCallTime = curTime;
6553 mBatteryStats.noteInputEvent();
6555 } catch (RemoteException e) {
6559 if (ev.classType == RawInputEvent.CLASS_CONFIGURATION_CHANGED) {
6560 // do not wake screen in this case
6561 } else if (eventType != TOUCH_EVENT
6562 && eventType != LONG_TOUCH_EVENT
6563 && eventType != CHEEK_EVENT) {
6564 mPowerManager.userActivity(curTime, false,
6566 } else if (mLastTouchEventType != eventType
6567 || (curTime - mLastUserActivityCallTime)
6568 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
6569 mLastUserActivityCallTime = curTime;
6570 mLastTouchEventType = eventType;
6571 mPowerManager.userActivity(curTime, false,
6575 switch (ev.classType) {
6576 case RawInputEvent.CLASS_KEYBOARD:
6577 KeyEvent ke = (KeyEvent)ev.event;
6579 lastKeyTime = curTime;
6580 if (lastKey != null &&
6581 ke.getKeyCode() == lastKey.getKeyCode()) {
6583 // Arbitrary long timeout to block
6584 // repeating here since we know that
6585 // the device driver takes care of it.
6586 nextKeyTime = lastKeyTime + LONG_WAIT;
6587 if (DEBUG_INPUT) Slog.v(
6588 TAG, "Received repeated key down");
6592 nextKeyTime = lastKeyTime
6593 + ViewConfiguration.getLongPressTimeout();
6594 if (DEBUG_INPUT) Slog.v(
6595 TAG, "Received key down: first repeat @ "
6603 // Arbitrary long timeout.
6604 lastKeyTime = curTime;
6605 nextKeyTime = curTime + LONG_WAIT;
6606 if (DEBUG_INPUT) Slog.v(
6607 TAG, "Received key up: ignore repeat @ "
6610 if (keyRepeatCount > 0) {
6611 dispatchKey(KeyEvent.changeTimeRepeat(ke,
6612 ke.getEventTime(), keyRepeatCount), 0, 0);
6614 dispatchKey(ke, 0, 0);
6616 mQueue.recycleEvent(ev);
6618 case RawInputEvent.CLASS_TOUCHSCREEN:
6619 //Slog.i(TAG, "Read next event " + ev);
6620 dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
6622 case RawInputEvent.CLASS_TRACKBALL:
6623 dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0);
6625 case RawInputEvent.CLASS_CONFIGURATION_CHANGED:
6626 configChanged = true;
6629 mQueue.recycleEvent(ev);
6633 } else if (configChanged) {
6634 configChanged = false;
6635 sendNewConfiguration();
6637 } else if (lastKey != null) {
6638 curTime = SystemClock.uptimeMillis();
6640 // Timeout occurred while key was down. If it is at or
6641 // past the key repeat time, dispatch the repeat.
6642 if (DEBUG_INPUT) Slog.v(
6643 TAG, "Key timeout: repeat=" + nextKeyTime
6644 + ", now=" + curTime);
6645 if (curTime < nextKeyTime) {
6649 lastKeyTime = nextKeyTime;
6650 nextKeyTime = nextKeyTime + KEY_REPEAT_DELAY;
6652 if (DEBUG_INPUT) Slog.v(
6653 TAG, "Key repeat: count=" + keyRepeatCount
6654 + ", next @ " + nextKeyTime);
6656 if (downTime != 0 && (downTime
6657 + ViewConfiguration.getLongPressTimeout())
6659 newEvent = KeyEvent.changeTimeRepeat(lastKey,
6660 curTime, keyRepeatCount,
6661 lastKey.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6664 newEvent = KeyEvent.changeTimeRepeat(lastKey,
6665 curTime, keyRepeatCount);
6667 dispatchKey(newEvent, 0, 0);
6670 curTime = SystemClock.uptimeMillis();
6672 lastKeyTime = curTime;
6673 nextKeyTime = curTime + LONG_WAIT;
6676 } catch (Exception e) {
6678 "Input thread received uncaught exception: " + e, e);
6684 // -------------------------------------------------------------
6685 // Client Session State
6686 // -------------------------------------------------------------
6688 private final class Session extends IWindowSession.Stub
6689 implements IBinder.DeathRecipient {
6690 final IInputMethodClient mClient;
6691 final IInputContext mInputContext;
6694 final String mStringName;
6695 SurfaceSession mSurfaceSession;
6697 boolean mClientDead = false;
6700 * Current pointer move event being dispatched to client window... must
6701 * hold key lock to access.
6703 QueuedEvent mPendingPointerMove;
6704 WindowState mPendingPointerWindow;
6707 * Current trackball move event being dispatched to client window... must
6708 * hold key lock to access.
6710 QueuedEvent mPendingTrackballMove;
6711 WindowState mPendingTrackballWindow;
6713 public Session(IInputMethodClient client, IInputContext inputContext) {
6715 mInputContext = inputContext;
6716 mUid = Binder.getCallingUid();
6717 mPid = Binder.getCallingPid();
6718 StringBuilder sb = new StringBuilder();
6719 sb.append("Session{");
6720 sb.append(Integer.toHexString(System.identityHashCode(this)));
6724 mStringName = sb.toString();
6726 synchronized (mWindowMap) {
6727 if (mInputMethodManager == null && mHaveInputMethods) {
6728 IBinder b = ServiceManager.getService(
6729 Context.INPUT_METHOD_SERVICE);
6730 mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
6733 long ident = Binder.clearCallingIdentity();
6735 // Note: it is safe to call in to the input method manager
6736 // here because we are not holding our lock.
6737 if (mInputMethodManager != null) {
6738 mInputMethodManager.addClient(client, inputContext,
6741 client.setUsingInputMethod(false);
6743 client.asBinder().linkToDeath(this, 0);
6744 } catch (RemoteException e) {
6745 // The caller has died, so we can just forget about this.
6747 if (mInputMethodManager != null) {
6748 mInputMethodManager.removeClient(client);
6750 } catch (RemoteException ee) {
6753 Binder.restoreCallingIdentity(ident);
6758 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
6759 throws RemoteException {
6761 return super.onTransact(code, data, reply, flags);
6762 } catch (RuntimeException e) {
6763 // Log all 'real' exceptions thrown to the caller
6764 if (!(e instanceof SecurityException)) {
6765 Slog.e(TAG, "Window Session Crash", e);
6771 public void binderDied() {
6772 // Note: it is safe to call in to the input method manager
6773 // here because we are not holding our lock.
6775 if (mInputMethodManager != null) {
6776 mInputMethodManager.removeClient(mClient);
6778 } catch (RemoteException e) {
6780 synchronized(mWindowMap) {
6781 mClient.asBinder().unlinkToDeath(this, 0);
6783 killSessionLocked();
6787 public int add(IWindow window, WindowManager.LayoutParams attrs,
6788 int viewVisibility, Rect outContentInsets) {
6789 return addWindow(this, window, attrs, viewVisibility, outContentInsets);
6792 public void remove(IWindow window) {
6793 removeWindow(this, window);
6796 public int relayout(IWindow window, WindowManager.LayoutParams attrs,
6797 int requestedWidth, int requestedHeight, int viewFlags,
6798 boolean insetsPending, Rect outFrame, Rect outContentInsets,
6799 Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
6800 return relayoutWindow(this, window, attrs,
6801 requestedWidth, requestedHeight, viewFlags, insetsPending,
6802 outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
6805 public void setTransparentRegion(IWindow window, Region region) {
6806 setTransparentRegionWindow(this, window, region);
6809 public void setInsets(IWindow window, int touchableInsets,
6810 Rect contentInsets, Rect visibleInsets) {
6811 setInsetsWindow(this, window, touchableInsets, contentInsets,
6815 public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
6816 getWindowDisplayFrame(this, window, outDisplayFrame);
6819 public void finishDrawing(IWindow window) {
6820 if (localLOGV) Slog.v(
6821 TAG, "IWindow finishDrawing called for " + window);
6822 finishDrawingWindow(this, window);
6825 public void finishKey(IWindow window) {
6826 if (localLOGV) Slog.v(
6827 TAG, "IWindow finishKey called for " + window);
6828 mKeyWaiter.finishedKey(this, window, false,
6829 KeyWaiter.RETURN_NOTHING);
6832 public MotionEvent getPendingPointerMove(IWindow window) {
6833 if (localLOGV) Slog.v(
6834 TAG, "IWindow getPendingMotionEvent called for " + window);
6835 return mKeyWaiter.finishedKey(this, window, false,
6836 KeyWaiter.RETURN_PENDING_POINTER);
6839 public MotionEvent getPendingTrackballMove(IWindow window) {
6840 if (localLOGV) Slog.v(
6841 TAG, "IWindow getPendingMotionEvent called for " + window);
6842 return mKeyWaiter.finishedKey(this, window, false,
6843 KeyWaiter.RETURN_PENDING_TRACKBALL);
6846 public void setInTouchMode(boolean mode) {
6847 synchronized(mWindowMap) {
6848 mInTouchMode = mode;
6852 public boolean getInTouchMode() {
6853 synchronized(mWindowMap) {
6854 return mInTouchMode;
6858 public boolean performHapticFeedback(IWindow window, int effectId,
6860 synchronized(mWindowMap) {
6861 long ident = Binder.clearCallingIdentity();
6863 return mPolicy.performHapticFeedbackLw(
6864 windowForClientLocked(this, window, true),
6867 Binder.restoreCallingIdentity(ident);
6872 public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
6873 synchronized(mWindowMap) {
6874 long ident = Binder.clearCallingIdentity();
6876 setWindowWallpaperPositionLocked(
6877 windowForClientLocked(this, window, true),
6878 x, y, xStep, yStep);
6880 Binder.restoreCallingIdentity(ident);
6885 public void wallpaperOffsetsComplete(IBinder window) {
6886 WindowManagerService.this.wallpaperOffsetsComplete(window);
6889 public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
6890 int z, Bundle extras, boolean sync) {
6891 synchronized(mWindowMap) {
6892 long ident = Binder.clearCallingIdentity();
6894 return sendWindowWallpaperCommandLocked(
6895 windowForClientLocked(this, window, true),
6896 action, x, y, z, extras, sync);
6898 Binder.restoreCallingIdentity(ident);
6903 public void wallpaperCommandComplete(IBinder window, Bundle result) {
6904 WindowManagerService.this.wallpaperCommandComplete(window, result);
6907 void windowAddedLocked() {
6908 if (mSurfaceSession == null) {
6909 if (localLOGV) Slog.v(
6910 TAG, "First window added to " + this + ", creating SurfaceSession");
6911 mSurfaceSession = new SurfaceSession();
6912 if (SHOW_TRANSACTIONS) Slog.i(
6913 TAG, " NEW SURFACE SESSION " + mSurfaceSession);
6914 mSessions.add(this);
6919 void windowRemovedLocked() {
6921 killSessionLocked();
6924 void killSessionLocked() {
6925 if (mNumWindow <= 0 && mClientDead) {
6926 mSessions.remove(this);
6927 if (mSurfaceSession != null) {
6928 if (localLOGV) Slog.v(
6929 TAG, "Last window removed from " + this
6930 + ", destroying " + mSurfaceSession);
6931 if (SHOW_TRANSACTIONS) Slog.i(
6932 TAG, " KILL SURFACE SESSION " + mSurfaceSession);
6934 mSurfaceSession.kill();
6935 } catch (Exception e) {
6936 Slog.w(TAG, "Exception thrown when killing surface session "
6937 + mSurfaceSession + " in session " + this
6938 + ": " + e.toString());
6940 mSurfaceSession = null;
6945 void dump(PrintWriter pw, String prefix) {
6946 pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
6947 pw.print(" mClientDead="); pw.print(mClientDead);
6948 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
6949 if (mPendingPointerWindow != null || mPendingPointerMove != null) {
6951 pw.print("mPendingPointerWindow="); pw.print(mPendingPointerWindow);
6952 pw.print(" mPendingPointerMove="); pw.println(mPendingPointerMove);
6954 if (mPendingTrackballWindow != null || mPendingTrackballMove != null) {
6956 pw.print("mPendingTrackballWindow="); pw.print(mPendingTrackballWindow);
6957 pw.print(" mPendingTrackballMove="); pw.println(mPendingTrackballMove);
6962 public String toString() {
6967 // -------------------------------------------------------------
6968 // Client Window State
6969 // -------------------------------------------------------------
6971 private final class WindowState implements WindowManagerPolicy.WindowState {
6972 final Session mSession;
6973 final IWindow mClient;
6975 WindowToken mRootToken;
6976 AppWindowToken mAppToken;
6977 AppWindowToken mTargetAppToken;
6978 final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
6979 final DeathRecipient mDeathRecipient;
6980 final WindowState mAttachedWindow;
6981 final ArrayList mChildWindows = new ArrayList();
6982 final int mBaseLayer;
6983 final int mSubLayer;
6984 final boolean mLayoutAttached;
6985 final boolean mIsImWindow;
6986 final boolean mIsWallpaper;
6987 final boolean mIsFloatingLayer;
6988 int mViewVisibility;
6989 boolean mPolicyVisibility = true;
6990 boolean mPolicyVisibilityAfterAnim = true;
6991 boolean mAppFreezing;
6993 boolean mReportDestroySurface;
6994 boolean mSurfacePendingDestroy;
6995 boolean mAttachedHidden; // is our parent window hidden?
6996 boolean mLastHidden; // was this window last hidden?
6997 boolean mWallpaperVisible; // for wallpaper, what was last vis report?
6998 int mRequestedWidth;
6999 int mRequestedHeight;
7000 int mLastRequestedWidth;
7001 int mLastRequestedHeight;
7007 boolean mTurnOnScreen;
7009 WindowState mNextOutsideTouch;
7011 int mLayoutSeq = -1;
7013 Configuration mConfiguration = null;
7015 // Actual frame shown on-screen (may be modified by animation)
7016 final Rect mShownFrame = new Rect();
7017 final Rect mLastShownFrame = new Rect();
7020 * Set when we have changed the size of the surface, to know that
7021 * we must tell them application to resize (and thus redraw itself).
7023 boolean mSurfaceResized;
7026 * Insets that determine the actually visible area
7028 final Rect mVisibleInsets = new Rect();
7029 final Rect mLastVisibleInsets = new Rect();
7030 boolean mVisibleInsetsChanged;
7033 * Insets that are covered by system windows
7035 final Rect mContentInsets = new Rect();
7036 final Rect mLastContentInsets = new Rect();
7037 boolean mContentInsetsChanged;
7040 * Set to true if we are waiting for this window to receive its
7041 * given internal insets before laying out other windows based on it.
7043 boolean mGivenInsetsPending;
7046 * These are the content insets that were given during layout for
7047 * this window, to be applied to windows behind it.
7049 final Rect mGivenContentInsets = new Rect();
7052 * These are the visible insets that were given during layout for
7053 * this window, to be applied to windows behind it.
7055 final Rect mGivenVisibleInsets = new Rect();
7058 * Flag indicating whether the touchable region should be adjusted by
7059 * the visible insets; if false the area outside the visible insets is
7060 * NOT touchable, so we must use those to adjust the frame during hit
7063 int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
7065 // Current transformation being applied.
7066 float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
7067 float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
7068 float mHScale=1, mVScale=1;
7069 float mLastHScale=1, mLastVScale=1;
7070 final Matrix mTmpMatrix = new Matrix();
7072 // "Real" frame that the application sees.
7073 final Rect mFrame = new Rect();
7074 final Rect mLastFrame = new Rect();
7076 final Rect mContainingFrame = new Rect();
7077 final Rect mDisplayFrame = new Rect();
7078 final Rect mContentFrame = new Rect();
7079 final Rect mVisibleFrame = new Rect();
7081 float mShownAlpha = 1;
7083 float mLastAlpha = 1;
7085 // Set to true if, when the window gets displayed, it should perform
7086 // an enter animation.
7087 boolean mEnterAnimationPending;
7089 // Currently running animation.
7091 boolean mLocalAnimating;
7092 Animation mAnimation;
7093 boolean mAnimationIsEntrance;
7094 boolean mHasTransformation;
7095 boolean mHasLocalTransformation;
7096 final Transformation mTransformation = new Transformation();
7098 // If a window showing a wallpaper: the requested offset for the
7099 // wallpaper; if a wallpaper window: the currently applied offset.
7100 float mWallpaperX = -1;
7101 float mWallpaperY = -1;
7103 // If a window showing a wallpaper: what fraction of the offset
7104 // range corresponds to a full virtual screen.
7105 float mWallpaperXStep = -1;
7106 float mWallpaperYStep = -1;
7108 // Wallpaper windows: pixels offset based on above variables.
7112 // This is set after IWindowSession.relayout() has been called at
7113 // least once for the window. It allows us to detect the situation
7114 // where we don't yet have a surface, but should have one soon, so
7115 // we can give the window focus before waiting for the relayout.
7116 boolean mRelayoutCalled;
7118 // This is set after the Surface has been created but before the
7119 // window has been drawn. During this time the surface is hidden.
7120 boolean mDrawPending;
7122 // This is set after the window has finished drawing for the first
7123 // time but before its surface is shown. The surface will be
7124 // displayed when the next layout is run.
7125 boolean mCommitDrawPending;
7127 // This is set during the time after the window's drawing has been
7128 // committed, and before its surface is actually shown. It is used
7129 // to delay showing the surface until all windows in a token are ready
7131 boolean mReadyToShow;
7133 // Set when the window has been shown in the screen the first time.
7136 // Currently running an exit animation?
7139 // Currently on the mDestroySurface list?
7140 boolean mDestroying;
7142 // Completely remove from window manager after exit animation?
7143 boolean mRemoveOnExit;
7145 // Set when the orientation is changing and this window has not yet
7146 // been updated for the new orientation.
7147 boolean mOrientationChanging;
7149 // Is this window now (or just being) removed?
7152 // For debugging, this is the last information given to the surface flinger.
7153 boolean mSurfaceShown;
7154 int mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
7156 float mSurfaceAlpha;
7158 WindowState(Session s, IWindow c, WindowToken token,
7159 WindowState attachedWindow, WindowManager.LayoutParams a,
7160 int viewVisibility) {
7165 mViewVisibility = viewVisibility;
7166 DeathRecipient deathRecipient = new DeathRecipient();
7168 if (localLOGV) Slog.v(
7169 TAG, "Window " + this + " client=" + c.asBinder()
7170 + " token=" + token + " (" + mAttrs.token + ")");
7172 c.asBinder().linkToDeath(deathRecipient, 0);
7173 } catch (RemoteException e) {
7174 mDeathRecipient = null;
7175 mAttachedWindow = null;
7176 mLayoutAttached = false;
7177 mIsImWindow = false;
7178 mIsWallpaper = false;
7179 mIsFloatingLayer = false;
7184 mDeathRecipient = deathRecipient;
7186 if ((mAttrs.type >= FIRST_SUB_WINDOW &&
7187 mAttrs.type <= LAST_SUB_WINDOW)) {
7188 // The multiplier here is to reserve space for multiple
7189 // windows in the same type layer.
7190 mBaseLayer = mPolicy.windowTypeToLayerLw(
7191 attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER
7192 + TYPE_LAYER_OFFSET;
7193 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
7194 mAttachedWindow = attachedWindow;
7195 mAttachedWindow.mChildWindows.add(this);
7196 mLayoutAttached = mAttrs.type !=
7197 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
7198 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
7199 || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
7200 mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
7201 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
7203 // The multiplier here is to reserve space for multiple
7204 // windows in the same type layer.
7205 mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
7206 * TYPE_LAYER_MULTIPLIER
7207 + TYPE_LAYER_OFFSET;
7209 mAttachedWindow = null;
7210 mLayoutAttached = false;
7211 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
7212 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
7213 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
7214 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
7217 WindowState appWin = this;
7218 while (appWin.mAttachedWindow != null) {
7219 appWin = mAttachedWindow;
7221 WindowToken appToken = appWin.mToken;
7222 while (appToken.appWindowToken == null) {
7223 WindowToken parent = mTokenMap.get(appToken.token);
7224 if (parent == null || appToken == parent) {
7229 mRootToken = appToken;
7230 mAppToken = appToken.appWindowToken;
7233 mRequestedWidth = 0;
7234 mRequestedHeight = 0;
7235 mLastRequestedWidth = 0;
7236 mLastRequestedHeight = 0;
7245 if (localLOGV) Slog.v(
7246 TAG, "Attaching " + this + " token=" + mToken
7247 + ", list=" + mToken.windows);
7248 mSession.windowAddedLocked();
7251 public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
7254 final Rect container = mContainingFrame;
7257 final Rect display = mDisplayFrame;
7260 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
7261 container.intersect(mCompatibleScreenFrame);
7262 if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
7263 display.intersect(mCompatibleScreenFrame);
7267 final int pw = container.right - container.left;
7268 final int ph = container.bottom - container.top;
7271 if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
7272 w = mAttrs.width < 0 ? pw : mAttrs.width;
7273 h = mAttrs.height< 0 ? ph : mAttrs.height;
7275 w = mAttrs.width == mAttrs.MATCH_PARENT ? pw : mRequestedWidth;
7276 h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight;
7279 final Rect content = mContentFrame;
7282 final Rect visible = mVisibleFrame;
7285 final Rect frame = mFrame;
7286 final int fw = frame.width();
7287 final int fh = frame.height();
7289 //System.out.println("In: w=" + w + " h=" + h + " container=" +
7290 // container + " x=" + mAttrs.x + " y=" + mAttrs.y);
7292 Gravity.apply(mAttrs.gravity, w, h, container,
7293 (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
7294 (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
7296 //System.out.println("Out: " + mFrame);
7298 // Now make sure the window fits in the overall display.
7299 Gravity.applyDisplay(mAttrs.gravity, df, frame);
7301 // Make sure the content and visible frames are inside of the
7302 // final window frame.
7303 if (content.left < frame.left) content.left = frame.left;
7304 if (content.top < frame.top) content.top = frame.top;
7305 if (content.right > frame.right) content.right = frame.right;
7306 if (content.bottom > frame.bottom) content.bottom = frame.bottom;
7307 if (visible.left < frame.left) visible.left = frame.left;
7308 if (visible.top < frame.top) visible.top = frame.top;
7309 if (visible.right > frame.right) visible.right = frame.right;
7310 if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
7312 final Rect contentInsets = mContentInsets;
7313 contentInsets.left = content.left-frame.left;
7314 contentInsets.top = content.top-frame.top;
7315 contentInsets.right = frame.right-content.right;
7316 contentInsets.bottom = frame.bottom-content.bottom;
7318 final Rect visibleInsets = mVisibleInsets;
7319 visibleInsets.left = visible.left-frame.left;
7320 visibleInsets.top = visible.top-frame.top;
7321 visibleInsets.right = frame.right-visible.right;
7322 visibleInsets.bottom = frame.bottom-visible.bottom;
7324 if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
7325 updateWallpaperOffsetLocked(this, mDisplay.getWidth(),
7326 mDisplay.getHeight(), false);
7330 //if ("com.google.android.youtube".equals(mAttrs.packageName)
7331 // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
7332 Slog.v(TAG, "Resolving (mRequestedWidth="
7333 + mRequestedWidth + ", mRequestedheight="
7334 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
7335 + "): frame=" + mFrame.toShortString()
7336 + " ci=" + contentInsets.toShortString()
7337 + " vi=" + visibleInsets.toShortString());
7342 public Rect getFrameLw() {
7346 public Rect getShownFrameLw() {
7350 public Rect getDisplayFrameLw() {
7351 return mDisplayFrame;
7354 public Rect getContentFrameLw() {
7355 return mContentFrame;
7358 public Rect getVisibleFrameLw() {
7359 return mVisibleFrame;
7362 public boolean getGivenInsetsPendingLw() {
7363 return mGivenInsetsPending;
7366 public Rect getGivenContentInsetsLw() {
7367 return mGivenContentInsets;
7370 public Rect getGivenVisibleInsetsLw() {
7371 return mGivenVisibleInsets;
7374 public WindowManager.LayoutParams getAttrs() {
7378 public int getSurfaceLayer() {
7382 public IApplicationToken getAppToken() {
7383 return mAppToken != null ? mAppToken.appToken : null;
7386 public boolean hasAppShownWindows() {
7387 return mAppToken != null ? mAppToken.firstWindowDrawn : false;
7390 public void setAnimation(Animation anim) {
7391 if (localLOGV) Slog.v(
7392 TAG, "Setting animation in " + this + ": " + anim);
7394 mLocalAnimating = false;
7396 mAnimation.restrictDuration(MAX_ANIMATION_DURATION);
7397 mAnimation.scaleCurrentDuration(mWindowAnimationScale);
7400 public void clearAnimation() {
7401 if (mAnimation != null) {
7403 mLocalAnimating = false;
7408 Surface createSurfaceLocked() {
7409 if (mSurface == null) {
7410 mReportDestroySurface = false;
7411 mSurfacePendingDestroy = false;
7412 mDrawPending = true;
7413 mCommitDrawPending = false;
7414 mReadyToShow = false;
7415 if (mAppToken != null) {
7416 mAppToken.allDrawn = false;
7420 if (mAttrs.memoryType == MEMORY_TYPE_PUSH_BUFFERS) {
7421 flags |= Surface.PUSH_BUFFERS;
7424 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
7425 flags |= Surface.SECURE;
7427 if (DEBUG_VISIBILITY) Slog.v(
7428 TAG, "Creating surface in session "
7429 + mSession.mSurfaceSession + " window " + this
7430 + " w=" + mFrame.width()
7431 + " h=" + mFrame.height() + " format="
7432 + mAttrs.format + " flags=" + flags);
7434 int w = mFrame.width();
7435 int h = mFrame.height();
7436 if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
7437 // for a scaled surface, we always want the requested
7439 w = mRequestedWidth;
7440 h = mRequestedHeight;
7443 // Something is wrong and SurfaceFlinger will not like this,
7444 // try to revert to sane values
7448 mSurfaceShown = false;
7456 mSurface = new Surface(
7457 mSession.mSurfaceSession, mSession.mPid,
7458 mAttrs.getTitle().toString(),
7459 0, w, h, mAttrs.format, flags);
7460 if (SHOW_TRANSACTIONS) Slog.i(TAG, " CREATE SURFACE "
7461 + mSurface + " IN SESSION "
7462 + mSession.mSurfaceSession
7463 + ": pid=" + mSession.mPid + " format="
7464 + mAttrs.format + " flags=0x"
7465 + Integer.toHexString(flags)
7467 } catch (Surface.OutOfResourcesException e) {
7468 Slog.w(TAG, "OutOfResourcesException creating surface");
7469 reclaimSomeSurfaceMemoryLocked(this, "create");
7471 } catch (Exception e) {
7472 Slog.e(TAG, "Exception creating surface", e);
7476 if (localLOGV) Slog.v(
7477 TAG, "Got surface: " + mSurface
7478 + ", set left=" + mFrame.left + " top=" + mFrame.top
7479 + ", animLayer=" + mAnimLayer);
7480 if (SHOW_TRANSACTIONS) {
7481 Slog.i(TAG, ">>> OPEN TRANSACTION");
7482 if (SHOW_TRANSACTIONS) logSurface(this,
7483 "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
7484 mFrame.width() + "x" + mFrame.height() + "), layer=" +
7485 mAnimLayer + " HIDE", null);
7487 Surface.openTransaction();
7490 mSurfaceX = mFrame.left + mXOffset;
7491 mSurfaceY = mFrame.top + mYOffset;
7492 mSurface.setPosition(mSurfaceX, mSurfaceY);
7493 mSurfaceLayer = mAnimLayer;
7494 mSurface.setLayer(mAnimLayer);
7495 mSurfaceShown = false;
7497 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
7498 if (SHOW_TRANSACTIONS) logSurface(this, "DITHER", null);
7499 mSurface.setFlags(Surface.SURFACE_DITHER,
7500 Surface.SURFACE_DITHER);
7502 } catch (RuntimeException e) {
7503 Slog.w(TAG, "Error creating surface in " + w, e);
7504 reclaimSomeSurfaceMemoryLocked(this, "create-init");
7508 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
7509 Surface.closeTransaction();
7511 if (localLOGV) Slog.v(
7512 TAG, "Created surface " + this);
7517 void destroySurfaceLocked() {
7518 // Window is no longer on-screen, so can no longer receive
7519 // key events... if we were waiting for it to finish
7520 // handling a key event, the wait is over!
7521 mKeyWaiter.finishedKey(mSession, mClient, true,
7522 KeyWaiter.RETURN_NOTHING);
7523 mKeyWaiter.releasePendingPointerLocked(mSession);
7524 mKeyWaiter.releasePendingTrackballLocked(mSession);
7526 if (mAppToken != null && this == mAppToken.startingWindow) {
7527 mAppToken.startingDisplayed = false;
7530 if (mSurface != null) {
7531 mDrawPending = false;
7532 mCommitDrawPending = false;
7533 mReadyToShow = false;
7535 int i = mChildWindows.size();
7538 WindowState c = (WindowState)mChildWindows.get(i);
7539 c.mAttachedHidden = true;
7542 if (mReportDestroySurface) {
7543 mReportDestroySurface = false;
7544 mSurfacePendingDestroy = true;
7546 mClient.dispatchGetNewSurface();
7547 // We'll really destroy on the next time around.
7549 } catch (RemoteException e) {
7554 if (DEBUG_VISIBILITY) {
7555 RuntimeException e = null;
7556 if (!HIDE_STACK_CRAWLS) {
7557 e = new RuntimeException();
7558 e.fillInStackTrace();
7560 Slog.w(TAG, "Window " + this + " destroying surface "
7561 + mSurface + ", session " + mSession, e);
7563 if (SHOW_TRANSACTIONS) {
7564 RuntimeException e = null;
7565 if (!HIDE_STACK_CRAWLS) {
7566 e = new RuntimeException();
7567 e.fillInStackTrace();
7569 if (SHOW_TRANSACTIONS) logSurface(this, "DESTROY", e);
7572 } catch (RuntimeException e) {
7573 Slog.w(TAG, "Exception thrown when destroying Window " + this
7574 + " surface " + mSurface + " session " + mSession
7575 + ": " + e.toString());
7578 mSurfaceShown = false;
7583 boolean finishDrawingLocked() {
7585 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Slog.v(
7586 TAG, "finishDrawingLocked: " + mSurface);
7587 mCommitDrawPending = true;
7588 mDrawPending = false;
7594 // This must be called while inside a transaction.
7595 boolean commitFinishDrawingLocked(long currentTime) {
7596 //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
7597 if (!mCommitDrawPending) {
7600 mCommitDrawPending = false;
7601 mReadyToShow = true;
7602 final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
7603 final AppWindowToken atoken = mAppToken;
7604 if (atoken == null || atoken.allDrawn || starting) {
7605 performShowLocked();
7610 // This must be called while inside a transaction.
7611 boolean performShowLocked() {
7612 if (DEBUG_VISIBILITY) {
7613 RuntimeException e = null;
7614 if (!HIDE_STACK_CRAWLS) {
7615 e = new RuntimeException();
7616 e.fillInStackTrace();
7618 Slog.v(TAG, "performShow on " + this
7619 + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
7620 + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
7622 if (mReadyToShow && isReadyForDisplay()) {
7623 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) logSurface(this,
7624 "SHOW (performShowLocked)", null);
7625 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
7626 + " during animation: policyVis=" + mPolicyVisibility
7627 + " attHidden=" + mAttachedHidden
7628 + " tok.hiddenRequested="
7629 + (mAppToken != null ? mAppToken.hiddenRequested : false)
7631 + (mAppToken != null ? mAppToken.hidden : false)
7632 + " animating=" + mAnimating
7634 + (mAppToken != null ? mAppToken.animating : false));
7635 if (!showSurfaceRobustlyLocked(this)) {
7640 mLastHidden = false;
7641 mReadyToShow = false;
7642 enableScreenIfNeededLocked();
7644 applyEnterAnimationLocked(this);
7646 int i = mChildWindows.size();
7649 WindowState c = (WindowState)mChildWindows.get(i);
7650 if (c.mAttachedHidden) {
7651 c.mAttachedHidden = false;
7652 if (c.mSurface != null) {
7653 c.performShowLocked();
7654 // It hadn't been shown, which means layout not
7655 // performed on it, so now we want to make sure to
7656 // do a layout. If called from within the transaction
7657 // loop, this will cause it to restart with a new
7659 mLayoutNeeded = true;
7664 if (mAttrs.type != TYPE_APPLICATION_STARTING
7665 && mAppToken != null) {
7666 mAppToken.firstWindowDrawn = true;
7668 if (mAppToken.startingData != null) {
7669 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG,
7670 "Finish starting " + mToken
7671 + ": first real window is shown, no animation");
7672 // If this initial window is animating, stop it -- we
7673 // will do an animation to reveal it from behind the
7674 // starting window, so there is no need for it to also
7675 // be doing its own stuff.
7676 if (mAnimation != null) {
7678 // Make sure we clean up the animation.
7681 mFinishedStarting.add(mAppToken);
7682 mH.sendEmptyMessage(H.FINISHED_STARTING);
7684 mAppToken.updateReportedVisibilityLocked();
7690 // This must be called while inside a transaction. Returns true if
7691 // there is more animation to run.
7692 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
7693 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
7694 // We will run animations as long as the display isn't frozen.
7696 if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
7697 mHasTransformation = true;
7698 mHasLocalTransformation = true;
7699 if (!mLocalAnimating) {
7700 if (DEBUG_ANIM) Slog.v(
7701 TAG, "Starting animation in " + this +
7702 " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
7703 " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale);
7704 mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
7705 mAnimation.setStartTime(currentTime);
7706 mLocalAnimating = true;
7709 mTransformation.clear();
7710 final boolean more = mAnimation.getTransformation(
7711 currentTime, mTransformation);
7712 if (DEBUG_ANIM) Slog.v(
7713 TAG, "Stepped animation in " + this +
7714 ": more=" + more + ", xform=" + mTransformation);
7719 if (DEBUG_ANIM) Slog.v(
7720 TAG, "Finished animation in " + this +
7721 " @ " + currentTime);
7723 //WindowManagerService.this.dump();
7725 mHasLocalTransformation = false;
7726 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
7727 && mAppToken.animation != null) {
7728 // When our app token is animating, we kind-of pretend like
7729 // we are as well. Note the mLocalAnimating mAnimationIsEntrance
7730 // part of this check means that we will only do this if
7731 // our window is not currently exiting, or it is not
7732 // locally animating itself. The idea being that one that
7733 // is exiting and doing a local animation should be removed
7734 // once that animation is done.
7736 mHasTransformation = true;
7737 mTransformation.clear();
7739 } else if (mHasTransformation) {
7740 // Little trick to get through the path below to act like
7741 // we have finished an animation.
7743 } else if (isAnimating()) {
7746 } else if (mAnimation != null) {
7747 // If the display is frozen, and there is a pending animation,
7748 // clear it and make sure we run the cleanup code.
7750 mLocalAnimating = true;
7754 if (!mAnimating && !mLocalAnimating) {
7758 if (DEBUG_ANIM) Slog.v(
7759 TAG, "Animation done in " + this + ": exiting=" + mExiting
7760 + ", reportedVisible="
7761 + (mAppToken != null ? mAppToken.reportedVisible : false));
7764 mLocalAnimating = false;
7766 mAnimLayer = mLayer;
7768 mAnimLayer += mInputMethodAnimLayerAdjustment;
7769 } else if (mIsWallpaper) {
7770 mAnimLayer += mWallpaperAnimLayerAdjustment;
7772 if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
7773 + " anim layer: " + mAnimLayer);
7774 mHasTransformation = false;
7775 mHasLocalTransformation = false;
7776 if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
7777 if (DEBUG_VISIBILITY) {
7778 Slog.v(TAG, "Policy visibility changing after anim in " + this + ": "
7779 + mPolicyVisibilityAfterAnim);
7781 mPolicyVisibility = mPolicyVisibilityAfterAnim;
7782 if (!mPolicyVisibility) {
7783 if (mCurrentFocus == this) {
7784 mFocusMayChange = true;
7786 // Window is no longer visible -- make sure if we were waiting
7787 // for it to be displayed before enabling the display, that
7788 // we allow the display to be enabled now.
7789 enableScreenIfNeededLocked();
7792 mTransformation.clear();
7794 && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
7795 && mAppToken != null
7796 && mAppToken.firstWindowDrawn
7797 && mAppToken.startingData != null) {
7798 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting "
7799 + mToken + ": first real window done animating");
7800 mFinishedStarting.add(mAppToken);
7801 mH.sendEmptyMessage(H.FINISHED_STARTING);
7806 if (mAppToken != null) {
7807 mAppToken.updateReportedVisibilityLocked();
7814 if (DEBUG_ANIM) Slog.v(
7815 TAG, "finishExit in " + this
7816 + ": exiting=" + mExiting
7817 + " remove=" + mRemoveOnExit
7818 + " windowAnimating=" + isWindowAnimating());
7820 final int N = mChildWindows.size();
7821 for (int i=0; i<N; i++) {
7822 ((WindowState)mChildWindows.get(i)).finishExit();
7829 if (isWindowAnimating()) {
7833 if (localLOGV) Slog.v(
7834 TAG, "Exit animation finished in " + this
7835 + ": remove=" + mRemoveOnExit);
7836 if (mSurface != null) {
7837 mDestroySurface.add(this);
7839 if (SHOW_TRANSACTIONS) logSurface(this, "HIDE (finishExit)", null);
7840 mSurfaceShown = false;
7843 } catch (RuntimeException e) {
7844 Slog.w(TAG, "Error hiding surface in " + this, e);
7847 mKeyWaiter.releasePendingPointerLocked(mSession);
7850 if (mRemoveOnExit) {
7851 mPendingRemove.add(this);
7852 mRemoveOnExit = false;
7856 boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
7857 if (dsdx < .99999f || dsdx > 1.00001f) return false;
7858 if (dtdy < .99999f || dtdy > 1.00001f) return false;
7859 if (dtdx < -.000001f || dtdx > .000001f) return false;
7860 if (dsdy < -.000001f || dsdy > .000001f) return false;
7864 void computeShownFrameLocked() {
7865 final boolean selfTransformation = mHasLocalTransformation;
7866 Transformation attachedTransformation =
7867 (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
7868 ? mAttachedWindow.mTransformation : null;
7869 Transformation appTransformation =
7870 (mAppToken != null && mAppToken.hasTransformation)
7871 ? mAppToken.transformation : null;
7873 // Wallpapers are animated based on the "real" window they
7874 // are currently targeting.
7875 if (mAttrs.type == TYPE_WALLPAPER && mLowerWallpaperTarget == null
7876 && mWallpaperTarget != null) {
7877 if (mWallpaperTarget.mHasLocalTransformation &&
7878 mWallpaperTarget.mAnimation != null &&
7879 !mWallpaperTarget.mAnimation.getDetachWallpaper()) {
7880 attachedTransformation = mWallpaperTarget.mTransformation;
7881 if (DEBUG_WALLPAPER && attachedTransformation != null) {
7882 Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
7885 if (mWallpaperTarget.mAppToken != null &&
7886 mWallpaperTarget.mAppToken.hasTransformation &&
7887 mWallpaperTarget.mAppToken.animation != null &&
7888 !mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
7889 appTransformation = mWallpaperTarget.mAppToken.transformation;
7890 if (DEBUG_WALLPAPER && appTransformation != null) {
7891 Slog.v(TAG, "WP target app xform: " + appTransformation);
7896 if (selfTransformation || attachedTransformation != null
7897 || appTransformation != null) {
7898 // cache often used attributes locally
7899 final Rect frame = mFrame;
7900 final float tmpFloats[] = mTmpFloats;
7901 final Matrix tmpMatrix = mTmpMatrix;
7903 // Compute the desired transformation.
7904 tmpMatrix.setTranslate(0, 0);
7905 if (selfTransformation) {
7906 tmpMatrix.postConcat(mTransformation.getMatrix());
7908 tmpMatrix.postTranslate(frame.left, frame.top);
7909 if (attachedTransformation != null) {
7910 tmpMatrix.postConcat(attachedTransformation.getMatrix());
7912 if (appTransformation != null) {
7913 tmpMatrix.postConcat(appTransformation.getMatrix());
7916 // "convert" it into SurfaceFlinger's format
7917 // (a 2x2 matrix + an offset)
7918 // Here we must not transform the position of the surface
7919 // since it is already included in the transformation.
7920 //Slog.i(TAG, "Transform: " + matrix);
7922 tmpMatrix.getValues(tmpFloats);
7923 mDsDx = tmpFloats[Matrix.MSCALE_X];
7924 mDtDx = tmpFloats[Matrix.MSKEW_X];
7925 mDsDy = tmpFloats[Matrix.MSKEW_Y];
7926 mDtDy = tmpFloats[Matrix.MSCALE_Y];
7927 int x = (int)tmpFloats[Matrix.MTRANS_X] + mXOffset;
7928 int y = (int)tmpFloats[Matrix.MTRANS_Y] + mYOffset;
7929 int w = frame.width();
7930 int h = frame.height();
7931 mShownFrame.set(x, y, x+w, y+h);
7933 // Now set the alpha... but because our current hardware
7934 // can't do alpha transformation on a non-opaque surface,
7935 // turn it off if we are running an animation that is also
7936 // transforming since it is more important to have that
7937 // animation be smooth.
7938 mShownAlpha = mAlpha;
7939 if (!mLimitedAlphaCompositing
7940 || (!PixelFormat.formatHasAlpha(mAttrs.format)
7941 || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
7942 && x == frame.left && y == frame.top))) {
7943 //Slog.i(TAG, "Applying alpha transform");
7944 if (selfTransformation) {
7945 mShownAlpha *= mTransformation.getAlpha();
7947 if (attachedTransformation != null) {
7948 mShownAlpha *= attachedTransformation.getAlpha();
7950 if (appTransformation != null) {
7951 mShownAlpha *= appTransformation.getAlpha();
7954 //Slog.i(TAG, "Not applying alpha transform");
7957 if (localLOGV) Slog.v(
7958 TAG, "Continuing animation in " + this +
7959 ": " + mShownFrame +
7960 ", alpha=" + mTransformation.getAlpha());
7964 mShownFrame.set(mFrame);
7965 if (mXOffset != 0 || mYOffset != 0) {
7966 mShownFrame.offset(mXOffset, mYOffset);
7968 mShownAlpha = mAlpha;
7976 * Is this window visible? It is not visible if there is no
7977 * surface, or we are in the process of running an exit animation
7978 * that will remove the surface, or its app token has been hidden.
7980 public boolean isVisibleLw() {
7981 final AppWindowToken atoken = mAppToken;
7982 return mSurface != null && mPolicyVisibility && !mAttachedHidden
7983 && (atoken == null || !atoken.hiddenRequested)
7984 && !mExiting && !mDestroying;
7988 * Like {@link #isVisibleLw}, but also counts a window that is currently
7989 * "hidden" behind the keyguard as visible. This allows us to apply
7990 * things like window flags that impact the keyguard.
7991 * XXX I am starting to think we need to have ANOTHER visibility flag
7992 * for this "hidden behind keyguard" state rather than overloading
7993 * mPolicyVisibility. Ungh.
7995 public boolean isVisibleOrBehindKeyguardLw() {
7996 final AppWindowToken atoken = mAppToken;
7997 return mSurface != null && !mAttachedHidden
7998 && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
7999 && (mOrientationChanging || (!mDrawPending && !mCommitDrawPending))
8000 && !mExiting && !mDestroying;
8004 * Is this window visible, ignoring its app token? It is not visible
8005 * if there is no surface, or we are in the process of running an exit animation
8006 * that will remove the surface.
8008 public boolean isWinVisibleLw() {
8009 final AppWindowToken atoken = mAppToken;
8010 return mSurface != null && mPolicyVisibility && !mAttachedHidden
8011 && (atoken == null || !atoken.hiddenRequested || atoken.animating)
8012 && !mExiting && !mDestroying;
8016 * The same as isVisible(), but follows the current hidden state of
8017 * the associated app token, not the pending requested hidden state.
8019 boolean isVisibleNow() {
8020 return mSurface != null && mPolicyVisibility && !mAttachedHidden
8021 && !mRootToken.hidden && !mExiting && !mDestroying;
8025 * Same as isVisible(), but we also count it as visible between the
8026 * call to IWindowSession.add() and the first relayout().
8028 boolean isVisibleOrAdding() {
8029 final AppWindowToken atoken = mAppToken;
8030 return ((mSurface != null && !mReportDestroySurface)
8031 || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
8032 && mPolicyVisibility && !mAttachedHidden
8033 && (atoken == null || !atoken.hiddenRequested)
8034 && !mExiting && !mDestroying;
8038 * Is this window currently on-screen? It is on-screen either if it
8039 * is visible or it is currently running an animation before no longer
8042 boolean isOnScreen() {
8043 final AppWindowToken atoken = mAppToken;
8044 if (atoken != null) {
8045 return mSurface != null && mPolicyVisibility && !mDestroying
8046 && ((!mAttachedHidden && !atoken.hiddenRequested)
8047 || mAnimation != null || atoken.animation != null);
8049 return mSurface != null && mPolicyVisibility && !mDestroying
8050 && (!mAttachedHidden || mAnimation != null);
8055 * Like isOnScreen(), but we don't return true if the window is part
8056 * of a transition that has not yet been started.
8058 boolean isReadyForDisplay() {
8059 if (mRootToken.waitingToShow &&
8060 mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
8063 final AppWindowToken atoken = mAppToken;
8064 final boolean animating = atoken != null
8065 ? (atoken.animation != null) : false;
8066 return mSurface != null && mPolicyVisibility && !mDestroying
8067 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
8068 && !mRootToken.hidden)
8069 || mAnimation != null || animating);
8072 /** Is the window or its container currently animating? */
8073 boolean isAnimating() {
8074 final WindowState attached = mAttachedWindow;
8075 final AppWindowToken atoken = mAppToken;
8076 return mAnimation != null
8077 || (attached != null && attached.mAnimation != null)
8078 || (atoken != null &&
8079 (atoken.animation != null
8080 || atoken.inPendingTransaction));
8083 /** Is this window currently animating? */
8084 boolean isWindowAnimating() {
8085 return mAnimation != null;
8089 * Like isOnScreen, but returns false if the surface hasn't yet
8092 public boolean isDisplayedLw() {
8093 final AppWindowToken atoken = mAppToken;
8094 return mSurface != null && mPolicyVisibility && !mDestroying
8095 && !mDrawPending && !mCommitDrawPending
8096 && ((!mAttachedHidden &&
8097 (atoken == null || !atoken.hiddenRequested))
8102 * Returns true if the window has a surface that it has drawn a
8103 * complete UI in to. Note that this returns true if the orientation
8104 * is changing even if the window hasn't redrawn because we don't want
8105 * to stop things from executing during that time.
8107 public boolean isDrawnLw() {
8108 final AppWindowToken atoken = mAppToken;
8109 return mSurface != null && !mDestroying
8110 && (mOrientationChanging || (!mDrawPending && !mCommitDrawPending));
8113 public boolean fillsScreenLw(int screenWidth, int screenHeight,
8114 boolean shownFrame, boolean onlyOpaque) {
8115 if (mSurface == null) {
8118 if (mAppToken != null && !mAppToken.appFullscreen) {
8121 if (onlyOpaque && mAttrs.format != PixelFormat.OPAQUE) {
8124 final Rect frame = shownFrame ? mShownFrame : mFrame;
8126 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
8127 return frame.left <= mCompatibleScreenFrame.left &&
8128 frame.top <= mCompatibleScreenFrame.top &&
8129 frame.right >= mCompatibleScreenFrame.right &&
8130 frame.bottom >= mCompatibleScreenFrame.bottom;
8132 return frame.left <= 0 && frame.top <= 0
8133 && frame.right >= screenWidth
8134 && frame.bottom >= screenHeight;
8139 * Return true if the window is opaque and fully drawn. This indicates
8140 * it may obscure windows behind it.
8142 boolean isOpaqueDrawn() {
8143 return (mAttrs.format == PixelFormat.OPAQUE
8144 || mAttrs.type == TYPE_WALLPAPER)
8145 && mSurface != null && mAnimation == null
8146 && (mAppToken == null || mAppToken.animation == null)
8147 && !mDrawPending && !mCommitDrawPending;
8150 boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
8152 // only if the application is requesting compatible window
8153 (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
8154 // only if it's visible
8155 mHasDrawn && mViewVisibility == View.VISIBLE &&
8156 // and only if the application fills the compatible screen
8157 mFrame.left <= mCompatibleScreenFrame.left &&
8158 mFrame.top <= mCompatibleScreenFrame.top &&
8159 mFrame.right >= mCompatibleScreenFrame.right &&
8160 mFrame.bottom >= mCompatibleScreenFrame.bottom &&
8161 // and starting window do not need background filler
8162 mAttrs.type != mAttrs.TYPE_APPLICATION_STARTING;
8165 boolean isFullscreen(int screenWidth, int screenHeight) {
8166 return mFrame.left <= 0 && mFrame.top <= 0 &&
8167 mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
8170 void removeLocked() {
8171 if (mAttachedWindow != null) {
8172 mAttachedWindow.mChildWindows.remove(this);
8174 destroySurfaceLocked();
8175 mSession.windowRemovedLocked();
8177 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
8178 } catch (RuntimeException e) {
8179 // Ignore if it has already been removed (usually because
8180 // we are doing this as part of processing a death note.)
8184 private class DeathRecipient implements IBinder.DeathRecipient {
8185 public void binderDied() {
8187 synchronized(mWindowMap) {
8188 WindowState win = windowForClientLocked(mSession, mClient, false);
8189 Slog.i(TAG, "WIN DEATH: " + win);
8191 removeWindowLocked(mSession, win);
8194 } catch (IllegalArgumentException ex) {
8195 // This will happen if the window has already been
8201 /** Returns true if this window desires key events. */
8202 public final boolean canReceiveKeys() {
8203 return isVisibleOrAdding()
8204 && (mViewVisibility == View.VISIBLE)
8205 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
8208 public boolean hasDrawnLw() {
8212 public boolean showLw(boolean doAnimation) {
8213 return showLw(doAnimation, true);
8216 boolean showLw(boolean doAnimation, boolean requestAnim) {
8217 if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
8220 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
8222 if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
8223 + mPolicyVisibility + " mAnimation=" + mAnimation);
8224 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
8225 doAnimation = false;
8226 } else if (mPolicyVisibility && mAnimation == null) {
8227 // Check for the case where we are currently visible and
8228 // not animating; we do not want to do animation at such a
8229 // point to become visible when we already are.
8230 doAnimation = false;
8233 mPolicyVisibility = true;
8234 mPolicyVisibilityAfterAnim = true;
8236 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
8239 requestAnimationLocked(0);
8244 public boolean hideLw(boolean doAnimation) {
8245 return hideLw(doAnimation, true);
8248 boolean hideLw(boolean doAnimation, boolean requestAnim) {
8250 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
8251 doAnimation = false;
8254 boolean current = doAnimation ? mPolicyVisibilityAfterAnim
8255 : mPolicyVisibility;
8260 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
8261 if (mAnimation == null) {
8262 doAnimation = false;
8266 mPolicyVisibilityAfterAnim = false;
8268 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
8269 mPolicyVisibilityAfterAnim = false;
8270 mPolicyVisibility = false;
8271 // Window is no longer visible -- make sure if we were waiting
8272 // for it to be displayed before enabling the display, that
8273 // we allow the display to be enabled now.
8274 enableScreenIfNeededLocked();
8275 if (mCurrentFocus == this) {
8276 mFocusMayChange = true;
8280 requestAnimationLocked(0);
8285 void dump(PrintWriter pw, String prefix) {
8286 pw.print(prefix); pw.print("mSession="); pw.print(mSession);
8287 pw.print(" mClient="); pw.println(mClient.asBinder());
8288 pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
8289 if (mAttachedWindow != null || mLayoutAttached) {
8290 pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
8291 pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
8293 if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
8294 pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
8295 pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
8296 pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
8297 pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
8299 pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
8300 pw.print(" mSubLayer="); pw.print(mSubLayer);
8301 pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
8302 pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
8303 : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
8304 pw.print("="); pw.print(mAnimLayer);
8305 pw.print(" mLastLayer="); pw.println(mLastLayer);
8306 if (mSurface != null) {
8307 pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
8308 pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
8309 pw.print(" layer="); pw.print(mSurfaceLayer);
8310 pw.print(" alpha="); pw.print(mSurfaceAlpha);
8311 pw.print(" rect=("); pw.print(mSurfaceX);
8312 pw.print(","); pw.print(mSurfaceY);
8313 pw.print(") "); pw.print(mSurfaceW);
8314 pw.print(" x "); pw.println(mSurfaceH);
8316 pw.print(prefix); pw.print("mToken="); pw.println(mToken);
8317 pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
8318 if (mAppToken != null) {
8319 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
8321 if (mTargetAppToken != null) {
8322 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
8324 pw.print(prefix); pw.print("mViewVisibility=0x");
8325 pw.print(Integer.toHexString(mViewVisibility));
8326 pw.print(" mLastHidden="); pw.print(mLastHidden);
8327 pw.print(" mHaveFrame="); pw.print(mHaveFrame);
8328 pw.print(" mObscured="); pw.println(mObscured);
8329 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
8330 pw.print(prefix); pw.print("mPolicyVisibility=");
8331 pw.print(mPolicyVisibility);
8332 pw.print(" mPolicyVisibilityAfterAnim=");
8333 pw.print(mPolicyVisibilityAfterAnim);
8334 pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
8336 if (!mRelayoutCalled) {
8337 pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
8339 pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
8340 pw.print(" h="); pw.print(mRequestedHeight);
8341 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
8342 if (mXOffset != 0 || mYOffset != 0) {
8343 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
8344 pw.print(" y="); pw.println(mYOffset);
8346 pw.print(prefix); pw.print("mGivenContentInsets=");
8347 mGivenContentInsets.printShortString(pw);
8348 pw.print(" mGivenVisibleInsets=");
8349 mGivenVisibleInsets.printShortString(pw);
8351 if (mTouchableInsets != 0 || mGivenInsetsPending) {
8352 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
8353 pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
8355 pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
8356 pw.print(prefix); pw.print("mShownFrame=");
8357 mShownFrame.printShortString(pw);
8358 pw.print(" last="); mLastShownFrame.printShortString(pw);
8360 pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
8361 pw.print(" last="); mLastFrame.printShortString(pw);
8363 pw.print(prefix); pw.print("mContainingFrame=");
8364 mContainingFrame.printShortString(pw);
8365 pw.print(" mDisplayFrame=");
8366 mDisplayFrame.printShortString(pw);
8368 pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
8369 pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
8371 pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
8372 pw.print(" last="); mLastContentInsets.printShortString(pw);
8373 pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
8374 pw.print(" last="); mLastVisibleInsets.printShortString(pw);
8376 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
8377 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
8378 pw.print(" mAlpha="); pw.print(mAlpha);
8379 pw.print(" mLastAlpha="); pw.println(mLastAlpha);
8381 if (mAnimating || mLocalAnimating || mAnimationIsEntrance
8382 || mAnimation != null) {
8383 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
8384 pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
8385 pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
8386 pw.print(" mAnimation="); pw.println(mAnimation);
8388 if (mHasTransformation || mHasLocalTransformation) {
8389 pw.print(prefix); pw.print("XForm: has=");
8390 pw.print(mHasTransformation);
8391 pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
8392 pw.print(" "); mTransformation.printShortString(pw);
8395 pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
8396 pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
8397 pw.print(" mReadyToShow="); pw.print(mReadyToShow);
8398 pw.print(" mHasDrawn="); pw.println(mHasDrawn);
8399 if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
8400 pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
8401 pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
8402 pw.print(" mDestroying="); pw.print(mDestroying);
8403 pw.print(" mRemoved="); pw.println(mRemoved);
8405 if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
8406 pw.print(prefix); pw.print("mOrientationChanging=");
8407 pw.print(mOrientationChanging);
8408 pw.print(" mAppFreezing="); pw.print(mAppFreezing);
8409 pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
8411 if (mHScale != 1 || mVScale != 1) {
8412 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
8413 pw.print(" mVScale="); pw.println(mVScale);
8415 if (mWallpaperX != -1 || mWallpaperY != -1) {
8416 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
8417 pw.print(" mWallpaperY="); pw.println(mWallpaperY);
8419 if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
8420 pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
8421 pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
8426 public String toString() {
8428 + Integer.toHexString(System.identityHashCode(this))
8429 + " " + mAttrs.getTitle() + " paused=" + mToken.paused + "}";
8433 // -------------------------------------------------------------
8434 // Window Token State
8435 // -------------------------------------------------------------
8438 // The actual token.
8439 final IBinder token;
8441 // The type of window this token is for, as per WindowManager.LayoutParams.
8442 final int windowType;
8444 // Set if this token was explicitly added by a client, so should
8445 // not be removed when all windows are removed.
8446 final boolean explicit;
8451 // If this is an AppWindowToken, this is non-null.
8452 AppWindowToken appWindowToken;
8454 // All of the windows associated with this token.
8455 final ArrayList<WindowState> windows = new ArrayList<WindowState>();
8457 // Is key dispatching paused for this token?
8458 boolean paused = false;
8460 // Should this token's windows be hidden?
8463 // Temporary for finding which tokens no longer have visible windows.
8466 // Set to true when this token is in a pending transaction where it
8468 boolean waitingToShow;
8470 // Set to true when this token is in a pending transaction where it
8472 boolean waitingToHide;
8474 // Set to true when this token is in a pending transaction where its
8475 // windows will be put to the bottom of the list.
8476 boolean sendingToBottom;
8478 // Set to true when this token is in a pending transaction where its
8479 // windows will be put to the top of the list.
8480 boolean sendingToTop;
8482 WindowToken(IBinder _token, int type, boolean _explicit) {
8485 explicit = _explicit;
8488 void dump(PrintWriter pw, String prefix) {
8489 pw.print(prefix); pw.print("token="); pw.println(token);
8490 pw.print(prefix); pw.print("windows="); pw.println(windows);
8491 pw.print(prefix); pw.print("windowType="); pw.print(windowType);
8492 pw.print(" hidden="); pw.print(hidden);
8493 pw.print(" hasVisible="); pw.println(hasVisible);
8494 if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) {
8495 pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
8496 pw.print(" waitingToHide="); pw.print(waitingToHide);
8497 pw.print(" sendingToBottom="); pw.print(sendingToBottom);
8498 pw.print(" sendingToTop="); pw.println(sendingToTop);
8503 public String toString() {
8504 if (stringName == null) {
8505 StringBuilder sb = new StringBuilder();
8506 sb.append("WindowToken{");
8507 sb.append(Integer.toHexString(System.identityHashCode(this)));
8508 sb.append(" token="); sb.append(token); sb.append('}');
8509 stringName = sb.toString();
8515 class AppWindowToken extends WindowToken {
8516 // Non-null only for application tokens.
8517 final IApplicationToken appToken;
8519 // All of the windows and child windows that are included in this
8520 // application token. Note this list is NOT sorted!
8521 final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
8524 boolean appFullscreen;
8525 int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
8527 // These are used for determining when all windows associated with
8528 // an activity have been drawn, so they can be made visible together
8529 // at the same time.
8530 int lastTransactionSequence = mTransactionSequence-1;
8531 int numInterestingWindows;
8532 int numDrawnWindows;
8533 boolean inPendingTransaction;
8536 // Is this token going to be hidden in a little while? If so, it
8537 // won't be taken into account for setting the screen orientation.
8538 boolean willBeHidden;
8540 // Is this window's surface needed? This is almost like hidden, except
8541 // it will sometimes be true a little earlier: when the token has
8542 // been shown, but is still waiting for its app transition to execute
8543 // before making its windows shown.
8544 boolean hiddenRequested;
8546 // Have we told the window clients to hide themselves?
8547 boolean clientHidden;
8549 // Last visibility state we reported to the app token.
8550 boolean reportedVisible;
8552 // Set to true when the token has been removed from the window mgr.
8555 // Have we been asked to have this token keep the screen frozen?
8556 boolean freezingScreen;
8559 Animation animation;
8560 boolean hasTransformation;
8561 final Transformation transformation = new Transformation();
8563 // Offset to the window of all layers in the token, for use by
8564 // AppWindowToken animations.
8565 int animLayerAdjustment;
8567 // Information about an application starting window if displayed.
8568 StartingData startingData;
8569 WindowState startingWindow;
8571 boolean startingDisplayed;
8572 boolean startingMoved;
8573 boolean firstWindowDrawn;
8575 AppWindowToken(IApplicationToken _token) {
8576 super(_token.asBinder(),
8577 WindowManager.LayoutParams.TYPE_APPLICATION, true);
8578 appWindowToken = this;
8582 public void setAnimation(Animation anim) {
8583 if (localLOGV) Slog.v(
8584 TAG, "Setting animation in " + this + ": " + anim);
8587 anim.restrictDuration(MAX_ANIMATION_DURATION);
8588 anim.scaleCurrentDuration(mTransitionAnimationScale);
8589 int zorder = anim.getZAdjustment();
8591 if (zorder == Animation.ZORDER_TOP) {
8592 adj = TYPE_LAYER_OFFSET;
8593 } else if (zorder == Animation.ZORDER_BOTTOM) {
8594 adj = -TYPE_LAYER_OFFSET;
8597 if (animLayerAdjustment != adj) {
8598 animLayerAdjustment = adj;
8603 public void setDummyAnimation() {
8604 if (animation == null) {
8605 if (localLOGV) Slog.v(
8606 TAG, "Setting dummy animation in " + this);
8607 animation = sDummyAnimation;
8611 public void clearAnimation() {
8612 if (animation != null) {
8618 void updateLayers() {
8619 final int N = allAppWindows.size();
8620 final int adj = animLayerAdjustment;
8621 for (int i=0; i<N; i++) {
8622 WindowState w = allAppWindows.get(i);
8623 w.mAnimLayer = w.mLayer + adj;
8624 if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": "
8626 if (w == mInputMethodTarget) {
8627 setInputMethodAnimLayerAdjustment(adj);
8629 if (w == mWallpaperTarget && mLowerWallpaperTarget == null) {
8630 setWallpaperAnimLayerAdjustmentLocked(adj);
8635 void sendAppVisibilityToClients() {
8636 final int N = allAppWindows.size();
8637 for (int i=0; i<N; i++) {
8638 WindowState win = allAppWindows.get(i);
8639 if (win == startingWindow && clientHidden) {
8640 // Don't hide the starting window.
8644 if (DEBUG_VISIBILITY) Slog.v(TAG,
8645 "Setting visibility of " + win + ": " + (!clientHidden));
8646 win.mClient.dispatchAppVisibility(!clientHidden);
8647 } catch (RemoteException e) {
8652 void showAllWindowsLocked() {
8653 final int NW = allAppWindows.size();
8654 for (int i=0; i<NW; i++) {
8655 WindowState w = allAppWindows.get(i);
8656 if (DEBUG_VISIBILITY) Slog.v(TAG,
8657 "performing show on: " + w);
8658 w.performShowLocked();
8662 // This must be called while inside a transaction.
8663 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
8664 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
8665 // We will run animations as long as the display isn't frozen.
8667 if (animation == sDummyAnimation) {
8668 // This guy is going to animate, but not yet. For now count
8669 // it as not animating for purposes of scheduling transactions;
8670 // when it is really time to animate, this will be set to
8671 // a real animation and the next call will execute normally.
8675 if ((allDrawn || animating || startingDisplayed) && animation != null) {
8677 if (DEBUG_ANIM) Slog.v(
8678 TAG, "Starting animation in " + this +
8679 " @ " + currentTime + ": dw=" + dw + " dh=" + dh
8680 + " scale=" + mTransitionAnimationScale
8681 + " allDrawn=" + allDrawn + " animating=" + animating);
8682 animation.initialize(dw, dh, dw, dh);
8683 animation.setStartTime(currentTime);
8686 transformation.clear();
8687 final boolean more = animation.getTransformation(
8688 currentTime, transformation);
8689 if (DEBUG_ANIM) Slog.v(
8690 TAG, "Stepped animation in " + this +
8691 ": more=" + more + ", xform=" + transformation);
8694 hasTransformation = true;
8697 if (DEBUG_ANIM) Slog.v(
8698 TAG, "Finished animation in " + this +
8699 " @ " + currentTime);
8702 } else if (animation != null) {
8703 // If the display is frozen, and there is a pending animation,
8704 // clear it and make sure we run the cleanup code.
8709 hasTransformation = false;
8717 if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) {
8718 moveInputMethodWindowsIfNeededLocked(true);
8721 if (DEBUG_ANIM) Slog.v(
8722 TAG, "Animation done in " + this
8723 + ": reportedVisible=" + reportedVisible);
8725 transformation.clear();
8726 if (animLayerAdjustment != 0) {
8727 animLayerAdjustment = 0;
8731 final int N = windows.size();
8732 for (int i=0; i<N; i++) {
8733 ((WindowState)windows.get(i)).finishExit();
8735 updateReportedVisibilityLocked();
8740 void updateReportedVisibilityLocked() {
8741 if (appToken == null) {
8745 int numInteresting = 0;
8747 boolean nowGone = true;
8749 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
8750 final int N = allAppWindows.size();
8751 for (int i=0; i<N; i++) {
8752 WindowState win = allAppWindows.get(i);
8753 if (win == startingWindow || win.mAppFreezing
8754 || win.mViewVisibility != View.VISIBLE
8755 || win.mAttrs.type == TYPE_APPLICATION_STARTING) {
8758 if (DEBUG_VISIBILITY) {
8759 Slog.v(TAG, "Win " + win + ": isDrawn="
8761 + ", isAnimating=" + win.isAnimating());
8762 if (!win.isDrawnLw()) {
8763 Slog.v(TAG, "Not displayed: s=" + win.mSurface
8764 + " pv=" + win.mPolicyVisibility
8765 + " dp=" + win.mDrawPending
8766 + " cdp=" + win.mCommitDrawPending
8767 + " ah=" + win.mAttachedHidden
8769 + (win.mAppToken != null
8770 ? win.mAppToken.hiddenRequested : false)
8771 + " a=" + win.mAnimating);
8775 if (win.isDrawnLw()) {
8776 if (!win.isAnimating()) {
8780 } else if (win.isAnimating()) {
8785 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
8786 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
8787 + numInteresting + " visible=" + numVisible);
8788 if (nowVisible != reportedVisible) {
8789 if (DEBUG_VISIBILITY) Slog.v(
8790 TAG, "Visibility changed in " + this
8791 + ": vis=" + nowVisible);
8792 reportedVisible = nowVisible;
8793 Message m = mH.obtainMessage(
8794 H.REPORT_APPLICATION_TOKEN_WINDOWS,
8802 WindowState findMainWindow() {
8803 int j = windows.size();
8806 WindowState win = windows.get(j);
8807 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
8808 || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
8815 void dump(PrintWriter pw, String prefix) {
8816 super.dump(pw, prefix);
8817 if (appToken != null) {
8818 pw.print(prefix); pw.println("app=true");
8820 if (allAppWindows.size() > 0) {
8821 pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
8823 pw.print(prefix); pw.print("groupId="); pw.print(groupId);
8824 pw.print(" appFullscreen="); pw.print(appFullscreen);
8825 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
8826 pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
8827 pw.print(" clientHidden="); pw.print(clientHidden);
8828 pw.print(" willBeHidden="); pw.print(willBeHidden);
8829 pw.print(" reportedVisible="); pw.println(reportedVisible);
8830 if (paused || freezingScreen) {
8831 pw.print(prefix); pw.print("paused="); pw.print(paused);
8832 pw.print(" freezingScreen="); pw.println(freezingScreen);
8834 if (numInterestingWindows != 0 || numDrawnWindows != 0
8835 || inPendingTransaction || allDrawn) {
8836 pw.print(prefix); pw.print("numInterestingWindows=");
8837 pw.print(numInterestingWindows);
8838 pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
8839 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
8840 pw.print(" allDrawn="); pw.println(allDrawn);
8842 if (animating || animation != null) {
8843 pw.print(prefix); pw.print("animating="); pw.print(animating);
8844 pw.print(" animation="); pw.println(animation);
8846 if (animLayerAdjustment != 0) {
8847 pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
8849 if (hasTransformation) {
8850 pw.print(prefix); pw.print("hasTransformation="); pw.print(hasTransformation);
8851 pw.print(" transformation="); transformation.printShortString(pw);
8854 if (startingData != null || removed || firstWindowDrawn) {
8855 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
8856 pw.print(" removed="); pw.print(removed);
8857 pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
8859 if (startingWindow != null || startingView != null
8860 || startingDisplayed || startingMoved) {
8861 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
8862 pw.print(" startingView="); pw.print(startingView);
8863 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
8864 pw.print(" startingMoved"); pw.println(startingMoved);
8869 public String toString() {
8870 if (stringName == null) {
8871 StringBuilder sb = new StringBuilder();
8872 sb.append("AppWindowToken{");
8873 sb.append(Integer.toHexString(System.identityHashCode(this)));
8874 sb.append(" token="); sb.append(token); sb.append('}');
8875 stringName = sb.toString();
8881 // -------------------------------------------------------------
8883 // -------------------------------------------------------------
8885 // This is an animation that does nothing: it just immediately finishes
8886 // itself every time it is called. It is used as a stub animation in cases
8887 // where we want to synchronize multiple things that may be animating.
8888 static final class DummyAnimation extends Animation {
8889 public boolean getTransformation(long currentTime, Transformation outTransformation) {
8893 static final Animation sDummyAnimation = new DummyAnimation();
8895 // -------------------------------------------------------------
8897 // -------------------------------------------------------------
8899 static final class StartingData {
8902 final CharSequence nonLocalizedLabel;
8906 StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
8907 int _labelRes, int _icon) {
8910 nonLocalizedLabel = _nonLocalizedLabel;
8911 labelRes = _labelRes;
8916 private final class H extends Handler {
8917 public static final int REPORT_FOCUS_CHANGE = 2;
8918 public static final int REPORT_LOSING_FOCUS = 3;
8919 public static final int ANIMATE = 4;
8920 public static final int ADD_STARTING = 5;
8921 public static final int REMOVE_STARTING = 6;
8922 public static final int FINISHED_STARTING = 7;
8923 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
8924 public static final int WINDOW_FREEZE_TIMEOUT = 11;
8925 public static final int HOLD_SCREEN_CHANGED = 12;
8926 public static final int APP_TRANSITION_TIMEOUT = 13;
8927 public static final int PERSIST_ANIMATION_SCALE = 14;
8928 public static final int FORCE_GC = 15;
8929 public static final int ENABLE_SCREEN = 16;
8930 public static final int APP_FREEZE_TIMEOUT = 17;
8931 public static final int SEND_NEW_CONFIGURATION = 18;
8933 private Session mLastReportedHold;
8939 public void handleMessage(Message msg) {
8941 case REPORT_FOCUS_CHANGE: {
8942 WindowState lastFocus;
8943 WindowState newFocus;
8945 synchronized(mWindowMap) {
8946 lastFocus = mLastFocus;
8947 newFocus = mCurrentFocus;
8948 if (lastFocus == newFocus) {
8949 // Focus is not changing, so nothing to do.
8952 mLastFocus = newFocus;
8953 //Slog.i(TAG, "Focus moving from " + lastFocus
8954 // + " to " + newFocus);
8955 if (newFocus != null && lastFocus != null
8956 && !newFocus.isDisplayedLw()) {
8957 //Slog.i(TAG, "Delaying loss of focus...");
8958 mLosingFocus.add(lastFocus);
8963 if (lastFocus != newFocus) {
8964 //System.out.println("Changing focus from " + lastFocus
8965 // + " to " + newFocus);
8966 if (newFocus != null) {
8968 //Slog.i(TAG, "Gaining focus: " + newFocus);
8969 newFocus.mClient.windowFocusChanged(true, mInTouchMode);
8970 } catch (RemoteException e) {
8971 // Ignore if process has died.
8975 if (lastFocus != null) {
8977 //Slog.i(TAG, "Losing focus: " + lastFocus);
8978 lastFocus.mClient.windowFocusChanged(false, mInTouchMode);
8979 } catch (RemoteException e) {
8980 // Ignore if process has died.
8986 case REPORT_LOSING_FOCUS: {
8987 ArrayList<WindowState> losers;
8989 synchronized(mWindowMap) {
8990 losers = mLosingFocus;
8991 mLosingFocus = new ArrayList<WindowState>();
8994 final int N = losers.size();
8995 for (int i=0; i<N; i++) {
8997 //Slog.i(TAG, "Losing delayed focus: " + losers.get(i));
8998 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode);
8999 } catch (RemoteException e) {
9000 // Ignore if process has died.
9006 synchronized(mWindowMap) {
9007 mAnimationPending = false;
9008 performLayoutAndPlaceSurfacesLocked();
9012 case ADD_STARTING: {
9013 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9014 final StartingData sd = wtoken.startingData;
9017 // Animation has been canceled... do nothing.
9021 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
9022 + wtoken + ": pkg=" + sd.pkg);
9026 view = mPolicy.addStartingWindow(
9027 wtoken.token, sd.pkg,
9028 sd.theme, sd.nonLocalizedLabel, sd.labelRes,
9030 } catch (Exception e) {
9031 Slog.w(TAG, "Exception when adding starting window", e);
9035 boolean abort = false;
9037 synchronized(mWindowMap) {
9038 if (wtoken.removed || wtoken.startingData == null) {
9039 // If the window was successfully added, then
9040 // we need to remove it.
9041 if (wtoken.startingWindow != null) {
9042 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
9043 "Aborted starting " + wtoken
9044 + ": removed=" + wtoken.removed
9045 + " startingData=" + wtoken.startingData);
9046 wtoken.startingWindow = null;
9047 wtoken.startingData = null;
9051 wtoken.startingView = view;
9053 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
9054 "Added starting " + wtoken
9055 + ": startingWindow="
9056 + wtoken.startingWindow + " startingView="
9057 + wtoken.startingView);
9062 mPolicy.removeStartingWindow(wtoken.token, view);
9063 } catch (Exception e) {
9064 Slog.w(TAG, "Exception when removing starting window", e);
9070 case REMOVE_STARTING: {
9071 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9072 IBinder token = null;
9074 synchronized (mWindowMap) {
9075 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
9076 + wtoken + ": startingWindow="
9077 + wtoken.startingWindow + " startingView="
9078 + wtoken.startingView);
9079 if (wtoken.startingWindow != null) {
9080 view = wtoken.startingView;
9081 token = wtoken.token;
9082 wtoken.startingData = null;
9083 wtoken.startingView = null;
9084 wtoken.startingWindow = null;
9089 mPolicy.removeStartingWindow(token, view);
9090 } catch (Exception e) {
9091 Slog.w(TAG, "Exception when removing starting window", e);
9096 case FINISHED_STARTING: {
9097 IBinder token = null;
9100 synchronized (mWindowMap) {
9101 final int N = mFinishedStarting.size();
9105 AppWindowToken wtoken = mFinishedStarting.remove(N-1);
9107 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
9108 "Finished starting " + wtoken
9109 + ": startingWindow=" + wtoken.startingWindow
9110 + " startingView=" + wtoken.startingView);
9112 if (wtoken.startingWindow == null) {
9116 view = wtoken.startingView;
9117 token = wtoken.token;
9118 wtoken.startingData = null;
9119 wtoken.startingView = null;
9120 wtoken.startingWindow = null;
9124 mPolicy.removeStartingWindow(token, view);
9125 } catch (Exception e) {
9126 Slog.w(TAG, "Exception when removing starting window", e);
9131 case REPORT_APPLICATION_TOKEN_WINDOWS: {
9132 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9134 boolean nowVisible = msg.arg1 != 0;
9135 boolean nowGone = msg.arg2 != 0;
9138 if (DEBUG_VISIBILITY) Slog.v(
9139 TAG, "Reporting visible in " + wtoken
9140 + " visible=" + nowVisible
9141 + " gone=" + nowGone);
9143 wtoken.appToken.windowsVisible();
9145 wtoken.appToken.windowsGone();
9147 } catch (RemoteException ex) {
9151 case WINDOW_FREEZE_TIMEOUT: {
9152 synchronized (mWindowMap) {
9153 Slog.w(TAG, "Window freeze timeout expired.");
9154 int i = mWindows.size();
9157 WindowState w = (WindowState)mWindows.get(i);
9158 if (w.mOrientationChanging) {
9159 w.mOrientationChanging = false;
9160 Slog.w(TAG, "Force clearing orientation change: " + w);
9163 performLayoutAndPlaceSurfacesLocked();
9168 case HOLD_SCREEN_CHANGED: {
9171 synchronized (mWindowMap) {
9172 oldHold = mLastReportedHold;
9173 newHold = (Session)msg.obj;
9174 mLastReportedHold = newHold;
9177 if (oldHold != newHold) {
9179 if (oldHold != null) {
9180 mBatteryStats.noteStopWakelock(oldHold.mUid,
9182 BatteryStats.WAKE_TYPE_WINDOW);
9184 if (newHold != null) {
9185 mBatteryStats.noteStartWakelock(newHold.mUid,
9187 BatteryStats.WAKE_TYPE_WINDOW);
9189 } catch (RemoteException e) {
9195 case APP_TRANSITION_TIMEOUT: {
9196 synchronized (mWindowMap) {
9197 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
9198 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
9199 "*** APP TRANSITION TIMEOUT");
9200 mAppTransitionReady = true;
9201 mAppTransitionTimeout = true;
9202 performLayoutAndPlaceSurfacesLocked();
9208 case PERSIST_ANIMATION_SCALE: {
9209 Settings.System.putFloat(mContext.getContentResolver(),
9210 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
9211 Settings.System.putFloat(mContext.getContentResolver(),
9212 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
9217 synchronized(mWindowMap) {
9218 if (mAnimationPending) {
9219 // If we are animating, don't do the gc now but
9220 // delay a bit so we don't interrupt the animation.
9221 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
9225 // If we are currently rotating the display, it will
9226 // schedule a new message when done.
9227 if (mDisplayFrozen) {
9230 mFreezeGcPending = 0;
9232 Runtime.getRuntime().gc();
9236 case ENABLE_SCREEN: {
9237 performEnableScreen();
9241 case APP_FREEZE_TIMEOUT: {
9242 synchronized (mWindowMap) {
9243 Slog.w(TAG, "App freeze timeout expired.");
9244 int i = mAppTokens.size();
9247 AppWindowToken tok = mAppTokens.get(i);
9248 if (tok.freezingScreen) {
9249 Slog.w(TAG, "Force clearing freeze: " + tok);
9250 unsetAppFreezingScreenLocked(tok, true, true);
9257 case SEND_NEW_CONFIGURATION: {
9258 removeMessages(SEND_NEW_CONFIGURATION);
9259 sendNewConfiguration();
9267 // -------------------------------------------------------------
9268 // IWindowManager API
9269 // -------------------------------------------------------------
9271 public IWindowSession openSession(IInputMethodClient client,
9272 IInputContext inputContext) {
9273 if (client == null) throw new IllegalArgumentException("null client");
9274 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
9275 return new Session(client, inputContext);
9278 public boolean inputMethodClientHasFocus(IInputMethodClient client) {
9279 synchronized (mWindowMap) {
9280 // The focus for the client is the window immediately below
9281 // where we would place the input method window.
9282 int idx = findDesiredInputMethodWindowIndexLocked(false);
9283 WindowState imFocus;
9285 imFocus = (WindowState)mWindows.get(idx-1);
9286 if (imFocus != null) {
9287 if (imFocus.mSession.mClient != null &&
9288 imFocus.mSession.mClient.asBinder() == client.asBinder()) {
9297 // -------------------------------------------------------------
9299 // -------------------------------------------------------------
9301 final WindowState windowForClientLocked(Session session, IWindow client,
9302 boolean throwOnError) {
9303 return windowForClientLocked(session, client.asBinder(), throwOnError);
9306 final WindowState windowForClientLocked(Session session, IBinder client,
9307 boolean throwOnError) {
9308 WindowState win = mWindowMap.get(client);
9309 if (localLOGV) Slog.v(
9310 TAG, "Looking up client " + client + ": " + win);
9312 RuntimeException ex = new IllegalArgumentException(
9313 "Requested window " + client + " does not exist");
9317 Slog.w(TAG, "Failed looking up window", ex);
9320 if (session != null && win.mSession != session) {
9321 RuntimeException ex = new IllegalArgumentException(
9322 "Requested window " + client + " is in session " +
9323 win.mSession + ", not " + session);
9327 Slog.w(TAG, "Failed looking up window", ex);
9334 final void rebuildAppWindowListLocked() {
9335 int NW = mWindows.size();
9337 int lastWallpaper = -1;
9340 // First remove all existing app windows.
9343 WindowState w = (WindowState)mWindows.get(i);
9344 if (w.mAppToken != null) {
9345 WindowState win = (WindowState)mWindows.remove(i);
9346 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
9347 "Rebuild removing window: " + win);
9351 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER
9352 && lastWallpaper == i-1) {
9358 // The wallpaper window(s) typically live at the bottom of the stack,
9359 // so skip them before adding app tokens.
9363 // First add all of the exiting app tokens... these are no longer
9364 // in the main app list, but still have windows shown. We put them
9365 // in the back because now that the animation is over we no longer
9366 // will care about them.
9367 int NT = mExitingAppTokens.size();
9368 for (int j=0; j<NT; j++) {
9369 i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j));
9372 // And add in the still active app tokens in Z order.
9373 NT = mAppTokens.size();
9374 for (int j=0; j<NT; j++) {
9375 i = reAddAppWindowsLocked(i, mAppTokens.get(j));
9379 if (i != numRemoved) {
9380 Slog.w(TAG, "Rebuild removed " + numRemoved
9381 + " windows but added " + i);
9385 private final void assignLayersLocked() {
9386 int N = mWindows.size();
9387 int curBaseLayer = 0;
9391 for (i=0; i<N; i++) {
9392 WindowState w = (WindowState)mWindows.get(i);
9393 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
9394 || (i > 0 && w.mIsWallpaper)) {
9395 curLayer += WINDOW_LAYER_MULTIPLIER;
9396 w.mLayer = curLayer;
9398 curBaseLayer = curLayer = w.mBaseLayer;
9399 w.mLayer = curLayer;
9401 if (w.mTargetAppToken != null) {
9402 w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment;
9403 } else if (w.mAppToken != null) {
9404 w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment;
9406 w.mAnimLayer = w.mLayer;
9408 if (w.mIsImWindow) {
9409 w.mAnimLayer += mInputMethodAnimLayerAdjustment;
9410 } else if (w.mIsWallpaper) {
9411 w.mAnimLayer += mWallpaperAnimLayerAdjustment;
9413 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
9415 //System.out.println(
9416 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
9420 private boolean mInLayout = false;
9421 private final void performLayoutAndPlaceSurfacesLocked() {
9424 throw new RuntimeException("Recursive call!");
9426 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout");
9430 if (mWaitingForConfig) {
9431 // Our configuration has changed (most likely rotation), but we
9432 // don't yet have the complete configuration to report to
9433 // applications. Don't do any window layout until we have it.
9437 boolean recoveringMemory = false;
9438 if (mForceRemoves != null) {
9439 recoveringMemory = true;
9440 // Wait a little it for things to settle down, and off we go.
9441 for (int i=0; i<mForceRemoves.size(); i++) {
9442 WindowState ws = mForceRemoves.get(i);
9443 Slog.i(TAG, "Force removing: " + ws);
9444 removeWindowInnerLocked(ws.mSession, ws);
9446 mForceRemoves = null;
9447 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
9448 Object tmp = new Object();
9449 synchronized (tmp) {
9452 } catch (InterruptedException e) {
9459 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
9461 int i = mPendingRemove.size()-1;
9464 WindowState w = mPendingRemove.get(i);
9465 removeWindowInnerLocked(w.mSession, w);
9468 mPendingRemove.clear();
9471 assignLayersLocked();
9472 mLayoutNeeded = true;
9473 performLayoutAndPlaceSurfacesLocked();
9477 if (mLayoutNeeded) {
9478 requestAnimationLocked(0);
9481 } catch (RuntimeException e) {
9483 Slog.e(TAG, "Unhandled exception while layout out windows", e);
9487 private final int performLayoutLockedInner() {
9488 if (!mLayoutNeeded) {
9492 mLayoutNeeded = false;
9494 final int dw = mDisplay.getWidth();
9495 final int dh = mDisplay.getHeight();
9497 final int N = mWindows.size();
9500 if (DEBUG_LAYOUT) Slog.v(TAG, "performLayout: needed="
9501 + mLayoutNeeded + " dw=" + dw + " dh=" + dh);
9503 mPolicy.beginLayoutLw(dw, dh);
9505 int seq = mLayoutSeq+1;
9506 if (seq < 0) seq = 0;
9509 // First perform layout of any root windows (not attached
9510 // to another window).
9511 int topAttached = -1;
9512 for (i = N-1; i >= 0; i--) {
9513 WindowState win = (WindowState) mWindows.get(i);
9515 // Don't do layout of a window if it is not visible, or
9516 // soon won't be visible, to avoid wasting time and funky
9517 // changes while a window is animating away.
9518 final AppWindowToken atoken = win.mAppToken;
9519 final boolean gone = win.mViewVisibility == View.GONE
9520 || !win.mRelayoutCalled
9521 || win.mRootToken.hidden
9522 || (atoken != null && atoken.hiddenRequested)
9523 || win.mAttachedHidden
9524 || win.mExiting || win.mDestroying;
9526 if (!win.mLayoutAttached) {
9527 if (DEBUG_LAYOUT) Slog.v(TAG, "First pass " + win
9528 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
9529 + " mLayoutAttached=" + win.mLayoutAttached);
9530 if (DEBUG_LAYOUT && gone) Slog.v(TAG, " (mViewVisibility="
9531 + win.mViewVisibility + " mRelayoutCalled="
9532 + win.mRelayoutCalled + " hidden="
9533 + win.mRootToken.hidden + " hiddenRequested="
9534 + (atoken != null && atoken.hiddenRequested)
9535 + " mAttachedHidden=" + win.mAttachedHidden);
9538 // If this view is GONE, then skip it -- keep the current
9539 // frame, and let the caller know so they can ignore it
9540 // if they want. (We do the normal layout for INVISIBLE
9541 // windows, since that means "perform layout as normal,
9542 // just don't display").
9543 if (!gone || !win.mHaveFrame) {
9544 if (!win.mLayoutAttached) {
9545 mPolicy.layoutWindowLw(win, win.mAttrs, null);
9546 win.mLayoutSeq = seq;
9547 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
9548 + win.mFrame + " mContainingFrame="
9549 + win.mContainingFrame + " mDisplayFrame="
9550 + win.mDisplayFrame);
9552 if (topAttached < 0) topAttached = i;
9557 // Now perform layout of attached windows, which usually
9558 // depend on the position of the window they are attached to.
9559 // XXX does not deal with windows that are attached to windows
9560 // that are themselves attached.
9561 for (i = topAttached; i >= 0; i--) {
9562 WindowState win = (WindowState) mWindows.get(i);
9564 // If this view is GONE, then skip it -- keep the current
9565 // frame, and let the caller know so they can ignore it
9566 // if they want. (We do the normal layout for INVISIBLE
9567 // windows, since that means "perform layout as normal,
9568 // just don't display").
9569 if (win.mLayoutAttached) {
9570 if (DEBUG_LAYOUT) Slog.v(TAG, "Second pass " + win
9571 + " mHaveFrame=" + win.mHaveFrame
9572 + " mViewVisibility=" + win.mViewVisibility
9573 + " mRelayoutCalled=" + win.mRelayoutCalled);
9574 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
9575 || !win.mHaveFrame) {
9576 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
9577 win.mLayoutSeq = seq;
9578 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
9579 + win.mFrame + " mContainingFrame="
9580 + win.mContainingFrame + " mDisplayFrame="
9581 + win.mDisplayFrame);
9586 return mPolicy.finishLayoutLw();
9589 private final void performLayoutAndPlaceSurfacesLockedInner(
9590 boolean recoveringMemory) {
9591 final long currentTime = SystemClock.uptimeMillis();
9592 final int dw = mDisplay.getWidth();
9593 final int dh = mDisplay.getHeight();
9597 if (mFocusMayChange) {
9598 mFocusMayChange = false;
9599 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
9602 if (mFxSession == null) {
9603 mFxSession = new SurfaceSession();
9606 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
9608 // Initialize state of exiting tokens.
9609 for (i=mExitingTokens.size()-1; i>=0; i--) {
9610 mExitingTokens.get(i).hasVisible = false;
9613 // Initialize state of exiting applications.
9614 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
9615 mExitingAppTokens.get(i).hasVisible = false;
9618 boolean orientationChangeComplete = true;
9619 Session holdScreen = null;
9620 float screenBrightness = -1;
9621 float buttonBrightness = -1;
9622 boolean focusDisplayed = false;
9623 boolean animating = false;
9625 Surface.openTransaction();
9627 boolean wallpaperForceHidingChanged = false;
9634 Slog.w(TAG, "Animation repeat aborted after too many iterations");
9635 mLayoutNeeded = false;
9639 if ((changes&(WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER
9640 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG
9641 | WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT)) != 0) {
9642 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
9643 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
9644 assignLayersLocked();
9645 mLayoutNeeded = true;
9648 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
9649 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
9650 if (updateOrientationFromAppTokensLocked()) {
9651 mLayoutNeeded = true;
9652 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9655 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9656 mLayoutNeeded = true;
9660 // FIRST LOOP: Perform a layout, if needed.
9662 changes = performLayoutLockedInner();
9667 Slog.w(TAG, "Layout repeat skipped after too many iterations");
9671 final int transactionSequence = ++mTransactionSequence;
9673 // Update animations of all applications, including those
9674 // associated with exiting/removed apps
9675 boolean tokensAnimating = false;
9676 final int NAT = mAppTokens.size();
9677 for (i=0; i<NAT; i++) {
9678 if (mAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
9679 tokensAnimating = true;
9682 final int NEAT = mExitingAppTokens.size();
9683 for (i=0; i<NEAT; i++) {
9684 if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
9685 tokensAnimating = true;
9689 // SECOND LOOP: Execute animations and update visibility of windows.
9691 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq="
9692 + transactionSequence + " tokensAnimating="
9695 animating = tokensAnimating;
9697 boolean tokenMayBeDrawn = false;
9698 boolean wallpaperMayChange = false;
9699 boolean forceHiding = false;
9701 mPolicy.beginAnimationLw(dw, dh);
9703 final int N = mWindows.size();
9705 for (i=N-1; i>=0; i--) {
9706 WindowState w = (WindowState)mWindows.get(i);
9708 final WindowManager.LayoutParams attrs = w.mAttrs;
9710 if (w.mSurface != null) {
9711 // Execute animation.
9712 if (w.commitFinishDrawingLocked(currentTime)) {
9714 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
9715 if (DEBUG_WALLPAPER) Slog.v(TAG,
9716 "First draw done in potential wallpaper target " + w);
9717 wallpaperMayChange = true;
9721 boolean wasAnimating = w.mAnimating;
9722 if (w.stepAnimationLocked(currentTime, dw, dh)) {
9726 if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
9727 wallpaperMayChange = true;
9730 if (mPolicy.doesForceHide(w, attrs)) {
9731 if (!wasAnimating && animating) {
9732 if (DEBUG_VISIBILITY) Slog.v(TAG,
9733 "Animation done that could impact force hide: "
9735 wallpaperForceHidingChanged = true;
9736 mFocusMayChange = true;
9737 } else if (w.isReadyForDisplay() && w.mAnimation == null) {
9740 } else if (mPolicy.canBeForceHidden(w, attrs)) {
9743 changed = w.hideLw(false, false);
9744 if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
9745 "Now policy hidden: " + w);
9747 changed = w.showLw(false, false);
9748 if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
9749 "Now policy shown: " + w);
9751 if (wallpaperForceHidingChanged
9752 && w.isVisibleNow() /*w.isReadyForDisplay()*/) {
9753 // Assume we will need to animate. If
9754 // we don't (because the wallpaper will
9755 // stay with the lock screen), then we will
9757 Animation a = mPolicy.createForceHideEnterAnimation();
9762 if (mCurrentFocus == null ||
9763 mCurrentFocus.mLayer < w.mLayer) {
9764 // We are showing on to of the current
9765 // focus, so re-evaluate focus to make
9766 // sure it is correct.
9767 mFocusMayChange = true;
9771 if (changed && (attrs.flags
9772 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
9773 wallpaperMayChange = true;
9777 mPolicy.animatingWindowLw(w, attrs);
9780 final AppWindowToken atoken = w.mAppToken;
9781 if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
9782 if (atoken.lastTransactionSequence != transactionSequence) {
9783 atoken.lastTransactionSequence = transactionSequence;
9784 atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9785 atoken.startingDisplayed = false;
9787 if ((w.isOnScreen() || w.mAttrs.type
9788 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
9789 && !w.mExiting && !w.mDestroying) {
9790 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
9791 Slog.v(TAG, "Eval win " + w + ": isDrawn="
9793 + ", isAnimating=" + w.isAnimating());
9794 if (!w.isDrawnLw()) {
9795 Slog.v(TAG, "Not displayed: s=" + w.mSurface
9796 + " pv=" + w.mPolicyVisibility
9797 + " dp=" + w.mDrawPending
9798 + " cdp=" + w.mCommitDrawPending
9799 + " ah=" + w.mAttachedHidden
9800 + " th=" + atoken.hiddenRequested
9801 + " a=" + w.mAnimating);
9804 if (w != atoken.startingWindow) {
9805 if (!atoken.freezingScreen || !w.mAppFreezing) {
9806 atoken.numInterestingWindows++;
9807 if (w.isDrawnLw()) {
9808 atoken.numDrawnWindows++;
9809 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
9810 "tokenMayBeDrawn: " + atoken
9811 + " freezingScreen=" + atoken.freezingScreen
9812 + " mAppFreezing=" + w.mAppFreezing);
9813 tokenMayBeDrawn = true;
9816 } else if (w.isDrawnLw()) {
9817 atoken.startingDisplayed = true;
9820 } else if (w.mReadyToShow) {
9821 w.performShowLocked();
9825 changes |= mPolicy.finishAnimationLw();
9827 if (tokenMayBeDrawn) {
9828 // See if any windows have been drawn, so they (and others
9829 // associated with them) can now be shown.
9830 final int NT = mTokenList.size();
9831 for (i=0; i<NT; i++) {
9832 AppWindowToken wtoken = mTokenList.get(i).appWindowToken;
9833 if (wtoken == null) {
9836 if (wtoken.freezingScreen) {
9837 int numInteresting = wtoken.numInterestingWindows;
9838 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
9839 if (DEBUG_VISIBILITY) Slog.v(TAG,
9840 "allDrawn: " + wtoken
9841 + " interesting=" + numInteresting
9842 + " drawn=" + wtoken.numDrawnWindows);
9843 wtoken.showAllWindowsLocked();
9844 unsetAppFreezingScreenLocked(wtoken, false, true);
9845 orientationChangeComplete = true;
9847 } else if (!wtoken.allDrawn) {
9848 int numInteresting = wtoken.numInterestingWindows;
9849 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
9850 if (DEBUG_VISIBILITY) Slog.v(TAG,
9851 "allDrawn: " + wtoken
9852 + " interesting=" + numInteresting
9853 + " drawn=" + wtoken.numDrawnWindows);
9854 wtoken.allDrawn = true;
9855 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
9857 // We can now show all of the drawn windows!
9858 if (!mOpeningApps.contains(wtoken)) {
9859 wtoken.showAllWindowsLocked();
9866 // If we are ready to perform an app transition, check through
9867 // all of the app tokens to be shown and see if they are ready
9869 if (mAppTransitionReady) {
9870 int NN = mOpeningApps.size();
9871 boolean goodToGo = true;
9872 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
9873 "Checking " + NN + " opening apps (frozen="
9874 + mDisplayFrozen + " timeout="
9875 + mAppTransitionTimeout + ")...");
9876 if (!mDisplayFrozen && !mAppTransitionTimeout) {
9877 // If the display isn't frozen, wait to do anything until
9878 // all of the apps are ready. Otherwise just go because
9879 // we'll unfreeze the display when everyone is ready.
9880 for (i=0; i<NN && goodToGo; i++) {
9881 AppWindowToken wtoken = mOpeningApps.get(i);
9882 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
9883 "Check opening app" + wtoken + ": allDrawn="
9884 + wtoken.allDrawn + " startingDisplayed="
9885 + wtoken.startingDisplayed);
9886 if (!wtoken.allDrawn && !wtoken.startingDisplayed
9887 && !wtoken.startingMoved) {
9893 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
9894 int transit = mNextAppTransition;
9895 if (mSkipAppTransitionAnimation) {
9896 transit = WindowManagerPolicy.TRANSIT_UNSET;
9898 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
9899 mAppTransitionReady = false;
9900 mAppTransitionRunning = true;
9901 mAppTransitionTimeout = false;
9902 mStartingIconInTransition = false;
9903 mSkipAppTransitionAnimation = false;
9905 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
9907 // If there are applications waiting to come to the
9908 // top of the stack, now is the time to move their windows.
9909 // (Note that we don't do apps going to the bottom
9910 // here -- we want to keep their windows in the old
9911 // Z-order until the animation completes.)
9912 if (mToTopApps.size() > 0) {
9913 NN = mAppTokens.size();
9914 for (i=0; i<NN; i++) {
9915 AppWindowToken wtoken = mAppTokens.get(i);
9916 if (wtoken.sendingToTop) {
9917 wtoken.sendingToTop = false;
9918 moveAppWindowsLocked(wtoken, NN, false);
9924 WindowState oldWallpaper = mWallpaperTarget;
9926 adjustWallpaperWindowsLocked();
9927 wallpaperMayChange = false;
9929 // The top-most window will supply the layout params,
9930 // and we will determine it below.
9931 LayoutParams animLp = null;
9932 AppWindowToken animToken = null;
9933 int bestAnimLayer = -1;
9935 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
9936 "New wallpaper target=" + mWallpaperTarget
9937 + ", lower target=" + mLowerWallpaperTarget
9938 + ", upper target=" + mUpperWallpaperTarget);
9939 int foundWallpapers = 0;
9940 // Do a first pass through the tokens for two
9942 // (1) Determine if both the closing and opening
9943 // app token sets are wallpaper targets, in which
9944 // case special animations are needed
9945 // (since the wallpaper needs to stay static
9947 // (2) Find the layout params of the top-most
9948 // application window in the tokens, which is
9949 // what will control the animation theme.
9950 final int NC = mClosingApps.size();
9951 NN = NC + mOpeningApps.size();
9952 for (i=0; i<NN; i++) {
9953 AppWindowToken wtoken;
9956 wtoken = mClosingApps.get(i);
9959 wtoken = mOpeningApps.get(i-NC);
9962 if (mLowerWallpaperTarget != null) {
9963 if (mLowerWallpaperTarget.mAppToken == wtoken
9964 || mUpperWallpaperTarget.mAppToken == wtoken) {
9965 foundWallpapers |= mode;
9968 if (wtoken.appFullscreen) {
9969 WindowState ws = wtoken.findMainWindow();
9971 // If this is a compatibility mode
9972 // window, we will always use its anim.
9973 if ((ws.mAttrs.flags&FLAG_COMPATIBLE_WINDOW) != 0) {
9975 animToken = ws.mAppToken;
9976 bestAnimLayer = Integer.MAX_VALUE;
9977 } else if (ws.mLayer > bestAnimLayer) {
9979 animToken = ws.mAppToken;
9980 bestAnimLayer = ws.mLayer;
9986 if (foundWallpapers == 3) {
9987 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
9988 "Wallpaper animation!");
9990 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
9991 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
9992 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
9993 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN;
9995 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
9996 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
9997 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
9998 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE;
10001 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
10002 "New transit: " + transit);
10003 } else if (oldWallpaper != null) {
10004 // We are transitioning from an activity with
10005 // a wallpaper to one without.
10006 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE;
10007 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
10008 "New transit away from wallpaper: " + transit);
10009 } else if (mWallpaperTarget != null) {
10010 // We are transitioning from an activity without
10011 // a wallpaper to now showing the wallpaper
10012 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN;
10013 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
10014 "New transit into wallpaper: " + transit);
10017 if ((transit&WindowManagerPolicy.TRANSIT_ENTER_MASK) != 0) {
10018 mLastEnterAnimToken = animToken;
10019 mLastEnterAnimParams = animLp;
10020 } else if (mLastEnterAnimParams != null) {
10021 animLp = mLastEnterAnimParams;
10022 mLastEnterAnimToken = null;
10023 mLastEnterAnimParams = null;
10026 // If all closing windows are obscured, then there is
10027 // no need to do an animation. This is the case, for
10028 // example, when this transition is being done behind
10029 // the lock screen.
10030 if (!mPolicy.allowAppAnimationsLw()) {
10034 NN = mOpeningApps.size();
10035 for (i=0; i<NN; i++) {
10036 AppWindowToken wtoken = mOpeningApps.get(i);
10037 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
10038 "Now opening app" + wtoken);
10039 wtoken.reportedVisible = false;
10040 wtoken.inPendingTransaction = false;
10041 wtoken.animation = null;
10042 setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
10043 wtoken.updateReportedVisibilityLocked();
10044 wtoken.waitingToShow = false;
10045 wtoken.showAllWindowsLocked();
10047 NN = mClosingApps.size();
10048 for (i=0; i<NN; i++) {
10049 AppWindowToken wtoken = mClosingApps.get(i);
10050 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
10051 "Now closing app" + wtoken);
10052 wtoken.inPendingTransaction = false;
10053 wtoken.animation = null;
10054 setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
10055 wtoken.updateReportedVisibilityLocked();
10056 wtoken.waitingToHide = false;
10057 // Force the allDrawn flag, because we want to start
10058 // this guy's animations regardless of whether it's
10060 wtoken.allDrawn = true;
10063 mNextAppTransitionPackage = null;
10065 mOpeningApps.clear();
10066 mClosingApps.clear();
10068 // This has changed the visibility of windows, so perform
10069 // a new layout to get them all up-to-date.
10070 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
10071 mLayoutNeeded = true;
10072 if (!moveInputMethodWindowsIfNeededLocked(true)) {
10073 assignLayersLocked();
10075 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
10076 mFocusMayChange = false;
10082 if (!animating && mAppTransitionRunning) {
10083 // We have finished the animation of an app transition. To do
10084 // this, we have delayed a lot of operations like showing and
10085 // hiding apps, moving apps in Z-order, etc. The app token list
10086 // reflects the correct Z-order, but the window list may now
10087 // be out of sync with it. So here we will just rebuild the
10088 // entire app window list. Fun!
10089 mAppTransitionRunning = false;
10090 // Clear information about apps that were moving.
10091 mToBottomApps.clear();
10093 rebuildAppWindowListLocked();
10094 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
10095 adjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED;
10096 moveInputMethodWindowsIfNeededLocked(false);
10097 wallpaperMayChange = true;
10098 // Since the window list has been rebuilt, focus might
10099 // have to be recomputed since the actual order of windows
10100 // might have changed again.
10101 mFocusMayChange = true;
10104 if (wallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) {
10105 // At this point, there was a window with a wallpaper that
10106 // was force hiding other windows behind it, but now it
10107 // is going away. This may be simple -- just animate
10108 // away the wallpaper and its window -- or it may be
10109 // hard -- the wallpaper now needs to be shown behind
10110 // something that was hidden.
10111 WindowState oldWallpaper = mWallpaperTarget;
10112 if (mLowerWallpaperTarget != null
10113 && mLowerWallpaperTarget.mAppToken != null) {
10114 if (DEBUG_WALLPAPER) Slog.v(TAG,
10115 "wallpaperForceHiding changed with lower="
10116 + mLowerWallpaperTarget);
10117 if (DEBUG_WALLPAPER) Slog.v(TAG,
10118 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden +
10119 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested);
10120 if (mLowerWallpaperTarget.mAppToken.hidden) {
10121 // The lower target has become hidden before we
10122 // actually started the animation... let's completely
10123 // re-evaluate everything.
10124 mLowerWallpaperTarget = mUpperWallpaperTarget = null;
10125 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
10128 adjResult |= adjustWallpaperWindowsLocked();
10129 wallpaperMayChange = false;
10130 wallpaperForceHidingChanged = false;
10131 if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper
10132 + " NEW: " + mWallpaperTarget
10133 + " LOWER: " + mLowerWallpaperTarget);
10134 if (mLowerWallpaperTarget == null) {
10135 // Whoops, we don't need a special wallpaper animation.
10137 forceHiding = false;
10138 for (i=N-1; i>=0; i--) {
10139 WindowState w = (WindowState)mWindows.get(i);
10140 if (w.mSurface != null) {
10141 final WindowManager.LayoutParams attrs = w.mAttrs;
10142 if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) {
10143 if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows");
10144 forceHiding = true;
10145 } else if (mPolicy.canBeForceHidden(w, attrs)) {
10146 if (!w.mAnimating) {
10147 // We set the animation above so it
10148 // is not yet running.
10149 w.clearAnimation();
10157 if (wallpaperMayChange) {
10158 if (DEBUG_WALLPAPER) Slog.v(TAG,
10159 "Wallpaper may change! Adjusting");
10160 adjResult |= adjustWallpaperWindowsLocked();
10163 if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
10164 if (DEBUG_WALLPAPER) Slog.v(TAG,
10165 "Wallpaper layer changed: assigning layers + relayout");
10166 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
10167 assignLayersLocked();
10168 } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
10169 if (DEBUG_WALLPAPER) Slog.v(TAG,
10170 "Wallpaper visibility changed: relayout");
10171 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
10174 if (mFocusMayChange) {
10175 mFocusMayChange = false;
10176 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES)) {
10177 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
10182 if (mLayoutNeeded) {
10183 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
10186 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
10187 + Integer.toHexString(changes));
10189 } while (changes != 0);
10191 // THIRD LOOP: Update the surfaces of all windows.
10193 final boolean someoneLosingFocus = mLosingFocus.size() != 0;
10195 boolean obscured = false;
10196 boolean blurring = false;
10197 boolean dimming = false;
10198 boolean covered = false;
10199 boolean syswin = false;
10200 boolean backgroundFillerShown = false;
10202 final int N = mWindows.size();
10204 for (i=N-1; i>=0; i--) {
10205 WindowState w = (WindowState)mWindows.get(i);
10207 boolean displayed = false;
10208 final WindowManager.LayoutParams attrs = w.mAttrs;
10209 final int attrFlags = attrs.flags;
10211 if (w.mSurface != null) {
10212 // XXX NOTE: The logic here could be improved. We have
10213 // the decision about whether to resize a window separated
10214 // from whether to hide the surface. This can cause us to
10215 // resize a surface even if we are going to hide it. You
10216 // can see this by (1) holding device in landscape mode on
10217 // home screen; (2) tapping browser icon (device will rotate
10218 // to landscape; (3) tap home. The wallpaper will be resized
10219 // in step 2 but then immediately hidden, causing us to
10220 // have to resize and then redraw it again in step 3. It
10221 // would be nice to figure out how to avoid this, but it is
10222 // difficult because we do need to resize surfaces in some
10223 // cases while they are hidden such as when first showing a
10226 w.computeShownFrameLocked();
10227 if (localLOGV) Slog.v(
10228 TAG, "Placing surface #" + i + " " + w.mSurface
10229 + ": new=" + w.mShownFrame + ", old="
10230 + w.mLastShownFrame);
10234 if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
10235 resize = w.mLastRequestedWidth != w.mRequestedWidth ||
10236 w.mLastRequestedHeight != w.mRequestedHeight;
10237 // for a scaled surface, we just want to use
10238 // the requested size.
10239 width = w.mRequestedWidth;
10240 height = w.mRequestedHeight;
10241 w.mLastRequestedWidth = width;
10242 w.mLastRequestedHeight = height;
10243 w.mLastShownFrame.set(w.mShownFrame);
10245 if (SHOW_TRANSACTIONS) logSurface(w,
10246 "POS " + w.mShownFrame.left
10247 + ", " + w.mShownFrame.top, null);
10248 w.mSurfaceX = w.mShownFrame.left;
10249 w.mSurfaceY = w.mShownFrame.top;
10250 w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
10251 } catch (RuntimeException e) {
10252 Slog.w(TAG, "Error positioning surface in " + w, e);
10253 if (!recoveringMemory) {
10254 reclaimSomeSurfaceMemoryLocked(w, "position");
10258 resize = !w.mLastShownFrame.equals(w.mShownFrame);
10259 width = w.mShownFrame.width();
10260 height = w.mShownFrame.height();
10261 w.mLastShownFrame.set(w.mShownFrame);
10265 if (width < 1) width = 1;
10266 if (height < 1) height = 1;
10267 if (w.mSurface != null) {
10269 if (SHOW_TRANSACTIONS) logSurface(w,
10270 "POS " + w.mShownFrame.left + ","
10271 + w.mShownFrame.top + " SIZE "
10272 + w.mShownFrame.width() + "x"
10273 + w.mShownFrame.height(), null);
10274 w.mSurfaceResized = true;
10275 w.mSurfaceW = width;
10276 w.mSurfaceH = height;
10277 w.mSurface.setSize(width, height);
10278 w.mSurfaceX = w.mShownFrame.left;
10279 w.mSurfaceY = w.mShownFrame.top;
10280 w.mSurface.setPosition(w.mShownFrame.left,
10281 w.mShownFrame.top);
10282 } catch (RuntimeException e) {
10283 // If something goes wrong with the surface (such
10284 // as running out of memory), don't take down the
10286 Slog.e(TAG, "Failure updating surface of " + w
10287 + "size=(" + width + "x" + height
10288 + "), pos=(" + w.mShownFrame.left
10289 + "," + w.mShownFrame.top + ")", e);
10290 if (!recoveringMemory) {
10291 reclaimSomeSurfaceMemoryLocked(w, "size");
10296 if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
10297 w.mContentInsetsChanged =
10298 !w.mLastContentInsets.equals(w.mContentInsets);
10299 w.mVisibleInsetsChanged =
10300 !w.mLastVisibleInsets.equals(w.mVisibleInsets);
10301 boolean configChanged =
10302 w.mConfiguration != mCurConfiguration
10303 && (w.mConfiguration == null
10304 || mCurConfiguration.diff(w.mConfiguration) != 0);
10305 if (DEBUG_CONFIGURATION && configChanged) {
10306 Slog.v(TAG, "Win " + w + " config changed: "
10307 + mCurConfiguration);
10309 if (localLOGV) Slog.v(TAG, "Resizing " + w
10310 + ": configChanged=" + configChanged
10311 + " last=" + w.mLastFrame + " frame=" + w.mFrame);
10312 if (!w.mLastFrame.equals(w.mFrame)
10313 || w.mContentInsetsChanged
10314 || w.mVisibleInsetsChanged
10315 || w.mSurfaceResized
10316 || configChanged) {
10317 w.mLastFrame.set(w.mFrame);
10318 w.mLastContentInsets.set(w.mContentInsets);
10319 w.mLastVisibleInsets.set(w.mVisibleInsets);
10320 // If the screen is currently frozen, then keep
10321 // it frozen until this window draws at its new
10323 if (mDisplayFrozen) {
10324 if (DEBUG_ORIENTATION) Slog.v(TAG,
10325 "Resizing while display frozen: " + w);
10326 w.mOrientationChanging = true;
10327 if (!mWindowsFreezingScreen) {
10328 mWindowsFreezingScreen = true;
10329 // XXX should probably keep timeout from
10330 // when we first froze the display.
10331 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
10332 mH.sendMessageDelayed(mH.obtainMessage(
10333 H.WINDOW_FREEZE_TIMEOUT), 2000);
10336 // If the orientation is changing, then we need to
10337 // hold off on unfreezing the display until this
10338 // window has been redrawn; to do that, we need
10339 // to go through the process of getting informed
10340 // by the application when it has finished drawing.
10341 if (w.mOrientationChanging) {
10342 if (DEBUG_ORIENTATION) Slog.v(TAG,
10343 "Orientation start waiting for draw in "
10344 + w + ", surface " + w.mSurface);
10345 w.mDrawPending = true;
10346 w.mCommitDrawPending = false;
10347 w.mReadyToShow = false;
10348 if (w.mAppToken != null) {
10349 w.mAppToken.allDrawn = false;
10352 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
10353 "Resizing window " + w + " to " + w.mFrame);
10354 mResizingWindows.add(w);
10355 } else if (w.mOrientationChanging) {
10356 if (!w.mDrawPending && !w.mCommitDrawPending) {
10357 if (DEBUG_ORIENTATION) Slog.v(TAG,
10358 "Orientation not waiting for draw in "
10359 + w + ", surface " + w.mSurface);
10360 w.mOrientationChanging = false;
10365 if (w.mAttachedHidden || !w.isReadyForDisplay()) {
10366 if (!w.mLastHidden) {
10368 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Window hiding: waitingToShow="
10369 + w.mRootToken.waitingToShow + " polvis="
10370 + w.mPolicyVisibility + " atthid="
10371 + w.mAttachedHidden + " tokhid="
10372 + w.mRootToken.hidden + " vis="
10373 + w.mViewVisibility);
10374 w.mLastHidden = true;
10375 if (SHOW_TRANSACTIONS) logSurface(w,
10376 "HIDE (performLayout)", null);
10377 if (w.mSurface != null) {
10378 w.mSurfaceShown = false;
10381 } catch (RuntimeException e) {
10382 Slog.w(TAG, "Exception hiding surface in " + w);
10385 mKeyWaiter.releasePendingPointerLocked(w.mSession);
10387 // If we are waiting for this window to handle an
10388 // orientation change, well, it is hidden, so
10389 // doesn't really matter. Note that this does
10390 // introduce a potential glitch if the window
10391 // becomes unhidden before it has drawn for the
10392 // new orientation.
10393 if (w.mOrientationChanging) {
10394 w.mOrientationChanging = false;
10395 if (DEBUG_ORIENTATION) Slog.v(TAG,
10396 "Orientation change skips hidden " + w);
10398 } else if (w.mLastLayer != w.mAnimLayer
10399 || w.mLastAlpha != w.mShownAlpha
10400 || w.mLastDsDx != w.mDsDx
10401 || w.mLastDtDx != w.mDtDx
10402 || w.mLastDsDy != w.mDsDy
10403 || w.mLastDtDy != w.mDtDy
10404 || w.mLastHScale != w.mHScale
10405 || w.mLastVScale != w.mVScale
10406 || w.mLastHidden) {
10408 w.mLastAlpha = w.mShownAlpha;
10409 w.mLastLayer = w.mAnimLayer;
10410 w.mLastDsDx = w.mDsDx;
10411 w.mLastDtDx = w.mDtDx;
10412 w.mLastDsDy = w.mDsDy;
10413 w.mLastDtDy = w.mDtDy;
10414 w.mLastHScale = w.mHScale;
10415 w.mLastVScale = w.mVScale;
10416 if (SHOW_TRANSACTIONS) logSurface(w,
10417 "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer
10418 + " matrix=[" + (w.mDsDx*w.mHScale)
10419 + "," + (w.mDtDx*w.mVScale)
10420 + "][" + (w.mDsDy*w.mHScale)
10421 + "," + (w.mDtDy*w.mVScale) + "]", null);
10422 if (w.mSurface != null) {
10424 w.mSurfaceAlpha = w.mShownAlpha;
10425 w.mSurface.setAlpha(w.mShownAlpha);
10426 w.mSurfaceLayer = w.mAnimLayer;
10427 w.mSurface.setLayer(w.mAnimLayer);
10428 w.mSurface.setMatrix(
10429 w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
10430 w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
10431 } catch (RuntimeException e) {
10432 Slog.w(TAG, "Error updating surface in " + w, e);
10433 if (!recoveringMemory) {
10434 reclaimSomeSurfaceMemoryLocked(w, "update");
10439 if (w.mLastHidden && !w.mDrawPending
10440 && !w.mCommitDrawPending
10441 && !w.mReadyToShow) {
10442 if (SHOW_TRANSACTIONS) logSurface(w,
10443 "SHOW (performLayout)", null);
10444 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w
10445 + " during relayout");
10446 if (showSurfaceRobustlyLocked(w)) {
10447 w.mHasDrawn = true;
10448 w.mLastHidden = false;
10450 w.mOrientationChanging = false;
10453 if (w.mSurface != null) {
10454 w.mToken.hasVisible = true;
10462 if (attrs.width == LayoutParams.MATCH_PARENT
10463 && attrs.height == LayoutParams.MATCH_PARENT) {
10467 if (w.mOrientationChanging) {
10468 if (w.mDrawPending || w.mCommitDrawPending) {
10469 orientationChangeComplete = false;
10470 if (DEBUG_ORIENTATION) Slog.v(TAG,
10471 "Orientation continue waiting for draw in " + w);
10473 w.mOrientationChanging = false;
10474 if (DEBUG_ORIENTATION) Slog.v(TAG,
10475 "Orientation change complete in " + w);
10478 w.mToken.hasVisible = true;
10480 } else if (w.mOrientationChanging) {
10481 if (DEBUG_ORIENTATION) Slog.v(TAG,
10482 "Orientation change skips hidden " + w);
10483 w.mOrientationChanging = false;
10486 final boolean canBeSeen = w.isDisplayedLw();
10488 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) {
10489 focusDisplayed = true;
10492 final boolean obscuredChanged = w.mObscured != obscured;
10495 if (!(w.mObscured=obscured)) {
10496 if (w.mSurface != null) {
10497 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
10498 holdScreen = w.mSession;
10500 if (!syswin && w.mAttrs.screenBrightness >= 0
10501 && screenBrightness < 0) {
10502 screenBrightness = w.mAttrs.screenBrightness;
10504 if (!syswin && w.mAttrs.buttonBrightness >= 0
10505 && buttonBrightness < 0) {
10506 buttonBrightness = w.mAttrs.buttonBrightness;
10509 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
10510 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD
10511 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) {
10516 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
10517 if (opaqueDrawn && w.isFullscreen(dw, dh)) {
10518 // This window completely covers everything behind it,
10519 // so we want to leave all of them as unblurred (for
10520 // performance reasons).
10522 } else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) {
10523 if (SHOW_TRANSACTIONS) Slog.d(TAG, "showing background filler");
10524 // This window is in compatibility mode, and needs background filler.
10526 if (mBackgroundFillerSurface == null) {
10528 mBackgroundFillerSurface = new Surface(mFxSession, 0,
10529 "BackGroundFiller",
10531 PixelFormat.OPAQUE,
10532 Surface.FX_SURFACE_NORMAL);
10533 } catch (Exception e) {
10534 Slog.e(TAG, "Exception creating filler surface", e);
10538 mBackgroundFillerSurface.setPosition(0, 0);
10539 mBackgroundFillerSurface.setSize(dw, dh);
10540 // Using the same layer as Dim because they will never be shown at the
10542 mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1);
10543 mBackgroundFillerSurface.show();
10544 } catch (RuntimeException e) {
10545 Slog.e(TAG, "Exception showing filler surface");
10547 backgroundFillerShown = true;
10548 mBackgroundFillerShown = true;
10549 } else if (canBeSeen && !obscured &&
10550 (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
10551 if (localLOGV) Slog.v(TAG, "Win " + w
10552 + ": blurring=" + blurring
10553 + " obscured=" + obscured
10554 + " displayed=" + displayed);
10555 if ((attrFlags&FLAG_DIM_BEHIND) != 0) {
10557 //Slog.i(TAG, "DIM BEHIND: " + w);
10559 if (mDimAnimator == null) {
10560 mDimAnimator = new DimAnimator(mFxSession);
10562 mDimAnimator.show(dw, dh);
10563 mDimAnimator.updateParameters(w, currentTime);
10566 if ((attrFlags&FLAG_BLUR_BEHIND) != 0) {
10568 //Slog.i(TAG, "BLUR BEHIND: " + w);
10570 if (mBlurSurface == null) {
10571 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
10572 + mBlurSurface + ": CREATE");
10574 mBlurSurface = new Surface(mFxSession, 0,
10577 PixelFormat.OPAQUE,
10578 Surface.FX_SURFACE_BLUR);
10579 } catch (Exception e) {
10580 Slog.e(TAG, "Exception creating Blur surface", e);
10583 if (mBlurSurface != null) {
10584 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
10585 + mBlurSurface + ": pos=(0,0) (" +
10586 dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
10587 mBlurSurface.setPosition(0, 0);
10588 mBlurSurface.setSize(dw, dh);
10589 mBlurSurface.setLayer(w.mAnimLayer-2);
10592 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
10593 + mBlurSurface + ": SHOW");
10594 mBlurSurface.show();
10595 } catch (RuntimeException e) {
10596 Slog.w(TAG, "Failure showing blur surface", e);
10606 if (obscuredChanged && mWallpaperTarget == w) {
10607 // This is the wallpaper target and its obscured state
10608 // changed... make sure the current wallaper's visibility
10609 // has been updated accordingly.
10610 updateWallpaperVisibilityLocked();
10614 if (backgroundFillerShown == false && mBackgroundFillerShown) {
10615 mBackgroundFillerShown = false;
10616 if (SHOW_TRANSACTIONS) Slog.d(TAG, "hiding background filler");
10618 mBackgroundFillerSurface.hide();
10619 } catch (RuntimeException e) {
10620 Slog.e(TAG, "Exception hiding filler surface", e);
10624 if (mDimAnimator != null && mDimAnimator.mDimShown) {
10625 animating |= mDimAnimator.updateSurface(dimming, currentTime,
10626 mDisplayFrozen || !mPolicy.isScreenOn());
10629 if (!blurring && mBlurShown) {
10630 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " + mBlurSurface
10633 mBlurSurface.hide();
10634 } catch (IllegalArgumentException e) {
10635 Slog.w(TAG, "Illegal argument exception hiding blur surface");
10637 mBlurShown = false;
10640 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
10641 } catch (RuntimeException e) {
10642 Slog.e(TAG, "Unhandled exception in Window Manager", e);
10645 Surface.closeTransaction();
10647 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
10648 "With display frozen, orientationChangeComplete="
10649 + orientationChangeComplete);
10650 if (orientationChangeComplete) {
10651 if (mWindowsFreezingScreen) {
10652 mWindowsFreezingScreen = false;
10653 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
10655 stopFreezingDisplayLocked();
10658 i = mResizingWindows.size();
10662 WindowState win = mResizingWindows.get(i);
10664 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
10665 "Reporting new frame to " + win + ": " + win.mFrame);
10667 boolean configChanged =
10668 win.mConfiguration != mCurConfiguration
10669 && (win.mConfiguration == null
10670 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0);
10671 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
10672 && configChanged) {
10673 Slog.i(TAG, "Sending new config to window " + win + ": "
10674 + win.mFrame.width() + "x" + win.mFrame.height()
10675 + " / " + mCurConfiguration + " / 0x"
10676 + Integer.toHexString(diff));
10678 win.mConfiguration = mCurConfiguration;
10679 win.mClient.resized(win.mFrame.width(),
10680 win.mFrame.height(), win.mLastContentInsets,
10681 win.mLastVisibleInsets, win.mDrawPending,
10682 configChanged ? win.mConfiguration : null);
10683 win.mContentInsetsChanged = false;
10684 win.mVisibleInsetsChanged = false;
10685 win.mSurfaceResized = false;
10686 } catch (RemoteException e) {
10687 win.mOrientationChanging = false;
10690 mResizingWindows.clear();
10693 // Destroy the surface of any windows that are no longer visible.
10694 boolean wallpaperDestroyed = false;
10695 i = mDestroySurface.size();
10699 WindowState win = mDestroySurface.get(i);
10700 win.mDestroying = false;
10701 if (mInputMethodWindow == win) {
10702 mInputMethodWindow = null;
10704 if (win == mWallpaperTarget) {
10705 wallpaperDestroyed = true;
10707 win.destroySurfaceLocked();
10709 mDestroySurface.clear();
10712 // Time to remove any exiting tokens?
10713 for (i=mExitingTokens.size()-1; i>=0; i--) {
10714 WindowToken token = mExitingTokens.get(i);
10715 if (!token.hasVisible) {
10716 mExitingTokens.remove(i);
10717 if (token.windowType == TYPE_WALLPAPER) {
10718 mWallpaperTokens.remove(token);
10723 // Time to remove any exiting applications?
10724 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
10725 AppWindowToken token = mExitingAppTokens.get(i);
10726 if (!token.hasVisible && !mClosingApps.contains(token)) {
10727 // Make sure there is no animation running on this token,
10728 // so any windows associated with it will be removed as
10729 // soon as their animations are complete
10730 token.animation = null;
10731 token.animating = false;
10732 mAppTokens.remove(token);
10733 mExitingAppTokens.remove(i);
10734 if (mLastEnterAnimToken == token) {
10735 mLastEnterAnimToken = null;
10736 mLastEnterAnimParams = null;
10741 boolean needRelayout = false;
10743 if (!animating && mAppTransitionRunning) {
10744 // We have finished the animation of an app transition. To do
10745 // this, we have delayed a lot of operations like showing and
10746 // hiding apps, moving apps in Z-order, etc. The app token list
10747 // reflects the correct Z-order, but the window list may now
10748 // be out of sync with it. So here we will just rebuild the
10749 // entire app window list. Fun!
10750 mAppTransitionRunning = false;
10751 needRelayout = true;
10752 rebuildAppWindowListLocked();
10753 assignLayersLocked();
10754 // Clear information about apps that were moving.
10755 mToBottomApps.clear();
10758 if (focusDisplayed) {
10759 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
10761 if (wallpaperDestroyed) {
10762 needRelayout = adjustWallpaperWindowsLocked() != 0;
10764 if (needRelayout) {
10765 requestAnimationLocked(0);
10766 } else if (animating) {
10767 requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
10770 if (DEBUG_FREEZE) Slog.v(TAG, "Layout: mDisplayFrozen=" + mDisplayFrozen
10771 + " holdScreen=" + holdScreen);
10772 if (!mDisplayFrozen) {
10773 mQueue.setHoldScreenLocked(holdScreen != null);
10774 if (screenBrightness < 0 || screenBrightness > 1.0f) {
10775 mPowerManager.setScreenBrightnessOverride(-1);
10777 mPowerManager.setScreenBrightnessOverride((int)
10778 (screenBrightness * Power.BRIGHTNESS_ON));
10780 if (buttonBrightness < 0 || buttonBrightness > 1.0f) {
10781 mPowerManager.setButtonBrightnessOverride(-1);
10783 mPowerManager.setButtonBrightnessOverride((int)
10784 (buttonBrightness * Power.BRIGHTNESS_ON));
10786 if (holdScreen != mHoldingScreenOn) {
10787 mHoldingScreenOn = holdScreen;
10788 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen);
10793 if (mTurnOnScreen) {
10794 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
10795 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
10796 LocalPowerManager.BUTTON_EVENT, true);
10797 mTurnOnScreen = false;
10800 // Check to see if we are now in a state where the screen should
10801 // be enabled, because the window obscured flags have changed.
10802 enableScreenIfNeededLocked();
10805 void requestAnimationLocked(long delay) {
10806 if (!mAnimationPending) {
10807 mAnimationPending = true;
10808 mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay);
10813 * Have the surface flinger show a surface, robustly dealing with
10814 * error conditions. In particular, if there is not enough memory
10815 * to show the surface, then we will try to get rid of other surfaces
10816 * in order to succeed.
10818 * @return Returns true if the surface was successfully shown.
10820 boolean showSurfaceRobustlyLocked(WindowState win) {
10822 if (win.mSurface != null) {
10823 win.mSurfaceShown = true;
10824 win.mSurface.show();
10825 if (win.mTurnOnScreen) {
10826 if (DEBUG_VISIBILITY) Slog.v(TAG,
10827 "Show surface turning screen on: " + win);
10828 win.mTurnOnScreen = false;
10829 mTurnOnScreen = true;
10833 } catch (RuntimeException e) {
10834 Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win);
10837 reclaimSomeSurfaceMemoryLocked(win, "show");
10842 void reclaimSomeSurfaceMemoryLocked(WindowState win, String operation) {
10843 final Surface surface = win.mSurface;
10845 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, win.toString(),
10846 win.mSession.mPid, operation);
10848 if (mForceRemoves == null) {
10849 mForceRemoves = new ArrayList<WindowState>();
10852 long callingIdentity = Binder.clearCallingIdentity();
10854 // There was some problem... first, do a sanity check of the
10855 // window list to make sure we haven't left any dangling surfaces
10857 int N = mWindows.size();
10858 boolean leakedSurface = false;
10859 Slog.i(TAG, "Out of memory for surface! Looking for leaks...");
10860 for (int i=0; i<N; i++) {
10861 WindowState ws = (WindowState)mWindows.get(i);
10862 if (ws.mSurface != null) {
10863 if (!mSessions.contains(ws.mSession)) {
10864 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
10865 + ws + " surface=" + ws.mSurface
10866 + " token=" + win.mToken
10867 + " pid=" + ws.mSession.mPid
10868 + " uid=" + ws.mSession.mUid);
10869 ws.mSurface.destroy();
10870 ws.mSurfaceShown = false;
10871 ws.mSurface = null;
10872 mForceRemoves.add(ws);
10875 leakedSurface = true;
10876 } else if (win.mAppToken != null && win.mAppToken.clientHidden) {
10877 Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
10878 + ws + " surface=" + ws.mSurface
10879 + " token=" + win.mAppToken);
10880 ws.mSurface.destroy();
10881 ws.mSurfaceShown = false;
10882 ws.mSurface = null;
10883 leakedSurface = true;
10888 boolean killedApps = false;
10889 if (!leakedSurface) {
10890 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
10891 SparseIntArray pidCandidates = new SparseIntArray();
10892 for (int i=0; i<N; i++) {
10893 WindowState ws = (WindowState)mWindows.get(i);
10894 if (ws.mSurface != null) {
10895 pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid);
10898 if (pidCandidates.size() > 0) {
10899 int[] pids = new int[pidCandidates.size()];
10900 for (int i=0; i<pids.length; i++) {
10901 pids[i] = pidCandidates.keyAt(i);
10904 if (mActivityManager.killPids(pids, "Free memory")) {
10907 } catch (RemoteException e) {
10912 if (leakedSurface || killedApps) {
10913 // We managed to reclaim some memory, so get rid of the trouble
10914 // surface and ask the app to request another one.
10915 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
10916 if (surface != null) {
10918 win.mSurfaceShown = false;
10919 win.mSurface = null;
10923 win.mClient.dispatchGetNewSurface();
10924 } catch (RemoteException e) {
10928 Binder.restoreCallingIdentity(callingIdentity);
10932 private boolean updateFocusedWindowLocked(int mode) {
10933 WindowState newFocus = computeFocusedWindowLocked();
10934 if (mCurrentFocus != newFocus) {
10935 // This check makes sure that we don't already have the focus
10936 // change message pending.
10937 mH.removeMessages(H.REPORT_FOCUS_CHANGE);
10938 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
10939 if (localLOGV) Slog.v(
10940 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
10941 final WindowState oldFocus = mCurrentFocus;
10942 mCurrentFocus = newFocus;
10943 mLosingFocus.remove(newFocus);
10945 final WindowState imWindow = mInputMethodWindow;
10946 if (newFocus != imWindow && oldFocus != imWindow) {
10947 if (moveInputMethodWindowsIfNeededLocked(
10948 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
10949 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
10950 mLayoutNeeded = true;
10952 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
10953 performLayoutLockedInner();
10954 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
10955 // Client will do the layout, but we need to assign layers
10956 // for handleNewWindowLocked() below.
10957 assignLayersLocked();
10961 if (newFocus != null && mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
10962 mKeyWaiter.handleNewWindowLocked(newFocus);
10969 private WindowState computeFocusedWindowLocked() {
10970 WindowState result = null;
10973 int i = mWindows.size() - 1;
10974 int nextAppIndex = mAppTokens.size()-1;
10975 WindowToken nextApp = nextAppIndex >= 0
10976 ? mAppTokens.get(nextAppIndex) : null;
10979 win = (WindowState)mWindows.get(i);
10981 if (localLOGV || DEBUG_FOCUS) Slog.v(
10982 TAG, "Looking for focus: " + i
10984 + ", flags=" + win.mAttrs.flags
10985 + ", canReceive=" + win.canReceiveKeys());
10987 AppWindowToken thisApp = win.mAppToken;
10989 // If this window's application has been removed, just skip it.
10990 if (thisApp != null && thisApp.removed) {
10995 // If there is a focused app, don't allow focus to go to any
10996 // windows below it. If this is an application window, step
10997 // through the app tokens until we find its app.
10998 if (thisApp != null && nextApp != null && thisApp != nextApp
10999 && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
11000 int origAppIndex = nextAppIndex;
11001 while (nextAppIndex > 0) {
11002 if (nextApp == mFocusedApp) {
11003 // Whoops, we are below the focused app... no focus
11005 if (localLOGV || DEBUG_FOCUS) Slog.v(
11006 TAG, "Reached focused app: " + mFocusedApp);
11010 nextApp = mAppTokens.get(nextAppIndex);
11011 if (nextApp == thisApp) {
11015 if (thisApp != nextApp) {
11016 // Uh oh, the app token doesn't exist! This shouldn't
11017 // happen, but if it does we can get totally hosed...
11018 // so restart at the original app.
11019 nextAppIndex = origAppIndex;
11020 nextApp = mAppTokens.get(nextAppIndex);
11024 // Dispatch to this window if it is wants key events.
11025 if (win.canReceiveKeys()) {
11026 if (DEBUG_FOCUS) Slog.v(
11027 TAG, "Found focus @ " + i + " = " + win);
11038 private void startFreezingDisplayLocked() {
11039 if (mDisplayFrozen) {
11040 // Freezing the display also suspends key event delivery, to
11041 // keep events from going astray while the display is reconfigured.
11042 // If someone has changed orientation again while the screen is
11043 // still frozen, the events will continue to be blocked while the
11044 // successive orientation change is processed. To prevent spurious
11045 // ANRs, we reset the event dispatch timeout in this case.
11046 synchronized (mKeyWaiter) {
11047 mKeyWaiter.mWasFrozen = true;
11052 mScreenFrozenLock.acquire();
11054 long now = SystemClock.uptimeMillis();
11055 //Slog.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now);
11056 if (mFreezeGcPending != 0) {
11057 if (now > (mFreezeGcPending+1000)) {
11058 //Slog.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000));
11059 mH.removeMessages(H.FORCE_GC);
11060 Runtime.getRuntime().gc();
11061 mFreezeGcPending = now;
11064 mFreezeGcPending = now;
11067 if (DEBUG_FREEZE) Slog.v(TAG, "*** FREEZING DISPLAY", new RuntimeException());
11069 mDisplayFrozen = true;
11070 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
11071 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
11072 mNextAppTransitionPackage = null;
11073 mAppTransitionReady = true;
11076 if (PROFILE_ORIENTATION) {
11077 File file = new File("/data/system/frozen");
11078 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
11080 Surface.freezeDisplay(0);
11083 private void stopFreezingDisplayLocked() {
11084 if (!mDisplayFrozen) {
11088 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) {
11092 if (DEBUG_FREEZE) Slog.v(TAG, "*** UNFREEZING DISPLAY", new RuntimeException());
11094 mDisplayFrozen = false;
11095 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
11096 if (PROFILE_ORIENTATION) {
11097 Debug.stopMethodTracing();
11099 Surface.unfreezeDisplay(0);
11101 // Reset the key delivery timeout on unfreeze, too. We force a wakeup here
11102 // too because regular key delivery processing should resume immediately.
11103 synchronized (mKeyWaiter) {
11104 mKeyWaiter.mWasFrozen = true;
11105 mKeyWaiter.notifyAll();
11108 // While the display is frozen we don't re-compute the orientation
11109 // to avoid inconsistent states. However, something interesting
11110 // could have actually changed during that time so re-evaluate it
11111 // now to catch that.
11112 if (updateOrientationFromAppTokensLocked()) {
11113 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
11116 // A little kludge: a lot could have happened while the
11117 // display was frozen, so now that we are coming back we
11118 // do a gc so that any remote references the system
11119 // processes holds on others can be released if they are
11120 // no longer needed.
11121 mH.removeMessages(H.FORCE_GC);
11122 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
11125 mScreenFrozenLock.release();
11129 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
11130 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
11131 != PackageManager.PERMISSION_GRANTED) {
11132 pw.println("Permission Denial: can't dump WindowManager from from pid="
11133 + Binder.getCallingPid()
11134 + ", uid=" + Binder.getCallingUid());
11138 pw.println("Input State:");
11139 mQueue.dump(pw, " ");
11142 synchronized(mWindowMap) {
11143 pw.println("Current Window Manager state:");
11144 for (int i=mWindows.size()-1; i>=0; i--) {
11145 WindowState w = (WindowState)mWindows.get(i);
11146 pw.print(" Window #"); pw.print(i); pw.print(' ');
11147 pw.print(w); pw.println(":");
11150 if (mInputMethodDialogs.size() > 0) {
11152 pw.println(" Input method dialogs:");
11153 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
11154 WindowState w = mInputMethodDialogs.get(i);
11155 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
11158 if (mPendingRemove.size() > 0) {
11160 pw.println(" Remove pending for:");
11161 for (int i=mPendingRemove.size()-1; i>=0; i--) {
11162 WindowState w = mPendingRemove.get(i);
11163 pw.print(" Remove #"); pw.print(i); pw.print(' ');
11164 pw.print(w); pw.println(":");
11168 if (mForceRemoves != null && mForceRemoves.size() > 0) {
11170 pw.println(" Windows force removing:");
11171 for (int i=mForceRemoves.size()-1; i>=0; i--) {
11172 WindowState w = mForceRemoves.get(i);
11173 pw.print(" Removing #"); pw.print(i); pw.print(' ');
11174 pw.print(w); pw.println(":");
11178 if (mDestroySurface.size() > 0) {
11180 pw.println(" Windows waiting to destroy their surface:");
11181 for (int i=mDestroySurface.size()-1; i>=0; i--) {
11182 WindowState w = mDestroySurface.get(i);
11183 pw.print(" Destroy #"); pw.print(i); pw.print(' ');
11184 pw.print(w); pw.println(":");
11188 if (mLosingFocus.size() > 0) {
11190 pw.println(" Windows losing focus:");
11191 for (int i=mLosingFocus.size()-1; i>=0; i--) {
11192 WindowState w = mLosingFocus.get(i);
11193 pw.print(" Losing #"); pw.print(i); pw.print(' ');
11194 pw.print(w); pw.println(":");
11198 if (mResizingWindows.size() > 0) {
11200 pw.println(" Windows waiting to resize:");
11201 for (int i=mResizingWindows.size()-1; i>=0; i--) {
11202 WindowState w = mResizingWindows.get(i);
11203 pw.print(" Resizing #"); pw.print(i); pw.print(' ');
11204 pw.print(w); pw.println(":");
11208 if (mSessions.size() > 0) {
11210 pw.println(" All active sessions:");
11211 Iterator<Session> it = mSessions.iterator();
11212 while (it.hasNext()) {
11213 Session s = it.next();
11214 pw.print(" Session "); pw.print(s); pw.println(':');
11218 if (mTokenMap.size() > 0) {
11220 pw.println(" All tokens:");
11221 Iterator<WindowToken> it = mTokenMap.values().iterator();
11222 while (it.hasNext()) {
11223 WindowToken token = it.next();
11224 pw.print(" Token "); pw.print(token.token); pw.println(':');
11225 token.dump(pw, " ");
11228 if (mTokenList.size() > 0) {
11230 pw.println(" Window token list:");
11231 for (int i=0; i<mTokenList.size(); i++) {
11232 pw.print(" #"); pw.print(i); pw.print(": ");
11233 pw.println(mTokenList.get(i));
11236 if (mWallpaperTokens.size() > 0) {
11238 pw.println(" Wallpaper tokens:");
11239 for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
11240 WindowToken token = mWallpaperTokens.get(i);
11241 pw.print(" Wallpaper #"); pw.print(i);
11242 pw.print(' '); pw.print(token); pw.println(':');
11243 token.dump(pw, " ");
11246 if (mAppTokens.size() > 0) {
11248 pw.println(" Application tokens in Z order:");
11249 for (int i=mAppTokens.size()-1; i>=0; i--) {
11250 pw.print(" App #"); pw.print(i); pw.print(": ");
11251 pw.println(mAppTokens.get(i));
11254 if (mFinishedStarting.size() > 0) {
11256 pw.println(" Finishing start of application tokens:");
11257 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
11258 WindowToken token = mFinishedStarting.get(i);
11259 pw.print(" Finished Starting #"); pw.print(i);
11260 pw.print(' '); pw.print(token); pw.println(':');
11261 token.dump(pw, " ");
11264 if (mExitingTokens.size() > 0) {
11266 pw.println(" Exiting tokens:");
11267 for (int i=mExitingTokens.size()-1; i>=0; i--) {
11268 WindowToken token = mExitingTokens.get(i);
11269 pw.print(" Exiting #"); pw.print(i);
11270 pw.print(' '); pw.print(token); pw.println(':');
11271 token.dump(pw, " ");
11274 if (mExitingAppTokens.size() > 0) {
11276 pw.println(" Exiting application tokens:");
11277 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
11278 WindowToken token = mExitingAppTokens.get(i);
11279 pw.print(" Exiting App #"); pw.print(i);
11280 pw.print(' '); pw.print(token); pw.println(':');
11281 token.dump(pw, " ");
11285 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
11286 pw.print(" mLastFocus="); pw.println(mLastFocus);
11287 pw.print(" mFocusedApp="); pw.println(mFocusedApp);
11288 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
11289 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
11290 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget);
11291 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) {
11292 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
11293 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
11295 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration);
11296 pw.print(" mInTouchMode="); pw.print(mInTouchMode);
11297 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
11298 pw.print(" mSystemBooted="); pw.print(mSystemBooted);
11299 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
11300 pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded);
11301 pw.print(" mBlurShown="); pw.println(mBlurShown);
11302 if (mDimAnimator != null) {
11303 mDimAnimator.printTo(pw);
11305 pw.println( " no DimAnimator ");
11307 pw.print(" mInputMethodAnimLayerAdjustment=");
11308 pw.print(mInputMethodAnimLayerAdjustment);
11309 pw.print(" mWallpaperAnimLayerAdjustment=");
11310 pw.println(mWallpaperAnimLayerAdjustment);
11311 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX);
11312 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
11313 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
11314 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
11315 pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
11316 pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig);
11317 pw.print(" mRotation="); pw.print(mRotation);
11318 pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
11319 pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
11320 pw.print(" mAnimationPending="); pw.print(mAnimationPending);
11321 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
11322 pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale);
11323 pw.print(" mNextAppTransition=0x");
11324 pw.print(Integer.toHexString(mNextAppTransition));
11325 pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady);
11326 pw.print(", mAppTransitionRunning="); pw.print(mAppTransitionRunning);
11327 pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout);
11328 if (mNextAppTransitionPackage != null) {
11329 pw.print(" mNextAppTransitionPackage=");
11330 pw.print(mNextAppTransitionPackage);
11331 pw.print(", mNextAppTransitionEnter=0x");
11332 pw.print(Integer.toHexString(mNextAppTransitionEnter));
11333 pw.print(", mNextAppTransitionExit=0x");
11334 pw.print(Integer.toHexString(mNextAppTransitionExit));
11336 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
11337 pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
11338 if (mLastEnterAnimToken != null || mLastEnterAnimToken != null) {
11339 pw.print(" mLastEnterAnimToken="); pw.print(mLastEnterAnimToken);
11340 pw.print(", mLastEnterAnimParams="); pw.println(mLastEnterAnimParams);
11342 if (mOpeningApps.size() > 0) {
11343 pw.print(" mOpeningApps="); pw.println(mOpeningApps);
11345 if (mClosingApps.size() > 0) {
11346 pw.print(" mClosingApps="); pw.println(mClosingApps);
11348 if (mToTopApps.size() > 0) {
11349 pw.print(" mToTopApps="); pw.println(mToTopApps);
11351 if (mToBottomApps.size() > 0) {
11352 pw.print(" mToBottomApps="); pw.println(mToBottomApps);
11354 pw.print(" DisplayWidth="); pw.print(mDisplay.getWidth());
11355 pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight());
11356 pw.println(" KeyWaiter state:");
11357 pw.print(" mLastWin="); pw.print(mKeyWaiter.mLastWin);
11358 pw.print(" mLastBinder="); pw.println(mKeyWaiter.mLastBinder);
11359 pw.print(" mFinished="); pw.print(mKeyWaiter.mFinished);
11360 pw.print(" mGotFirstWindow="); pw.print(mKeyWaiter.mGotFirstWindow);
11361 pw.print(" mEventDispatching="); pw.print(mKeyWaiter.mEventDispatching);
11362 pw.print(" mTimeToSwitch="); pw.println(mKeyWaiter.mTimeToSwitch);
11366 public void monitor() {
11367 synchronized (mWindowMap) { }
11368 synchronized (mKeyguardTokenWatcher) { }
11369 synchronized (mKeyWaiter) { }
11372 public void virtualKeyFeedback(KeyEvent event) {
11373 mPolicy.keyFeedbackFromInput(event);
11377 * DimAnimator class that controls the dim animation. This holds the surface and
11378 * all state used for dim animation.
11380 private static class DimAnimator {
11381 Surface mDimSurface;
11382 boolean mDimShown = false;
11383 float mDimCurrentAlpha;
11384 float mDimTargetAlpha;
11385 float mDimDeltaPerMs;
11386 long mLastDimAnimTime;
11388 int mLastDimWidth, mLastDimHeight;
11390 DimAnimator (SurfaceSession session) {
11391 if (mDimSurface == null) {
11392 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
11393 + mDimSurface + ": CREATE");
11395 mDimSurface = new Surface(session, 0,
11397 -1, 16, 16, PixelFormat.OPAQUE,
11398 Surface.FX_SURFACE_DIM);
11399 mDimSurface.setAlpha(0.0f);
11400 } catch (Exception e) {
11401 Slog.e(TAG, "Exception creating Dim surface", e);
11407 * Show the dim surface.
11409 void show(int dw, int dh) {
11411 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
11412 dw + "x" + dh + ")");
11415 mLastDimWidth = dw;
11416 mLastDimHeight = dh;
11417 mDimSurface.setPosition(0, 0);
11418 mDimSurface.setSize(dw, dh);
11419 mDimSurface.show();
11420 } catch (RuntimeException e) {
11421 Slog.w(TAG, "Failure showing dim surface", e);
11423 } else if (mLastDimWidth != dw || mLastDimHeight != dh) {
11424 mLastDimWidth = dw;
11425 mLastDimHeight = dh;
11426 mDimSurface.setSize(dw, dh);
11431 * Set's the dim surface's layer and update dim parameters that will be used in
11432 * {@link updateSurface} after all windows are examined.
11434 void updateParameters(WindowState w, long currentTime) {
11435 mDimSurface.setLayer(w.mAnimLayer-1);
11437 final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
11438 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface
11439 + ": layer=" + (w.mAnimLayer-1) + " target=" + target);
11440 if (mDimTargetAlpha != target) {
11441 // If the desired dim level has changed, then
11442 // start an animation to it.
11443 mLastDimAnimTime = currentTime;
11444 long duration = (w.mAnimating && w.mAnimation != null)
11445 ? w.mAnimation.computeDurationHint()
11446 : DEFAULT_DIM_DURATION;
11447 if (target > mDimTargetAlpha) {
11448 // This is happening behind the activity UI,
11449 // so we can make it run a little longer to
11450 // give a stronger impression without disrupting
11452 duration *= DIM_DURATION_MULTIPLIER;
11454 if (duration < 1) {
11455 // Don't divide by zero
11458 mDimTargetAlpha = target;
11459 mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
11464 * Updating the surface's alpha. Returns true if the animation continues, or returns
11465 * false when the animation is finished and the dim surface is hidden.
11467 boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
11469 if (mDimTargetAlpha != 0) {
11470 mLastDimAnimTime = currentTime;
11471 mDimTargetAlpha = 0;
11472 mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION;
11476 boolean animating = false;
11477 if (mLastDimAnimTime != 0) {
11478 mDimCurrentAlpha += mDimDeltaPerMs
11479 * (currentTime-mLastDimAnimTime);
11480 boolean more = true;
11481 if (displayFrozen) {
11482 // If the display is frozen, there is no reason to animate.
11484 } else if (mDimDeltaPerMs > 0) {
11485 if (mDimCurrentAlpha > mDimTargetAlpha) {
11488 } else if (mDimDeltaPerMs < 0) {
11489 if (mDimCurrentAlpha < mDimTargetAlpha) {
11496 // Do we need to continue animating?
11498 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
11499 + mDimSurface + ": alpha=" + mDimCurrentAlpha);
11500 mLastDimAnimTime = currentTime;
11501 mDimSurface.setAlpha(mDimCurrentAlpha);
11504 mDimCurrentAlpha = mDimTargetAlpha;
11505 mLastDimAnimTime = 0;
11506 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
11507 + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
11508 mDimSurface.setAlpha(mDimCurrentAlpha);
11510 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface
11513 mDimSurface.hide();
11514 } catch (RuntimeException e) {
11515 Slog.w(TAG, "Illegal argument exception hiding dim surface");
11524 public void printTo(PrintWriter pw) {
11525 pw.print(" mDimShown="); pw.print(mDimShown);
11526 pw.print(" current="); pw.print(mDimCurrentAlpha);
11527 pw.print(" target="); pw.print(mDimTargetAlpha);
11528 pw.print(" delta="); pw.print(mDimDeltaPerMs);
11529 pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
11534 * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
11535 * This is used for opening/closing transition for apps in compatible mode.
11537 private static class FadeInOutAnimation extends Animation {
11541 public FadeInOutAnimation(boolean fadeIn) {
11542 setInterpolator(new AccelerateInterpolator());
11543 setDuration(DEFAULT_FADE_IN_OUT_DURATION);
11548 protected void applyTransformation(float interpolatedTime, Transformation t) {
11549 float x = interpolatedTime;
11551 x = 1.0f - x; // reverse the interpolation for fade out
11554 // move the window out of the screen.
11555 t.getMatrix().setTranslate(mWidth, 0);
11557 t.getMatrix().setTranslate(0, 0);// show
11558 t.setAlpha((x - 0.5f) * 2);
11563 public void initialize(int width, int height, int parentWidth, int parentHeight) {
11564 // width is the screen width {@see AppWindowToken#stepAnimatinoLocked}
11569 public int getZAdjustment() {
11570 return Animation.ZORDER_TOP;