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.wm;
19 import static android.view.WindowManager.LayoutParams.*;
21 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
22 import android.app.AppOpsManager;
23 import android.util.ArraySet;
24 import android.util.TimeUtils;
25 import android.view.IWindowId;
27 import android.view.IWindowSessionCallback;
28 import android.view.WindowContentFrameStats;
29 import com.android.internal.app.IBatteryStats;
30 import com.android.internal.policy.PolicyManager;
31 import com.android.internal.policy.impl.PhoneWindowManager;
32 import com.android.internal.util.FastPrintWriter;
33 import com.android.internal.view.IInputContext;
34 import com.android.internal.view.IInputMethodClient;
35 import com.android.internal.view.IInputMethodManager;
36 import com.android.internal.view.WindowManagerPolicyThread;
37 import com.android.server.AttributeCache;
38 import com.android.server.DisplayThread;
39 import com.android.server.EventLogTags;
40 import com.android.server.LocalServices;
41 import com.android.server.UiThread;
42 import com.android.server.Watchdog;
43 import com.android.server.am.BatteryStatsService;
44 import com.android.server.input.InputManagerService;
45 import com.android.server.power.ShutdownThread;
47 import android.Manifest;
48 import android.app.ActivityManagerNative;
49 import android.app.IActivityManager;
50 import android.app.StatusBarManager;
51 import android.app.admin.DevicePolicyManager;
52 import android.animation.ValueAnimator;
53 import android.content.BroadcastReceiver;
54 import android.content.Context;
55 import android.content.Intent;
56 import android.content.IntentFilter;
57 import android.content.pm.ActivityInfo;
58 import android.content.pm.PackageManager;
59 import android.content.res.CompatibilityInfo;
60 import android.content.res.Configuration;
61 import android.graphics.Bitmap;
62 import android.graphics.Bitmap.Config;
63 import android.graphics.Canvas;
64 import android.graphics.Matrix;
65 import android.graphics.PixelFormat;
66 import android.graphics.Point;
67 import android.graphics.Rect;
68 import android.graphics.RectF;
69 import android.graphics.Region;
70 import android.hardware.display.DisplayManager;
71 import android.hardware.display.DisplayManagerInternal;
72 import android.os.Binder;
73 import android.os.Bundle;
74 import android.os.Debug;
75 import android.os.Handler;
76 import android.os.IBinder;
77 import android.os.IRemoteCallback;
78 import android.os.Looper;
79 import android.os.Message;
80 import android.os.Parcel;
81 import android.os.ParcelFileDescriptor;
82 import android.os.PowerManager;
83 import android.os.PowerManagerInternal;
84 import android.os.Process;
85 import android.os.RemoteException;
86 import android.os.ServiceManager;
87 import android.os.StrictMode;
88 import android.os.SystemClock;
89 import android.os.SystemProperties;
90 import android.os.Trace;
91 import android.os.UserHandle;
92 import android.os.WorkSource;
93 import android.provider.Settings;
94 import android.util.DisplayMetrics;
95 import android.util.EventLog;
96 import android.util.FloatMath;
97 import android.util.Log;
98 import android.util.SparseArray;
99 import android.util.Pair;
100 import android.util.Slog;
101 import android.util.SparseIntArray;
102 import android.util.TypedValue;
103 import android.view.Choreographer;
104 import android.view.Display;
105 import android.view.DisplayInfo;
106 import android.view.Gravity;
107 import android.view.IApplicationToken;
108 import android.view.IInputFilter;
109 import android.view.IOnKeyguardExitResult;
110 import android.view.IRotationWatcher;
111 import android.view.IWindow;
112 import android.view.IWindowManager;
113 import android.view.IWindowSession;
114 import android.view.InputChannel;
115 import android.view.InputDevice;
116 import android.view.InputEvent;
117 import android.view.InputEventReceiver;
118 import android.view.KeyEvent;
119 import android.view.MagnificationSpec;
120 import android.view.MotionEvent;
121 import android.view.WindowManagerInternal;
122 import android.view.Surface.OutOfResourcesException;
123 import android.view.Surface;
124 import android.view.SurfaceControl;
125 import android.view.SurfaceSession;
126 import android.view.View;
127 import android.view.ViewTreeObserver;
128 import android.view.WindowManager;
129 import android.view.WindowManagerGlobal;
130 import android.view.WindowManagerPolicy;
131 import android.view.WindowManager.LayoutParams;
132 import android.view.WindowManagerPolicy.FakeWindow;
133 import android.view.WindowManagerPolicy.PointerEventListener;
134 import android.view.animation.Animation;
135 import android.view.animation.AnimationUtils;
136 import android.view.animation.Transformation;
138 import java.io.BufferedWriter;
139 import java.io.DataInputStream;
141 import java.io.FileDescriptor;
142 import java.io.FileInputStream;
143 import java.io.FileNotFoundException;
144 import java.io.IOException;
145 import java.io.OutputStream;
146 import java.io.OutputStreamWriter;
147 import java.io.PrintWriter;
148 import java.io.StringWriter;
149 import java.net.Socket;
150 import java.text.DateFormat;
151 import java.util.ArrayList;
152 import java.util.Date;
153 import java.util.HashMap;
154 import java.util.Iterator;
155 import java.util.List;
158 public class WindowManagerService extends IWindowManager.Stub
159 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
160 static final String TAG = "WindowManager";
161 static final boolean DEBUG = false;
162 static final boolean DEBUG_ADD_REMOVE = false;
163 static final boolean DEBUG_FOCUS = false;
164 static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false;
165 static final boolean DEBUG_ANIM = false;
166 static final boolean DEBUG_LAYOUT = false;
167 static final boolean DEBUG_RESIZE = false;
168 static final boolean DEBUG_LAYERS = false;
169 static final boolean DEBUG_INPUT = false;
170 static final boolean DEBUG_INPUT_METHOD = false;
171 static final boolean DEBUG_VISIBILITY = false;
172 static final boolean DEBUG_WINDOW_MOVEMENT = false;
173 static final boolean DEBUG_TOKEN_MOVEMENT = false;
174 static final boolean DEBUG_ORIENTATION = false;
175 static final boolean DEBUG_APP_ORIENTATION = false;
176 static final boolean DEBUG_CONFIGURATION = false;
177 static final boolean DEBUG_APP_TRANSITIONS = false;
178 static final boolean DEBUG_STARTING_WINDOW = false;
179 static final boolean DEBUG_REORDER = false;
180 static final boolean DEBUG_WALLPAPER = false;
181 static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
182 static final boolean DEBUG_DRAG = false;
183 static final boolean DEBUG_SCREEN_ON = false;
184 static final boolean DEBUG_SCREENSHOT = false;
185 static final boolean DEBUG_BOOT = false;
186 static final boolean DEBUG_LAYOUT_REPEATS = true;
187 static final boolean DEBUG_SURFACE_TRACE = false;
188 static final boolean DEBUG_WINDOW_TRACE = false;
189 static final boolean DEBUG_TASK_MOVEMENT = false;
190 static final boolean DEBUG_STACK = false;
191 static final boolean DEBUG_DISPLAY = false;
192 static final boolean SHOW_SURFACE_ALLOC = false;
193 static final boolean SHOW_TRANSACTIONS = false;
194 static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
195 static final boolean HIDE_STACK_CRAWLS = true;
196 static final int LAYOUT_REPEAT_THRESHOLD = 4;
198 static final boolean PROFILE_ORIENTATION = false;
199 static final boolean localLOGV = DEBUG;
201 /** How much to multiply the policy's type layer, to reserve room
202 * for multiple windows of the same type and Z-ordering adjustment
203 * with TYPE_LAYER_OFFSET. */
204 static final int TYPE_LAYER_MULTIPLIER = 10000;
206 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
207 * or below others in the same layer. */
208 static final int TYPE_LAYER_OFFSET = 1000;
210 /** How much to increment the layer for each window, to reserve room
211 * for effect surfaces between them.
213 static final int WINDOW_LAYER_MULTIPLIER = 5;
216 * Dim surface layer is immediately below target window.
218 static final int LAYER_OFFSET_DIM = 1;
221 * Blur surface layer is immediately below dim layer.
223 static final int LAYER_OFFSET_BLUR = 2;
226 * FocusedStackFrame layer is immediately above focused window.
228 static final int LAYER_OFFSET_FOCUSED_STACK = 1;
231 * Animation thumbnail is as far as possible below the window above
232 * the thumbnail (or in other words as far as possible above the window
235 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1;
238 * Layer at which to put the rotation freeze snapshot.
240 static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1;
243 * Layer at which to put the mask for emulated screen sizes.
245 static final int MASK_LAYER = TYPE_LAYER_MULTIPLIER * 200;
247 /** The maximum length we will accept for a loaded animation duration:
248 * this is 10 seconds.
250 static final int MAX_ANIMATION_DURATION = 10*1000;
252 /** Amount of time (in milliseconds) to animate the fade-in-out transition for
253 * compatible windows.
255 static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
257 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
258 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
261 * If true, the window manager will do its own custom freezing and general
262 * management of the screen during rotation.
264 static final boolean CUSTOM_SCREEN_ROTATION = true;
266 // Maximum number of milliseconds to wait for input devices to be enumerated before
267 // proceding with safe mode detection.
268 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
270 // Default input dispatching timeout in nanoseconds.
271 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
273 /** Minimum value for attachStack and resizeStack weight value */
274 public static final float STACK_WEIGHT_MIN = 0.2f;
276 /** Maximum value for attachStack and resizeStack weight value */
277 public static final float STACK_WEIGHT_MAX = 0.8f;
279 static final int UPDATE_FOCUS_NORMAL = 0;
280 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
281 static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
282 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
284 private static final String SYSTEM_SECURE = "ro.secure";
285 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
287 private static final String DENSITY_OVERRIDE = "ro.config.density_override";
288 private static final String SIZE_OVERRIDE = "ro.config.size_override";
290 private static final int MAX_SCREENSHOT_RETRIES = 3;
292 // The flag describing a full screen app window (where the app takes care of drawing under the
294 private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
295 View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
297 final private KeyguardDisableHandler mKeyguardDisableHandler;
299 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
301 public void onReceive(Context context, Intent intent) {
302 final String action = intent.getAction();
303 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
304 mKeyguardDisableHandler.sendEmptyMessage(
305 KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED);
311 * Current user when multi-user is enabled. Don't show windows of
312 * non-current user. Also see mCurrentProfileIds.
316 * Users that are profiles of the current user. These are also allowed to show windows
317 * on the current user.
319 int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER};
321 final Context mContext;
323 final boolean mHaveInputMethods;
325 final boolean mAllowBootMessages;
327 final boolean mLimitedAlphaCompositing;
329 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
331 final IActivityManager mActivityManager;
333 final IBatteryStats mBatteryStats;
335 final AppOpsManager mAppOps;
337 final DisplaySettings mDisplaySettings;
340 * All currently active sessions with clients.
342 final ArraySet<Session> mSessions = new ArraySet<Session>();
345 * Mapping from an IWindow IBinder to the server's Window object.
346 * This is also used as the lock for all of our state.
347 * NOTE: Never call into methods that lock ActivityManagerService while holding this object.
349 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
352 * Mapping from a token IBinder to a WindowToken object.
354 final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>();
357 * List of window tokens that have finished starting their application,
358 * and now need to have the policy remove their windows.
360 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
363 * Fake windows added to the window manager. Note: ordered from top to
364 * bottom, opposite of mWindows.
366 final ArrayList<FakeWindowImpl> mFakeWindows = new ArrayList<FakeWindowImpl>();
369 * Windows that are being resized. Used so we can tell the client about
370 * the resize after closing the transaction in which we resized the
371 * underlying surface.
373 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
376 * Windows whose animations have ended and now must be removed.
378 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
381 * Stacks whose animations have ended and whose tasks, apps, selves may now be removed.
383 final ArraySet<TaskStack> mPendingStacksRemove = new ArraySet<TaskStack>();
386 * Used when processing mPendingRemove to avoid working on the original array.
388 WindowState[] mPendingRemoveTmp = new WindowState[20];
391 * Windows whose surface should be destroyed.
393 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
396 * Windows that have lost input focus and are waiting for the new
397 * focus window to be displayed before they are told about this.
399 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
402 * This is set when we have run out of memory, and will either be an empty
403 * list or contain windows that need to be force removed.
405 ArrayList<WindowState> mForceRemoves;
408 * Windows that clients are waiting to have drawn.
410 ArrayList<WindowState> mWaitingForDrawn = new ArrayList<WindowState>();
412 * And the callback to make when they've all been drawn.
414 Runnable mWaitingForDrawnCallback;
417 * Windows that have called relayout() while we were running animations,
418 * so we need to tell when the animation is done.
420 final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>();
423 * Used when rebuilding window list to keep track of windows that have
426 WindowState[] mRebuildTmp = new WindowState[20];
428 IInputMethodManager mInputMethodManager;
430 AccessibilityController mAccessibilityController;
432 final SurfaceSession mFxSession;
433 Watermark mWatermark;
434 StrictModeFlash mStrictModeFlash;
435 FocusedStackFrame mFocusedStackFrame;
437 int mFocusedStackLayer;
439 final float[] mTmpFloats = new float[9];
440 final Rect mTmpContentRect = new Rect();
442 boolean mDisplayReady;
444 boolean mDisplayEnabled = false;
445 boolean mSystemBooted = false;
446 boolean mForceDisplayEnabled = false;
447 boolean mShowingBootMessages = false;
449 String mLastANRState;
451 /** All DisplayContents in the world, kept here */
452 SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(2);
455 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
456 boolean mAltOrientation = false;
457 class RotationWatcher {
458 IRotationWatcher watcher;
459 IBinder.DeathRecipient deathRecipient;
460 RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d) {
465 ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<RotationWatcher>();
466 int mDeferredRotationPauseCount;
468 int mSystemDecorLayer = 0;
469 final Rect mScreenRect = new Rect();
471 boolean mTraversalScheduled = false;
472 boolean mDisplayFrozen = false;
473 long mDisplayFreezeTime = 0;
474 int mLastDisplayFreezeDuration = 0;
475 Object mLastFinishedFreezeSource = null;
476 boolean mWaitingForConfig = false;
477 boolean mWindowsFreezingScreen = false;
478 boolean mClientFreezingScreen = false;
479 int mAppsFreezingScreen = 0;
480 int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
484 int mLastStatusBarVisibility = 0;
486 // State while inside of layoutAndPlaceSurfacesLocked().
487 boolean mFocusMayChange;
489 Configuration mCurConfiguration = new Configuration();
491 // This is held as long as we have the screen frozen, to give us time to
492 // perform a rotation animation when turning off shows the lock screen which
493 // changes the orientation.
494 private final PowerManager.WakeLock mScreenFrozenLock;
496 final AppTransition mAppTransition;
497 boolean mStartingIconInTransition = false;
498 boolean mSkipAppTransitionAnimation = false;
500 final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<AppWindowToken>();
501 final ArraySet<AppWindowToken> mClosingApps = new ArraySet<AppWindowToken>();
503 boolean mIsTouchDevice;
505 final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
506 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
507 final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
508 final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
510 final H mH = new H();
512 final Choreographer mChoreographer = Choreographer.getInstance();
514 WindowState mCurrentFocus = null;
515 WindowState mLastFocus = null;
517 /** This just indicates the window the input method is on top of, not
518 * necessarily the window its input is going to. */
519 WindowState mInputMethodTarget = null;
521 /** If true hold off on modifying the animation layer of mInputMethodTarget */
522 boolean mInputMethodTargetWaitingAnim;
523 int mInputMethodAnimLayerAdjustment;
525 WindowState mInputMethodWindow = null;
526 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
528 boolean mHardKeyboardAvailable;
529 boolean mHardKeyboardEnabled;
530 OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
532 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
534 // If non-null, this is the currently visible window that is associated
535 // with the wallpaper.
536 WindowState mWallpaperTarget = null;
537 // If non-null, we are in the middle of animating from one wallpaper target
538 // to another, and this is the lower one in Z-order.
539 WindowState mLowerWallpaperTarget = null;
540 // If non-null, we are in the middle of animating from one wallpaper target
541 // to another, and this is the higher one in Z-order.
542 WindowState mUpperWallpaperTarget = null;
543 int mWallpaperAnimLayerAdjustment;
544 float mLastWallpaperX = -1;
545 float mLastWallpaperY = -1;
546 float mLastWallpaperXStep = -1;
547 float mLastWallpaperYStep = -1;
548 // This is set when we are waiting for a wallpaper to tell us it is done
549 // changing its scroll position.
550 WindowState mWaitingOnWallpaper;
551 // The last time we had a timeout when waiting for a wallpaper.
552 long mLastWallpaperTimeoutTime;
553 // We give a wallpaper up to 150ms to finish scrolling.
554 static final long WALLPAPER_TIMEOUT = 150;
555 // Time we wait after a timeout before trying to wait again.
556 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
557 boolean mAnimateWallpaperWithTarget;
559 AppWindowToken mFocusedApp = null;
561 PowerManager mPowerManager;
562 PowerManagerInternal mPowerManagerInternal;
564 float mWindowAnimationScaleSetting = 1.0f;
565 float mTransitionAnimationScaleSetting = 1.0f;
566 float mAnimatorDurationScaleSetting = 1.0f;
567 boolean mAnimationsDisabled = false;
569 final InputManagerService mInputManager;
570 final DisplayManagerInternal mDisplayManagerInternal;
571 final DisplayManager mDisplayManager;
573 // Who is holding the screen on.
574 Session mHoldingScreenOn;
575 PowerManager.WakeLock mHoldingScreenWakeLock;
577 boolean mTurnOnScreen;
579 DragState mDragState = null;
581 // For frozen screen animations.
582 int mExitAnimId, mEnterAnimId;
584 /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple
587 static final int SET_UPDATE_ROTATION = 1 << 0;
588 static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1;
589 static final int SET_FORCE_HIDING_CHANGED = 1 << 2;
590 static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 3;
591 static final int SET_TURN_ON_SCREEN = 1 << 4;
592 static final int SET_WALLPAPER_ACTION_PENDING = 1 << 5;
594 boolean mWallpaperForceHidingChanged = false;
595 boolean mWallpaperMayChange = false;
596 boolean mOrientationChangeComplete = true;
597 Object mLastWindowFreezeSource = null;
598 private Session mHoldScreen = null;
599 private boolean mObscured = false;
600 private boolean mSyswin = false;
601 private float mScreenBrightness = -1;
602 private float mButtonBrightness = -1;
603 private long mUserActivityTimeout = -1;
604 private boolean mUpdateRotation = false;
605 boolean mWallpaperActionPending = false;
607 // Set to true when the display contains content to show the user.
608 // When false, the display manager may choose to mirror or blank the display.
609 boolean mDisplayHasContent = false;
611 // Only set while traversing the default display based on its content.
612 // Affects the behavior of mirroring on secondary displays.
613 boolean mObscureApplicationContentOnSecondaryDisplays = false;
615 final LayoutFields mInnerFields = new LayoutFields();
617 boolean mAnimationScheduled;
619 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
620 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
621 private int mTransactionSequence;
623 /** Only do a maximum of 6 repeated layouts. After that quit */
624 private int mLayoutRepeatCount;
626 final WindowAnimator mAnimator;
628 SparseArray<Task> mTaskIdToTask = new SparseArray<Task>();
630 /** All of the TaskStacks in the window manager, unordered. For an ordered list call
631 * DisplayContent.getStacks(). */
632 SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>();
634 private final PointerEventDispatcher mPointerEventDispatcher;
636 private WindowContentFrameStats mTempWindowRenderStats;
638 final class DragInputEventReceiver extends InputEventReceiver {
639 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
640 super(inputChannel, looper);
644 public void onInputEvent(InputEvent event) {
645 boolean handled = false;
647 if (event instanceof MotionEvent
648 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
649 && mDragState != null) {
650 final MotionEvent motionEvent = (MotionEvent)event;
651 boolean endDrag = false;
652 final float newX = motionEvent.getRawX();
653 final float newY = motionEvent.getRawY();
655 switch (motionEvent.getAction()) {
656 case MotionEvent.ACTION_DOWN: {
658 Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer");
662 case MotionEvent.ACTION_MOVE: {
663 synchronized (mWindowMap) {
664 // move the surface and tell the involved window(s) where we are
665 mDragState.notifyMoveLw(newX, newY);
669 case MotionEvent.ACTION_UP: {
670 if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at "
671 + newX + "," + newY);
672 synchronized (mWindowMap) {
673 endDrag = mDragState.notifyDropLw(newX, newY);
677 case MotionEvent.ACTION_CANCEL: {
678 if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!");
684 if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state");
685 // tell all the windows that the drag has ended
686 synchronized (mWindowMap) {
687 mDragState.endDragLw();
693 } catch (Exception e) {
694 Slog.e(TAG, "Exception caught by drag handleMotion", e);
696 finishInputEvent(event, handled);
702 * Whether the UI is currently running in touch mode (not showing
703 * navigational focus because the user is directly pressing the screen).
705 boolean mInTouchMode = true;
707 private ViewServer mViewServer;
708 private final ArrayList<WindowChangeListener> mWindowChangeListeners =
709 new ArrayList<WindowChangeListener>();
710 private boolean mWindowsChanged = false;
712 public interface WindowChangeListener {
713 public void windowsChanged();
714 public void focusChanged();
717 final Configuration mTempConfiguration = new Configuration();
719 // The desired scaling factor for compatible apps.
720 float mCompatibleScreenScale;
722 // If true, only the core apps and services are being launched because the device
723 // is in a special boot mode, such as being encrypted or waiting for a decryption password.
724 // For example, when this flag is true, there will be no wallpaper service.
725 final boolean mOnlyCore;
727 public static WindowManagerService main(final Context context,
728 final InputManagerService im,
729 final boolean haveInputMethods, final boolean showBootMsgs,
730 final boolean onlyCore) {
731 final WindowManagerService[] holder = new WindowManagerService[1];
732 DisplayThread.getHandler().runWithScissors(new Runnable() {
735 holder[0] = new WindowManagerService(context, im,
736 haveInputMethods, showBootMsgs, onlyCore);
742 private void initPolicy() {
743 UiThread.getHandler().runWithScissors(new Runnable() {
746 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
748 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
749 mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer()
750 * TYPE_LAYER_MULTIPLIER
756 private WindowManagerService(Context context, InputManagerService inputManager,
757 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
759 mHaveInputMethods = haveInputMethods;
760 mAllowBootMessages = showBootMsgs;
761 mOnlyCore = onlyCore;
762 mLimitedAlphaCompositing = context.getResources().getBoolean(
763 com.android.internal.R.bool.config_sf_limitedAlpha);
764 mInputManager = inputManager; // Must be before createDisplayContentLocked.
765 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
766 mDisplaySettings = new DisplaySettings(context);
767 mDisplaySettings.readSettingsLocked();
769 LocalServices.addService(WindowManagerPolicy.class, mPolicy);
771 mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG));
773 mFxSession = new SurfaceSession();
774 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
775 Display[] displays = mDisplayManager.getDisplays();
776 for (Display display : displays) {
777 createDisplayContentLocked(display);
780 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
782 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
783 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
784 mPowerManagerInternal.registerLowPowerModeObserver(
785 new PowerManagerInternal.LowPowerModeListener() {
787 public void onLowPowerModeChanged(boolean enabled) {
788 synchronized (mWindowMap) {
789 if (mAnimationsDisabled != enabled) {
790 mAnimationsDisabled = enabled;
791 dispatchNewAnimatorScaleLocked(null);
796 mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled();
797 mScreenFrozenLock = mPowerManager.newWakeLock(
798 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
799 mScreenFrozenLock.setReferenceCounted(false);
801 mAppTransition = new AppTransition(context, mH);
803 mActivityManager = ActivityManagerNative.getDefault();
804 mBatteryStats = BatteryStatsService.getService();
805 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
806 mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null,
807 new AppOpsManager.OnOpChangedInternalListener() {
809 public void onOpChanged(int op, String packageName) {
815 // Get persisted window scale setting
816 mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
817 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
818 mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
819 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting);
820 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
821 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
823 // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
824 IntentFilter filter = new IntentFilter();
825 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
826 mContext.registerReceiver(mBroadcastReceiver, filter);
828 mHoldingScreenWakeLock = mPowerManager.newWakeLock(
829 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG);
830 mHoldingScreenWakeLock.setReferenceCounted(false);
832 mAnimator = new WindowAnimator(this);
834 LocalServices.addService(WindowManagerInternal.class, new LocalService());
837 // Add ourself to the Watchdog monitors.
838 Watchdog.getInstance().addMonitor(this);
840 SurfaceControl.openTransaction();
842 createWatermarkInTransaction();
843 mFocusedStackFrame = new FocusedStackFrame(
844 getDefaultDisplayContentLocked().getDisplay(), mFxSession);
846 SurfaceControl.closeTransaction();
850 public InputMonitor getInputMonitor() {
851 return mInputMonitor;
855 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
856 throws RemoteException {
858 return super.onTransact(code, data, reply, flags);
859 } catch (RuntimeException e) {
860 // The window manager only throws security exceptions, so let's
862 if (!(e instanceof SecurityException)) {
863 Slog.wtf(TAG, "Window Manager Crash", e);
869 private void placeWindowAfter(WindowState pos, WindowState window) {
870 final WindowList windows = pos.getWindowList();
871 final int i = windows.indexOf(pos);
872 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
873 TAG, "Adding window " + window + " at "
874 + (i+1) + " of " + windows.size() + " (after " + pos + ")");
875 windows.add(i+1, window);
876 mWindowsChanged = true;
879 private void placeWindowBefore(WindowState pos, WindowState window) {
880 final WindowList windows = pos.getWindowList();
881 int i = windows.indexOf(pos);
882 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
883 TAG, "Adding window " + window + " at "
884 + i + " of " + windows.size() + " (before " + pos + ")");
886 Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows);
889 windows.add(i, window);
890 mWindowsChanged = true;
893 //This method finds out the index of a window that has the same app token as
894 //win. used for z ordering the windows in mWindows
895 private int findIdxBasedOnAppTokens(WindowState win) {
896 WindowList windows = win.getWindowList();
897 for(int j = windows.size() - 1; j >= 0; j--) {
898 WindowState wentry = windows.get(j);
899 if(wentry.mAppToken == win.mAppToken) {
907 * Return the list of Windows from the passed token on the given Display.
908 * @param token The token with all the windows.
909 * @param displayContent The display we are interested in.
910 * @return List of windows from token that are on displayContent.
912 WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) {
913 final WindowList windowList = new WindowList();
914 final int count = token.windows.size();
915 for (int i = 0; i < count; i++) {
916 final WindowState win = token.windows.get(i);
917 if (win.getDisplayContent() == displayContent) {
925 * Recursive search through a WindowList and all of its windows' children.
926 * @param targetWin The window to search for.
927 * @param windows The list to search.
928 * @return The index of win in windows or of the window that is an ancestor of win.
930 private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) {
931 for (int i = windows.size() - 1; i >= 0; i--) {
932 final WindowState w = windows.get(i);
933 if (w == targetWin) {
936 if (!w.mChildWindows.isEmpty()) {
937 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) {
945 private int addAppWindowToListLocked(final WindowState win) {
946 final IWindow client = win.mClient;
947 final WindowToken token = win.mToken;
948 final DisplayContent displayContent = win.getDisplayContent();
949 if (displayContent == null) {
950 // It doesn't matter this display is going away.
954 final WindowList windows = win.getWindowList();
955 final int N = windows.size();
956 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
957 int tokenWindowsPos = 0;
958 int windowListPos = tokenWindowList.size();
959 if (!tokenWindowList.isEmpty()) {
960 // If this application has existing windows, we
961 // simply place the new window on top of them... but
962 // keep the starting window on top.
963 if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
964 // Base windows go behind everything else.
965 WindowState lowestWindow = tokenWindowList.get(0);
966 placeWindowBefore(lowestWindow, win);
967 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows);
969 AppWindowToken atoken = win.mAppToken;
970 WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
971 if (atoken != null && lastWindow == atoken.startingWindow) {
972 placeWindowBefore(lastWindow, win);
973 tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows);
975 int newIdx = findIdxBasedOnAppTokens(win);
976 //there is a window above this one associated with the same
977 //apptoken note that the window could be a floating window
978 //that was created later or a window at the top of the list of
979 //windows associated with this token.
980 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
981 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " +
983 windows.add(newIdx + 1, win);
985 // No window from token found on win's display.
988 tokenWindowsPos = indexOfWinInWindowList(
989 windows.get(newIdx), token.windows) + 1;
991 mWindowsChanged = true;
994 return tokenWindowsPos;
997 // No windows from this token on this display
998 if (localLOGV) Slog.v(TAG, "Figuring out where to add app window " + client.asBinder()
999 + " (token=" + token + ")");
1000 // Figure out where the window should go, based on the
1001 // order of applications.
1002 WindowState pos = null;
1004 final ArrayList<Task> tasks = displayContent.getTasks();
1007 for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
1008 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
1009 for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
1010 final AppWindowToken t = tokens.get(tokenNdx);
1016 tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1;
1022 // We haven't reached the token yet; if this token
1023 // is not going to the bottom and has windows on this display, we can
1024 // use it as an anchor for when we do reach the token.
1025 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
1026 if (!t.sendingToBottom && tokenWindowList.size() > 0) {
1027 pos = tokenWindowList.get(0);
1030 if (tokenNdx >= 0) {
1036 // We now know the index into the apps. If we found
1037 // an app window above, that gives us the position; else
1038 // we need to look some more.
1040 // Move behind any windows attached to this one.
1041 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
1042 if (atoken != null) {
1044 getTokenWindowsOnDisplay(atoken, displayContent);
1045 final int NC = tokenWindowList.size();
1047 WindowState bottom = tokenWindowList.get(0);
1048 if (bottom.mSubLayer < 0) {
1053 placeWindowBefore(pos, win);
1054 return tokenWindowsPos;
1057 // Continue looking down until we find the first
1058 // token that has windows on this display.
1059 for ( ; taskNdx >= 0; --taskNdx) {
1060 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
1061 for ( ; tokenNdx >= 0; --tokenNdx) {
1062 final AppWindowToken t = tokens.get(tokenNdx);
1063 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
1064 final int NW = tokenWindowList.size();
1066 pos = tokenWindowList.get(NW-1);
1070 if (tokenNdx >= 0) {
1077 // Move in front of any windows attached to this
1079 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
1080 if (atoken != null) {
1081 final int NC = atoken.windows.size();
1083 WindowState top = atoken.windows.get(NC-1);
1084 if (top.mSubLayer >= 0) {
1089 placeWindowAfter(pos, win);
1090 return tokenWindowsPos;
1093 // Just search for the start of this layer.
1094 final int myLayer = win.mBaseLayer;
1096 for (i = 0; i < N; i++) {
1097 WindowState w = windows.get(i);
1098 if (w.mBaseLayer > myLayer) {
1102 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
1103 "Based on layer: Adding window " + win + " at " + i + " of " + N);
1104 windows.add(i, win);
1105 mWindowsChanged = true;
1106 return tokenWindowsPos;
1109 private void addFreeWindowToListLocked(final WindowState win) {
1110 final WindowList windows = win.getWindowList();
1112 // Figure out where window should go, based on layer.
1113 final int myLayer = win.mBaseLayer;
1115 for (i = windows.size() - 1; i >= 0; i--) {
1116 if (windows.get(i).mBaseLayer <= myLayer) {
1121 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
1122 "Free window: Adding window " + win + " at " + i + " of " + windows.size());
1123 windows.add(i, win);
1124 mWindowsChanged = true;
1127 private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) {
1128 final WindowToken token = win.mToken;
1129 final DisplayContent displayContent = win.getDisplayContent();
1130 if (displayContent == null) {
1133 final WindowState attached = win.mAttachedWindow;
1135 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
1137 // Figure out this window's ordering relative to the window
1138 // it is attached to.
1139 final int NA = tokenWindowList.size();
1140 final int sublayer = win.mSubLayer;
1141 int largestSublayer = Integer.MIN_VALUE;
1142 WindowState windowWithLargestSublayer = null;
1144 for (i = 0; i < NA; i++) {
1145 WindowState w = tokenWindowList.get(i);
1146 final int wSublayer = w.mSubLayer;
1147 if (wSublayer >= largestSublayer) {
1148 largestSublayer = wSublayer;
1149 windowWithLargestSublayer = w;
1152 // For negative sublayers, we go below all windows
1153 // in the same sublayer.
1154 if (wSublayer >= sublayer) {
1156 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1157 token.windows.add(i, win);
1159 placeWindowBefore(wSublayer >= 0 ? attached : w, win);
1163 // For positive sublayers, we go above all windows
1164 // in the same sublayer.
1165 if (wSublayer > sublayer) {
1167 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1168 token.windows.add(i, win);
1170 placeWindowBefore(w, win);
1177 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1178 token.windows.add(win);
1181 placeWindowBefore(attached, win);
1183 placeWindowAfter(largestSublayer >= 0
1184 ? windowWithLargestSublayer
1191 private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) {
1192 if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win +
1193 " Callers=" + Debug.getCallers(4));
1194 if (win.mAttachedWindow == null) {
1195 final WindowToken token = win.mToken;
1196 int tokenWindowsPos = 0;
1197 if (token.appWindowToken != null) {
1198 tokenWindowsPos = addAppWindowToListLocked(win);
1200 addFreeWindowToListLocked(win);
1203 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1204 token.windows.add(tokenWindowsPos, win);
1207 addAttachedWindowToListLocked(win, addToToken);
1210 if (win.mAppToken != null && addToToken) {
1211 win.mAppToken.allAppWindows.add(win);
1215 static boolean canBeImeTarget(WindowState w) {
1216 final int fl = w.mAttrs.flags
1217 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
1218 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)
1219 || w.mAttrs.type == TYPE_APPLICATION_STARTING) {
1220 if (DEBUG_INPUT_METHOD) {
1221 Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
1222 if (!w.isVisibleOrAdding()) {
1223 Slog.i(TAG, " mSurface=" + w.mWinAnimator.mSurfaceControl
1224 + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility
1225 + " policyVis=" + w.mPolicyVisibility
1226 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
1227 + " attachHid=" + w.mAttachedHidden
1228 + " exiting=" + w.mExiting + " destroying=" + w.mDestroying);
1229 if (w.mAppToken != null) {
1230 Slog.i(TAG, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
1234 return w.isVisibleOrAdding();
1240 * Dig through the WindowStates and find the one that the Input Method will target.
1242 * @return The index+1 in mWindows of the discovered target.
1244 int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
1245 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
1246 // same display. Or even when the current IME/target are not on the same screen as the next
1247 // IME/target. For now only look for input windows on the main screen.
1248 WindowList windows = getDefaultWindowListLocked();
1249 WindowState w = null;
1251 for (i = windows.size() - 1; i >= 0; --i) {
1252 WindowState win = windows.get(i);
1254 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i
1255 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
1256 if (canBeImeTarget(win)) {
1258 //Slog.i(TAG, "Putting input method here!");
1260 // Yet more tricksyness! If this window is a "starting"
1261 // window, we do actually want to be on top of it, but
1262 // it is not -really- where input will go. So if the caller
1263 // is not actually looking to move the IME, look down below
1264 // for a real window to target...
1266 && w.mAttrs.type == TYPE_APPLICATION_STARTING
1268 WindowState wb = windows.get(i-1);
1269 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
1278 // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
1280 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w);
1282 // Now, a special case -- if the last target's window is in the
1283 // process of exiting, and is above the new target, keep on the
1284 // last target to avoid flicker. Consider for example a Dialog with
1285 // the IME shown: when the Dialog is dismissed, we want to keep
1286 // the IME above it until it is completely gone so it doesn't drop
1287 // behind the dialog or its full-screen scrim.
1288 final WindowState curTarget = mInputMethodTarget;
1289 if (curTarget != null
1290 && curTarget.isDisplayedLw()
1291 && curTarget.isClosing()
1292 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
1293 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing");
1294 return windows.indexOf(curTarget) + 1;
1297 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
1298 + w + " willMove=" + willMove);
1300 if (willMove && w != null) {
1301 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
1302 if (token != null) {
1304 // Now some fun for dealing with window animations that
1305 // modify the Z order. We need to look at all windows below
1306 // the current target that are in this app, finding the highest
1307 // visible one in layering.
1308 WindowState highestTarget = null;
1310 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
1311 WindowList curWindows = curTarget.getWindowList();
1312 int pos = curWindows.indexOf(curTarget);
1314 WindowState win = curWindows.get(pos);
1315 if (win.mAppToken != token) {
1318 if (!win.mRemoved) {
1319 if (highestTarget == null || win.mWinAnimator.mAnimLayer >
1320 highestTarget.mWinAnimator.mAnimLayer) {
1321 highestTarget = win;
1329 if (highestTarget != null) {
1330 if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget
1331 + " animating=" + highestTarget.mWinAnimator.isAnimating()
1332 + " layer=" + highestTarget.mWinAnimator.mAnimLayer
1333 + " new layer=" + w.mWinAnimator.mAnimLayer);
1335 if (mAppTransition.isTransitionSet()) {
1336 // If we are currently setting up for an animation,
1337 // hold everything until we can find out what will happen.
1338 mInputMethodTargetWaitingAnim = true;
1339 mInputMethodTarget = highestTarget;
1340 return highestPos + 1;
1341 } else if (highestTarget.mWinAnimator.isAnimating() &&
1342 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
1343 // If the window we are currently targeting is involved
1344 // with an animation, and it is on top of the next target
1345 // we will be over, then hold off on moving until
1347 mInputMethodTargetWaitingAnim = true;
1348 mInputMethodTarget = highestTarget;
1349 return highestPos + 1;
1355 //Slog.i(TAG, "Placing input method @" + (i+1));
1358 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to "
1359 + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
1360 mInputMethodTarget = w;
1361 mInputMethodTargetWaitingAnim = false;
1362 if (w.mAppToken != null) {
1363 setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment);
1365 setInputMethodAnimLayerAdjustment(0);
1371 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null."
1372 + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
1373 mInputMethodTarget = null;
1374 setInputMethodAnimLayerAdjustment(0);
1379 void addInputMethodWindowToListLocked(WindowState win) {
1380 int pos = findDesiredInputMethodWindowIndexLocked(true);
1382 win.mTargetAppToken = mInputMethodTarget.mAppToken;
1383 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
1384 TAG, "Adding input method window " + win + " at " + pos);
1385 // TODO(multidisplay): IMEs are only supported on the default display.
1386 getDefaultWindowListLocked().add(pos, win);
1387 mWindowsChanged = true;
1388 moveInputMethodDialogsLocked(pos+1);
1391 win.mTargetAppToken = null;
1392 addWindowToListInOrderLocked(win, true);
1393 moveInputMethodDialogsLocked(pos);
1396 void setInputMethodAnimLayerAdjustment(int adj) {
1397 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj);
1398 mInputMethodAnimLayerAdjustment = adj;
1399 WindowState imw = mInputMethodWindow;
1401 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
1402 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
1403 + " anim layer: " + imw.mWinAnimator.mAnimLayer);
1404 int wi = imw.mChildWindows.size();
1407 WindowState cw = imw.mChildWindows.get(wi);
1408 cw.mWinAnimator.mAnimLayer = cw.mLayer + adj;
1409 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw
1410 + " anim layer: " + cw.mWinAnimator.mAnimLayer);
1413 int di = mInputMethodDialogs.size();
1416 imw = mInputMethodDialogs.get(di);
1417 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
1418 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
1419 + " anim layer: " + imw.mWinAnimator.mAnimLayer);
1423 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1424 WindowList windows = win.getWindowList();
1425 int wpos = windows.indexOf(win);
1427 if (wpos < interestingPos) interestingPos--;
1428 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
1429 windows.remove(wpos);
1430 mWindowsChanged = true;
1431 int NC = win.mChildWindows.size();
1434 WindowState cw = win.mChildWindows.get(NC);
1435 int cpos = windows.indexOf(cw);
1437 if (cpos < interestingPos) interestingPos--;
1438 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
1439 + cpos + ": " + cw);
1440 windows.remove(cpos);
1444 return interestingPos;
1447 private void reAddWindowToListInOrderLocked(WindowState win) {
1448 addWindowToListInOrderLocked(win, false);
1449 // This is a hack to get all of the child windows added as well
1450 // at the right position. Child windows should be rare and
1451 // this case should be rare, so it shouldn't be that big a deal.
1452 WindowList windows = win.getWindowList();
1453 int wpos = windows.indexOf(win);
1455 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win);
1456 windows.remove(wpos);
1457 mWindowsChanged = true;
1458 reAddWindowLocked(wpos, win);
1462 void logWindowList(final WindowList windows, String prefix) {
1463 int N = windows.size();
1466 Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N));
1470 void moveInputMethodDialogsLocked(int pos) {
1471 ArrayList<WindowState> dialogs = mInputMethodDialogs;
1473 // TODO(multidisplay): IMEs are only supported on the default display.
1474 WindowList windows = getDefaultWindowListLocked();
1475 final int N = dialogs.size();
1476 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
1477 for (int i=0; i<N; i++) {
1478 pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1480 if (DEBUG_INPUT_METHOD) {
1481 Slog.v(TAG, "Window list w/pos=" + pos);
1482 logWindowList(windows, " ");
1486 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1487 // Skip windows owned by the input method.
1488 if (mInputMethodWindow != null) {
1489 while (pos < windows.size()) {
1490 WindowState wp = windows.get(pos);
1491 if (wp == mInputMethodWindow || wp.mAttachedWindow == mInputMethodWindow) {
1498 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
1499 for (int i=0; i<N; i++) {
1500 WindowState win = dialogs.get(i);
1501 win.mTargetAppToken = targetAppToken;
1502 pos = reAddWindowLocked(pos, win);
1504 if (DEBUG_INPUT_METHOD) {
1505 Slog.v(TAG, "Final window list:");
1506 logWindowList(windows, " ");
1510 for (int i=0; i<N; i++) {
1511 WindowState win = dialogs.get(i);
1512 win.mTargetAppToken = null;
1513 reAddWindowToListInOrderLocked(win);
1514 if (DEBUG_INPUT_METHOD) {
1515 Slog.v(TAG, "No IM target, final list:");
1516 logWindowList(windows, " ");
1521 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1522 final WindowState imWin = mInputMethodWindow;
1523 final int DN = mInputMethodDialogs.size();
1524 if (imWin == null && DN == 0) {
1528 // TODO(multidisplay): IMEs are only supported on the default display.
1529 WindowList windows = getDefaultWindowListLocked();
1531 int imPos = findDesiredInputMethodWindowIndexLocked(true);
1533 // In this case, the input method windows are to be placed
1534 // immediately above the window they are targeting.
1536 // First check to see if the input method windows are already
1537 // located here, and contiguous.
1538 final int N = windows.size();
1539 WindowState firstImWin = imPos < N
1540 ? windows.get(imPos) : null;
1542 // Figure out the actual input method window that should be
1543 // at the bottom of their stack.
1544 WindowState baseImWin = imWin != null
1545 ? imWin : mInputMethodDialogs.get(0);
1546 if (baseImWin.mChildWindows.size() > 0) {
1547 WindowState cw = baseImWin.mChildWindows.get(0);
1548 if (cw.mSubLayer < 0) baseImWin = cw;
1551 if (firstImWin == baseImWin) {
1552 // The windows haven't moved... but are they still contiguous?
1553 // First find the top IM window.
1556 if (!(windows.get(pos)).mIsImWindow) {
1562 // Now there should be no more input method windows above.
1564 if ((windows.get(pos)).mIsImWindow) {
1571 // The IM target window may be changed, so update the mTargetAppToken.
1572 if (imWin != null) {
1573 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1579 if (imWin != null) {
1580 if (DEBUG_INPUT_METHOD) {
1581 Slog.v(TAG, "Moving IM from " + imPos);
1582 logWindowList(windows, " ");
1584 imPos = tmpRemoveWindowLocked(imPos, imWin);
1585 if (DEBUG_INPUT_METHOD) {
1586 Slog.v(TAG, "List after removing with new pos " + imPos + ":");
1587 logWindowList(windows, " ");
1589 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1590 reAddWindowLocked(imPos, imWin);
1591 if (DEBUG_INPUT_METHOD) {
1592 Slog.v(TAG, "List after moving IM to " + imPos + ":");
1593 logWindowList(windows, " ");
1595 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1597 moveInputMethodDialogsLocked(imPos);
1601 // In this case, the input method windows go in a fixed layer,
1602 // because they aren't currently associated with a focus window.
1604 if (imWin != null) {
1605 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos);
1606 tmpRemoveWindowLocked(0, imWin);
1607 imWin.mTargetAppToken = null;
1608 reAddWindowToListInOrderLocked(imWin);
1609 if (DEBUG_INPUT_METHOD) {
1610 Slog.v(TAG, "List with no IM target:");
1611 logWindowList(windows, " ");
1613 if (DN > 0) moveInputMethodDialogsLocked(-1);
1615 moveInputMethodDialogsLocked(-1);
1620 if (needAssignLayers) {
1621 assignLayersLocked(windows);
1627 final boolean isWallpaperVisible(WindowState wallpaperTarget) {
1628 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
1629 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
1630 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
1631 ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
1632 + " upper=" + mUpperWallpaperTarget
1633 + " lower=" + mLowerWallpaperTarget);
1634 return (wallpaperTarget != null
1635 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
1636 && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
1637 || mUpperWallpaperTarget != null
1638 || mLowerWallpaperTarget != null;
1641 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
1642 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
1644 int adjustWallpaperWindowsLocked() {
1645 mInnerFields.mWallpaperMayChange = false;
1646 boolean targetChanged = false;
1648 // TODO(multidisplay): Wallpapers on main screen only.
1649 final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo();
1650 final int dw = displayInfo.logicalWidth;
1651 final int dh = displayInfo.logicalHeight;
1653 // First find top-most window that has asked to be on top of the
1654 // wallpaper; all wallpapers go behind it.
1655 final WindowList windows = getDefaultWindowListLocked();
1656 int N = windows.size();
1657 WindowState w = null;
1658 WindowState foundW = null;
1660 WindowState topCurW = null;
1662 int windowDetachedI = -1;
1667 if ((w.mAttrs.type == TYPE_WALLPAPER)) {
1668 if (topCurW == null) {
1675 if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
1676 // If this window's app token is hidden and not animating,
1677 // it is of no interest to us.
1678 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
1679 if (DEBUG_WALLPAPER) Slog.v(TAG,
1680 "Skipping hidden and not animating token: " + w);
1684 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
1685 + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
1686 if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isOnScreen()
1687 && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
1688 if (DEBUG_WALLPAPER) Slog.v(TAG,
1689 "Found wallpaper target: #" + i + "=" + w);
1692 if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) {
1693 // The current wallpaper target is animating, so we'll
1694 // look behind it for another possible target and figure
1695 // out what is going on below.
1696 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
1697 + ": token animating, looking behind.");
1701 } else if (w == mAnimator.mWindowDetachedWallpaper) {
1702 windowDetachedI = i;
1706 if (foundW == null && windowDetachedI >= 0) {
1707 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
1708 "Found animating detached wallpaper activity: #" + i + "=" + w);
1710 foundI = windowDetachedI;
1713 if (mWallpaperTarget != foundW
1714 && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) {
1715 if (DEBUG_WALLPAPER_LIGHT) {
1716 Slog.v(TAG, "New wallpaper target: " + foundW
1717 + " oldTarget: " + mWallpaperTarget);
1720 mLowerWallpaperTarget = null;
1721 mUpperWallpaperTarget = null;
1723 WindowState oldW = mWallpaperTarget;
1724 mWallpaperTarget = foundW;
1725 targetChanged = true;
1727 // Now what is happening... if the current and new targets are
1728 // animating, then we are in our super special mode!
1729 if (foundW != null && oldW != null) {
1730 boolean oldAnim = oldW.isAnimatingLw();
1731 boolean foundAnim = foundW.isAnimatingLw();
1732 if (DEBUG_WALLPAPER_LIGHT) {
1733 Slog.v(TAG, "New animation: " + foundAnim
1734 + " old animation: " + oldAnim);
1736 if (foundAnim && oldAnim) {
1737 int oldI = windows.indexOf(oldW);
1738 if (DEBUG_WALLPAPER_LIGHT) {
1739 Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
1742 if (DEBUG_WALLPAPER_LIGHT) {
1743 Slog.v(TAG, "Animating wallpapers: old#" + oldI
1744 + "=" + oldW + "; new#" + foundI
1748 // Set the new target correctly.
1749 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
1750 if (DEBUG_WALLPAPER_LIGHT) {
1751 Slog.v(TAG, "Old wallpaper still the target.");
1753 mWallpaperTarget = oldW;
1757 // Now set the upper and lower wallpaper targets
1758 // correctly, and make sure that we are positioning
1759 // the wallpaper below the lower.
1760 else if (foundI > oldI) {
1761 // The new target is on top of the old one.
1762 if (DEBUG_WALLPAPER_LIGHT) {
1763 Slog.v(TAG, "Found target above old target.");
1765 mUpperWallpaperTarget = foundW;
1766 mLowerWallpaperTarget = oldW;
1770 // The new target is below the old one.
1771 if (DEBUG_WALLPAPER_LIGHT) {
1772 Slog.v(TAG, "Found target below old target.");
1774 mUpperWallpaperTarget = oldW;
1775 mLowerWallpaperTarget = foundW;
1781 } else if (mLowerWallpaperTarget != null) {
1782 // Is it time to stop animating?
1783 if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
1784 if (DEBUG_WALLPAPER_LIGHT) {
1785 Slog.v(TAG, "No longer animating wallpaper targets!");
1787 mLowerWallpaperTarget = null;
1788 mUpperWallpaperTarget = null;
1789 mWallpaperTarget = foundW;
1790 targetChanged = true;
1794 boolean visible = foundW != null;
1796 // The window is visible to the compositor... but is it visible
1797 // to the user? That is what the wallpaper cares about.
1798 visible = isWallpaperVisible(foundW);
1799 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
1801 // If the wallpaper target is animating, we may need to copy
1802 // its layer adjustment. Only do this if we are not transfering
1803 // between two wallpaper targets.
1804 mWallpaperAnimLayerAdjustment =
1805 (mLowerWallpaperTarget == null && foundW.mAppToken != null)
1806 ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0;
1808 final int maxLayer = mPolicy.getMaxWallpaperLayer()
1809 * TYPE_LAYER_MULTIPLIER
1810 + TYPE_LAYER_OFFSET;
1812 // Now w is the window we are supposed to be behind... but we
1813 // need to be sure to also be behind any of its attached windows,
1814 // AND any starting window associated with it, AND below the
1815 // maximum layer the policy allows for wallpapers.
1816 while (foundI > 0) {
1817 WindowState wb = windows.get(foundI-1);
1818 if (wb.mBaseLayer < maxLayer &&
1819 wb.mAttachedWindow != foundW &&
1820 (foundW.mAttachedWindow == null ||
1821 wb.mAttachedWindow != foundW.mAttachedWindow) &&
1822 (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
1823 foundW.mToken == null || wb.mToken != foundW.mToken)) {
1824 // This window is not related to the previous one in any
1825 // interesting way, so stop here.
1832 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
1835 if (foundW == null && topCurW != null) {
1836 // There is no wallpaper target, so it goes at the bottom.
1837 // We will assume it is the same place as last time, if known.
1841 // Okay i is the position immediately above the wallpaper. Look at
1842 // what is below it for later.
1843 foundW = foundI > 0 ? windows.get(foundI-1) : null;
1847 if (mWallpaperTarget.mWallpaperX >= 0) {
1848 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
1849 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
1851 if (mWallpaperTarget.mWallpaperY >= 0) {
1852 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
1853 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
1857 // Start stepping backwards from here, ensuring that our wallpaper windows
1858 // are correctly placed.
1860 int curTokenIndex = mWallpaperTokens.size();
1861 while (curTokenIndex > 0) {
1863 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1864 if (token.hidden == visible) {
1865 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
1866 "Wallpaper token " + token + " hidden=" + !visible);
1867 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
1868 token.hidden = !visible;
1869 // Need to do a layout to ensure the wallpaper now has the
1871 getDefaultDisplayContentLocked().layoutNeeded = true;
1874 int curWallpaperIndex = token.windows.size();
1875 while (curWallpaperIndex > 0) {
1876 curWallpaperIndex--;
1877 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1880 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
1883 // First, make sure the client has the current visibility
1885 dispatchWallpaperVisibility(wallpaper, visible);
1887 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
1888 if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
1889 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
1891 // First, if this window is at the current index, then all
1893 if (wallpaper == foundW) {
1896 ? windows.get(foundI-1) : null;
1900 // The window didn't match... the current wallpaper window,
1901 // wherever it is, is in the wrong place, so make sure it is
1903 int oldIndex = windows.indexOf(wallpaper);
1904 if (oldIndex >= 0) {
1905 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
1906 + oldIndex + ": " + wallpaper);
1907 windows.remove(oldIndex);
1908 mWindowsChanged = true;
1909 if (oldIndex < foundI) {
1914 // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
1915 // layer. For keyguard over wallpaper put the wallpaper under the keyguard.
1916 int insertionIndex = 0;
1917 if (visible && foundW != null) {
1918 final int type = foundW.mAttrs.type;
1919 final int privateFlags = foundW.mAttrs.privateFlags;
1920 if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0
1921 || type == TYPE_KEYGUARD_SCRIM) {
1922 insertionIndex = windows.indexOf(foundW);
1925 if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
1926 Slog.v(TAG, "Moving wallpaper " + wallpaper
1927 + " from " + oldIndex + " to " + insertionIndex);
1930 windows.add(insertionIndex, wallpaper);
1931 mWindowsChanged = true;
1932 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
1937 final TaskStack targetStack =
1938 mWallpaperTarget == null ? null : mWallpaperTarget.getStack();
1939 if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 &&
1940 targetStack != null && !targetStack.isHomeStack()) {
1941 // If the wallpaper target is not on the home stack then make sure that all windows
1942 // from other non-home stacks are above the wallpaper.
1943 for (i = foundI - 1; i >= 0; --i) {
1944 WindowState win = windows.get(i);
1945 if (!win.isVisibleLw()) {
1948 final TaskStack winStack = win.getStack();
1949 if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) {
1951 windows.add(foundI + 1, win);
1957 if (targetChanged && DEBUG_WALLPAPER_LIGHT) {
1958 Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget
1959 + " lower=" + mLowerWallpaperTarget + " upper="
1960 + mUpperWallpaperTarget);
1966 void setWallpaperAnimLayerAdjustmentLocked(int adj) {
1967 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
1968 "Setting wallpaper layer adj to " + adj);
1969 mWallpaperAnimLayerAdjustment = adj;
1970 int curTokenIndex = mWallpaperTokens.size();
1971 while (curTokenIndex > 0) {
1973 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1974 int curWallpaperIndex = token.windows.size();
1975 while (curWallpaperIndex > 0) {
1976 curWallpaperIndex--;
1977 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1978 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj;
1979 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win "
1980 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
1985 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
1987 boolean changed = false;
1988 boolean rawChanged = false;
1989 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
1990 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
1991 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
1992 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
1993 changed = wallpaperWin.mXOffset != offset;
1995 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
1996 + wallpaperWin + " x: " + offset);
1997 wallpaperWin.mXOffset = offset;
1999 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
2000 wallpaperWin.mWallpaperX = wpx;
2001 wallpaperWin.mWallpaperXStep = wpxs;
2005 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
2006 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
2007 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
2008 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
2009 if (wallpaperWin.mYOffset != offset) {
2010 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
2011 + wallpaperWin + " y: " + offset);
2013 wallpaperWin.mYOffset = offset;
2015 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
2016 wallpaperWin.mWallpaperY = wpy;
2017 wallpaperWin.mWallpaperYStep = wpys;
2021 if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
2022 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
2024 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
2025 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
2026 + " y=" + wallpaperWin.mWallpaperY);
2028 mWaitingOnWallpaper = wallpaperWin;
2030 wallpaperWin.mClient.dispatchWallpaperOffsets(
2031 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
2032 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
2034 if (mWaitingOnWallpaper != null) {
2035 long start = SystemClock.uptimeMillis();
2036 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
2039 if (DEBUG_WALLPAPER) Slog.v(TAG,
2040 "Waiting for offset complete...");
2041 mWindowMap.wait(WALLPAPER_TIMEOUT);
2042 } catch (InterruptedException e) {
2044 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
2045 if ((start+WALLPAPER_TIMEOUT)
2046 < SystemClock.uptimeMillis()) {
2047 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
2049 mLastWallpaperTimeoutTime = start;
2052 mWaitingOnWallpaper = null;
2055 } catch (RemoteException e) {
2062 void wallpaperOffsetsComplete(IBinder window) {
2063 synchronized (mWindowMap) {
2064 if (mWaitingOnWallpaper != null &&
2065 mWaitingOnWallpaper.mClient.asBinder() == window) {
2066 mWaitingOnWallpaper = null;
2067 mWindowMap.notifyAll();
2072 void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
2073 final DisplayContent displayContent = changingTarget.getDisplayContent();
2074 if (displayContent == null) {
2077 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2078 final int dw = displayInfo.logicalWidth;
2079 final int dh = displayInfo.logicalHeight;
2081 WindowState target = mWallpaperTarget;
2082 if (target != null) {
2083 if (target.mWallpaperX >= 0) {
2084 mLastWallpaperX = target.mWallpaperX;
2085 } else if (changingTarget.mWallpaperX >= 0) {
2086 mLastWallpaperX = changingTarget.mWallpaperX;
2088 if (target.mWallpaperY >= 0) {
2089 mLastWallpaperY = target.mWallpaperY;
2090 } else if (changingTarget.mWallpaperY >= 0) {
2091 mLastWallpaperY = changingTarget.mWallpaperY;
2095 int curTokenIndex = mWallpaperTokens.size();
2096 while (curTokenIndex > 0) {
2098 WindowToken token = mWallpaperTokens.get(curTokenIndex);
2099 int curWallpaperIndex = token.windows.size();
2100 while (curWallpaperIndex > 0) {
2101 curWallpaperIndex--;
2102 WindowState wallpaper = token.windows.get(curWallpaperIndex);
2103 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
2104 WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
2105 winAnimator.computeShownFrameLocked();
2106 // No need to lay out the windows - we can just set the wallpaper position
2108 winAnimator.setWallpaperOffset(wallpaper.mShownFrame);
2109 // We only want to be synchronous with one wallpaper.
2117 * Check wallpaper for visiblity change and notify window if so.
2118 * @param wallpaper The wallpaper to test and notify.
2119 * @param visible Current visibility.
2121 void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) {
2122 if (wallpaper.mWallpaperVisible != visible) {
2123 wallpaper.mWallpaperVisible = visible;
2125 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
2126 "Updating vis of wallpaper " + wallpaper
2127 + ": " + visible + " from:\n" + Debug.getCallers(4, " "));
2128 wallpaper.mClient.dispatchAppVisibility(visible);
2129 } catch (RemoteException e) {
2134 void updateWallpaperVisibilityLocked() {
2135 final boolean visible = isWallpaperVisible(mWallpaperTarget);
2136 final DisplayContent displayContent = mWallpaperTarget.getDisplayContent();
2137 if (displayContent == null) {
2140 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2141 final int dw = displayInfo.logicalWidth;
2142 final int dh = displayInfo.logicalHeight;
2144 int curTokenIndex = mWallpaperTokens.size();
2145 while (curTokenIndex > 0) {
2147 WindowToken token = mWallpaperTokens.get(curTokenIndex);
2148 if (token.hidden == visible) {
2149 token.hidden = !visible;
2150 // Need to do a layout to ensure the wallpaper now has the
2152 getDefaultDisplayContentLocked().layoutNeeded = true;
2155 int curWallpaperIndex = token.windows.size();
2156 while (curWallpaperIndex > 0) {
2157 curWallpaperIndex--;
2158 WindowState wallpaper = token.windows.get(curWallpaperIndex);
2160 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
2163 dispatchWallpaperVisibility(wallpaper, visible);
2168 public int addWindow(Session session, IWindow client, int seq,
2169 WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
2170 Rect outContentInsets, InputChannel outInputChannel) {
2171 int[] appOp = new int[1];
2172 int res = mPolicy.checkAddPermission(attrs, appOp);
2173 if (res != WindowManagerGlobal.ADD_OKAY) {
2177 boolean reportNewConfig = false;
2178 WindowState attachedWindow = null;
2179 WindowState win = null;
2181 final int type = attrs.type;
2183 synchronized(mWindowMap) {
2184 if (!mDisplayReady) {
2185 throw new IllegalStateException("Display has not been initialialized");
2188 final DisplayContent displayContent = getDisplayContentLocked(displayId);
2189 if (displayContent == null) {
2190 Slog.w(TAG, "Attempted to add window to a display that does not exist: "
2191 + displayId + ". Aborting.");
2192 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2194 if (!displayContent.hasAccess(session.mUid)) {
2195 Slog.w(TAG, "Attempted to add window to a display for which the application "
2196 + "does not have access: " + displayId + ". Aborting.");
2197 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2200 if (mWindowMap.containsKey(client.asBinder())) {
2201 Slog.w(TAG, "Window " + client + " is already added");
2202 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
2205 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
2206 attachedWindow = windowForClientLocked(null, attrs.token, false);
2207 if (attachedWindow == null) {
2208 Slog.w(TAG, "Attempted to add window with token that is not a window: "
2209 + attrs.token + ". Aborting.");
2210 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
2212 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
2213 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
2214 Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
2215 + attrs.token + ". Aborting.");
2216 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
2220 if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
2221 Slog.w(TAG, "Attempted to add private presentation window to a non-private display. Aborting.");
2222 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2225 boolean addToken = false;
2226 WindowToken token = mTokenMap.get(attrs.token);
2227 if (token == null) {
2228 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2229 Slog.w(TAG, "Attempted to add application window with unknown token "
2230 + attrs.token + ". Aborting.");
2231 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2233 if (type == TYPE_INPUT_METHOD) {
2234 Slog.w(TAG, "Attempted to add input method window with unknown token "
2235 + attrs.token + ". Aborting.");
2236 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2238 if (type == TYPE_VOICE_INTERACTION) {
2239 Slog.w(TAG, "Attempted to add voice interaction window with unknown token "
2240 + attrs.token + ". Aborting.");
2241 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2243 if (type == TYPE_WALLPAPER) {
2244 Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
2245 + attrs.token + ". Aborting.");
2246 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2248 if (type == TYPE_DREAM) {
2249 Slog.w(TAG, "Attempted to add Dream window with unknown token "
2250 + attrs.token + ". Aborting.");
2251 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2253 token = new WindowToken(this, attrs.token, -1, false);
2255 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2256 AppWindowToken atoken = token.appWindowToken;
2257 if (atoken == null) {
2258 Slog.w(TAG, "Attempted to add window with non-application token "
2259 + token + ". Aborting.");
2260 return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
2261 } else if (atoken.removed) {
2262 Slog.w(TAG, "Attempted to add window with exiting application token "
2263 + token + ". Aborting.");
2264 return WindowManagerGlobal.ADD_APP_EXITING;
2266 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
2267 // No need for this guy!
2268 if (localLOGV) Slog.v(
2269 TAG, "**** NO NEED TO START: " + attrs.getTitle());
2270 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
2272 } else if (type == TYPE_INPUT_METHOD) {
2273 if (token.windowType != TYPE_INPUT_METHOD) {
2274 Slog.w(TAG, "Attempted to add input method window with bad token "
2275 + attrs.token + ". Aborting.");
2276 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2278 } else if (type == TYPE_VOICE_INTERACTION) {
2279 if (token.windowType != TYPE_VOICE_INTERACTION) {
2280 Slog.w(TAG, "Attempted to add voice interaction window with bad token "
2281 + attrs.token + ". Aborting.");
2282 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2284 } else if (type == TYPE_WALLPAPER) {
2285 if (token.windowType != TYPE_WALLPAPER) {
2286 Slog.w(TAG, "Attempted to add wallpaper window with bad token "
2287 + attrs.token + ". Aborting.");
2288 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2290 } else if (type == TYPE_DREAM) {
2291 if (token.windowType != TYPE_DREAM) {
2292 Slog.w(TAG, "Attempted to add Dream window with bad token "
2293 + attrs.token + ". Aborting.");
2294 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2298 win = new WindowState(this, session, client, token,
2299 attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
2300 if (win.mDeathRecipient == null) {
2301 // Client has apparently died, so there is no reason to
2303 Slog.w(TAG, "Adding window client " + client.asBinder()
2304 + " that is dead, aborting.");
2305 return WindowManagerGlobal.ADD_APP_EXITING;
2308 if (win.getDisplayContent() == null) {
2309 Slog.w(TAG, "Adding window to Display that has been removed.");
2310 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2313 mPolicy.adjustWindowParamsLw(win.mAttrs);
2314 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
2316 res = mPolicy.prepareAddWindowLw(win, attrs);
2317 if (res != WindowManagerGlobal.ADD_OKAY) {
2321 if (outInputChannel != null && (attrs.inputFeatures
2322 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
2323 String name = win.makeInputChannelName();
2324 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
2325 win.setInputChannel(inputChannels[0]);
2326 inputChannels[1].transferTo(outInputChannel);
2328 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
2331 // From now on, no exceptions or errors allowed!
2333 res = WindowManagerGlobal.ADD_OKAY;
2335 origId = Binder.clearCallingIdentity();
2338 mTokenMap.put(attrs.token, token);
2341 mWindowMap.put(client.asBinder(), win);
2342 if (win.mAppOp != AppOpsManager.OP_NONE) {
2343 if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage())
2344 != AppOpsManager.MODE_ALLOWED) {
2345 win.setAppOpVisibilityLw(false);
2349 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
2350 token.appWindowToken.startingWindow = win;
2351 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken
2352 + " startingWindow=" + win);
2355 boolean imMayMove = true;
2357 if (type == TYPE_INPUT_METHOD) {
2358 win.mGivenInsetsPending = true;
2359 mInputMethodWindow = win;
2360 addInputMethodWindowToListLocked(win);
2362 } else if (type == TYPE_INPUT_METHOD_DIALOG) {
2363 mInputMethodDialogs.add(win);
2364 addWindowToListInOrderLocked(win, true);
2365 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
2368 addWindowToListInOrderLocked(win, true);
2369 if (type == TYPE_WALLPAPER) {
2370 mLastWallpaperTimeoutTime = 0;
2371 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2372 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2373 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2374 } else if (mWallpaperTarget != null
2375 && mWallpaperTarget.mLayer >= win.mBaseLayer) {
2376 // If there is currently a wallpaper being shown, and
2377 // the base layer of the new window is below the current
2378 // layer of the target window, then adjust the wallpaper.
2379 // This is to avoid a new window being placed between the
2380 // wallpaper and its target.
2381 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2385 win.mWinAnimator.mEnterAnimationPending = true;
2387 if (displayContent.isDefaultDisplay) {
2388 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
2390 outContentInsets.setEmpty();
2394 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
2396 if (win.mAppToken == null || !win.mAppToken.clientHidden) {
2397 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
2400 mInputMonitor.setUpdateInputWindowsNeededLw();
2402 boolean focusChanged = false;
2403 if (win.canReceiveKeys()) {
2404 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
2405 false /*updateInputWindows*/);
2412 moveInputMethodWindowsIfNeededLocked(false);
2415 assignLayersLocked(displayContent.getWindowList());
2416 // Don't do layout here, the window must call
2417 // relayout to be displayed, so we'll do it there.
2420 finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/);
2422 mInputMonitor.updateInputWindowsLw(false /*force*/);
2424 if (localLOGV) Slog.v(
2425 TAG, "New client " + client.asBinder()
2426 + ": window=" + win);
2428 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
2429 reportNewConfig = true;
2433 if (reportNewConfig) {
2434 sendNewConfiguration();
2437 Binder.restoreCallingIdentity(origId);
2442 public void removeWindow(Session session, IWindow client) {
2443 synchronized(mWindowMap) {
2444 WindowState win = windowForClientLocked(session, client, false);
2448 removeWindowLocked(session, win);
2452 public void removeWindowLocked(Session session, WindowState win) {
2453 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2454 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win);
2457 if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v(
2458 TAG, "Remove " + win + " client="
2459 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder()))
2460 + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers="
2461 + Debug.getCallers(4));
2463 final long origId = Binder.clearCallingIdentity();
2465 win.disposeInputChannel();
2467 if (DEBUG_APP_TRANSITIONS) Slog.v(
2468 TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl
2469 + " mExiting=" + win.mExiting
2470 + " isAnimating=" + win.mWinAnimator.isAnimating()
2472 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
2473 + " inPendingTransaction="
2474 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
2475 + " mDisplayFrozen=" + mDisplayFrozen);
2476 // Visibility of the removed window. Will be used later to update orientation later on.
2477 boolean wasVisible = false;
2478 // First, see if we need to run an animation. If we do, we have
2479 // to hold off on removing the window until the animation is done.
2480 // If the display is frozen, just remove immediately, since the
2481 // animation wouldn't be seen.
2482 if (win.mHasSurface && okToDisplay()) {
2483 // If we are not currently running the exit animation, we
2484 // need to see about starting one.
2485 wasVisible = win.isWinVisibleLw();
2488 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2489 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2490 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2492 // Try starting an animation.
2493 if (win.mWinAnimator.applyAnimationLocked(transit, false)) {
2494 win.mExiting = true;
2496 //TODO (multidisplay): Magnification is supported only for the default display.
2497 if (mAccessibilityController != null
2498 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
2499 mAccessibilityController.onWindowTransitionLocked(win, transit);
2502 if (win.mExiting || win.mWinAnimator.isAnimating()) {
2503 // The exit animation is running... wait for it!
2504 //Slog.i(TAG, "*** Running exit animation...");
2505 win.mExiting = true;
2506 win.mRemoveOnExit = true;
2507 final DisplayContent displayContent = win.getDisplayContent();
2508 if (displayContent != null) {
2509 displayContent.layoutNeeded = true;
2511 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
2512 false /*updateInputWindows*/);
2513 performLayoutAndPlaceSurfacesLocked();
2514 if (win.mAppToken != null) {
2515 win.mAppToken.updateReportedVisibilityLocked();
2518 Binder.restoreCallingIdentity(origId);
2523 removeWindowInnerLocked(session, win);
2524 // Removing a visible window will effect the computed orientation
2525 // So just update orientation if needed.
2526 if (wasVisible && updateOrientationFromAppTokensLocked(false)) {
2527 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
2529 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
2530 Binder.restoreCallingIdentity(origId);
2533 void removeWindowInnerLocked(Session session, WindowState win) {
2539 for (int i=win.mChildWindows.size()-1; i>=0; i--) {
2540 WindowState cwin = win.mChildWindows.get(i);
2541 Slog.w(TAG, "Force-removing child win " + cwin + " from container "
2543 removeWindowInnerLocked(cwin.mSession, cwin);
2546 win.mRemoved = true;
2548 if (mInputMethodTarget == win) {
2549 moveInputMethodWindowsIfNeededLocked(false);
2553 RuntimeException e = new RuntimeException("here");
2554 e.fillInStackTrace();
2555 Slog.w(TAG, "Removing window " + win, e);
2558 mPolicy.removeWindowLw(win);
2561 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win);
2562 mWindowMap.remove(win.mClient.asBinder());
2563 if (win.mAppOp != AppOpsManager.OP_NONE) {
2564 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
2567 mPendingRemove.remove(win);
2568 mResizingWindows.remove(win);
2569 mWindowsChanged = true;
2570 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
2572 if (mInputMethodWindow == win) {
2573 mInputMethodWindow = null;
2574 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2575 mInputMethodDialogs.remove(win);
2578 final WindowToken token = win.mToken;
2579 final AppWindowToken atoken = win.mAppToken;
2580 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token);
2581 token.windows.remove(win);
2582 if (atoken != null) {
2583 atoken.allAppWindows.remove(win);
2585 if (localLOGV) Slog.v(
2586 TAG, "**** Removing window " + win + ": count="
2587 + token.windows.size());
2588 if (token.windows.size() == 0) {
2589 if (!token.explicit) {
2590 mTokenMap.remove(token.token);
2591 } else if (atoken != null) {
2592 atoken.firstWindowDrawn = false;
2596 if (atoken != null) {
2597 if (atoken.startingWindow == win) {
2598 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling startingWindow " + win);
2599 atoken.startingWindow = null;
2600 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2601 // If this is the last window and we had requested a starting
2602 // transition window, well there is no point now.
2603 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling last startingWindow");
2604 atoken.startingData = null;
2605 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2606 // If this is the last window except for a starting transition
2607 // window, we need to get rid of the starting transition.
2608 scheduleRemoveStartingWindow(atoken);
2612 if (win.mAttrs.type == TYPE_WALLPAPER) {
2613 mLastWallpaperTimeoutTime = 0;
2614 getDefaultDisplayContentLocked().pendingLayoutChanges |=
2615 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2616 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2617 getDefaultDisplayContentLocked().pendingLayoutChanges |=
2618 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2621 final WindowList windows = win.getWindowList();
2622 if (windows != null) {
2623 windows.remove(win);
2625 assignLayersLocked(windows);
2626 final DisplayContent displayContent = win.getDisplayContent();
2627 if (displayContent != null) {
2628 displayContent.layoutNeeded = true;
2630 performLayoutAndPlaceSurfacesLocked();
2631 if (win.mAppToken != null) {
2632 win.mAppToken.updateReportedVisibilityLocked();
2637 mInputMonitor.updateInputWindowsLw(true /*force*/);
2640 public void updateAppOpsState() {
2641 synchronized(mWindowMap) {
2642 final int numDisplays = mDisplayContents.size();
2643 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
2644 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
2645 final int numWindows = windows.size();
2646 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
2647 final WindowState win = windows.get(winNdx);
2648 if (win.mAppOp != AppOpsManager.OP_NONE) {
2649 final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
2650 win.getOwningPackage());
2651 win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED);
2658 static void logSurface(WindowState w, String msg, RuntimeException where) {
2659 String str = " SURFACE " + msg + ": " + w;
2660 if (where != null) {
2661 Slog.i(TAG, str, where);
2667 static void logSurface(SurfaceControl s, String title, String msg, RuntimeException where) {
2668 String str = " SURFACE " + s + ": " + msg + " / " + title;
2669 if (where != null) {
2670 Slog.i(TAG, str, where);
2676 void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2677 long origId = Binder.clearCallingIdentity();
2679 synchronized (mWindowMap) {
2680 WindowState w = windowForClientLocked(session, client, false);
2681 if ((w != null) && w.mHasSurface) {
2682 w.mWinAnimator.setTransparentRegionHintLocked(region);
2686 Binder.restoreCallingIdentity(origId);
2690 void setInsetsWindow(Session session, IWindow client,
2691 int touchableInsets, Rect contentInsets,
2692 Rect visibleInsets, Region touchableRegion) {
2693 long origId = Binder.clearCallingIdentity();
2695 synchronized (mWindowMap) {
2696 WindowState w = windowForClientLocked(session, client, false);
2698 w.mGivenInsetsPending = false;
2699 w.mGivenContentInsets.set(contentInsets);
2700 w.mGivenVisibleInsets.set(visibleInsets);
2701 w.mGivenTouchableRegion.set(touchableRegion);
2702 w.mTouchableInsets = touchableInsets;
2703 if (w.mGlobalScale != 1) {
2704 w.mGivenContentInsets.scale(w.mGlobalScale);
2705 w.mGivenVisibleInsets.scale(w.mGlobalScale);
2706 w.mGivenTouchableRegion.scale(w.mGlobalScale);
2708 final DisplayContent displayContent = w.getDisplayContent();
2709 if (displayContent != null) {
2710 displayContent.layoutNeeded = true;
2712 performLayoutAndPlaceSurfacesLocked();
2716 Binder.restoreCallingIdentity(origId);
2720 public void getWindowDisplayFrame(Session session, IWindow client,
2721 Rect outDisplayFrame) {
2722 synchronized(mWindowMap) {
2723 WindowState win = windowForClientLocked(session, client, false);
2725 outDisplayFrame.setEmpty();
2728 outDisplayFrame.set(win.mDisplayFrame);
2732 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
2733 float xStep, float yStep) {
2734 if (window.mWallpaperX != x || window.mWallpaperY != y) {
2735 window.mWallpaperX = x;
2736 window.mWallpaperY = y;
2737 window.mWallpaperXStep = xStep;
2738 window.mWallpaperYStep = yStep;
2739 updateWallpaperOffsetLocked(window, true);
2743 void wallpaperCommandComplete(IBinder window, Bundle result) {
2744 synchronized (mWindowMap) {
2745 if (mWaitingOnWallpaper != null &&
2746 mWaitingOnWallpaper.mClient.asBinder() == window) {
2747 mWaitingOnWallpaper = null;
2748 mWindowMap.notifyAll();
2753 public Bundle sendWindowWallpaperCommandLocked(WindowState window,
2754 String action, int x, int y, int z, Bundle extras, boolean sync) {
2755 if (window == mWallpaperTarget || window == mLowerWallpaperTarget
2756 || window == mUpperWallpaperTarget) {
2757 boolean doWait = sync;
2758 int curTokenIndex = mWallpaperTokens.size();
2759 while (curTokenIndex > 0) {
2761 WindowToken token = mWallpaperTokens.get(curTokenIndex);
2762 int curWallpaperIndex = token.windows.size();
2763 while (curWallpaperIndex > 0) {
2764 curWallpaperIndex--;
2765 WindowState wallpaper = token.windows.get(curWallpaperIndex);
2767 wallpaper.mClient.dispatchWallpaperCommand(action,
2768 x, y, z, extras, sync);
2769 // We only want to be synchronous with one wallpaper.
2771 } catch (RemoteException e) {
2777 // XXX Need to wait for result.
2784 public void setUniverseTransformLocked(WindowState window, float alpha,
2785 float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) {
2786 Transformation transform = window.mWinAnimator.mUniverseTransform;
2787 transform.setAlpha(alpha);
2788 Matrix matrix = transform.getMatrix();
2789 matrix.getValues(mTmpFloats);
2790 mTmpFloats[Matrix.MTRANS_X] = offx;
2791 mTmpFloats[Matrix.MTRANS_Y] = offy;
2792 mTmpFloats[Matrix.MSCALE_X] = dsdx;
2793 mTmpFloats[Matrix.MSKEW_Y] = dtdx;
2794 mTmpFloats[Matrix.MSKEW_X] = dsdy;
2795 mTmpFloats[Matrix.MSCALE_Y] = dtdy;
2796 matrix.setValues(mTmpFloats);
2797 final DisplayContent displayContent = window.getDisplayContent();
2798 if (displayContent == null) {
2802 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2803 final RectF dispRect = new RectF(0, 0,
2804 displayInfo.logicalWidth, displayInfo.logicalHeight);
2805 matrix.mapRect(dispRect);
2806 window.mGivenTouchableRegion.set(0, 0,
2807 displayInfo.logicalWidth, displayInfo.logicalHeight);
2808 window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top,
2809 (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE);
2810 window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
2811 displayContent.layoutNeeded = true;
2812 performLayoutAndPlaceSurfacesLocked();
2815 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
2816 synchronized (mWindowMap) {
2817 if (mAccessibilityController != null) {
2818 WindowState window = mWindowMap.get(token);
2819 //TODO (multidisplay): Magnification is supported only for the default display.
2820 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
2821 mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle);
2827 public IWindowId getWindowId(IBinder token) {
2828 synchronized (mWindowMap) {
2829 WindowState window = mWindowMap.get(token);
2830 return window != null ? window.mWindowId : null;
2834 public int relayoutWindow(Session session, IWindow client, int seq,
2835 WindowManager.LayoutParams attrs, int requestedWidth,
2836 int requestedHeight, int viewVisibility, int flags,
2837 Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
2838 Rect outVisibleInsets, Rect outStableInsets, Configuration outConfig,
2839 Surface outSurface) {
2840 boolean toBeDisplayed = false;
2841 boolean inTouchMode;
2842 boolean configChanged;
2843 boolean surfaceChanged = false;
2845 boolean hasStatusBarPermission =
2846 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
2847 == PackageManager.PERMISSION_GRANTED;
2849 long origId = Binder.clearCallingIdentity();
2851 synchronized(mWindowMap) {
2852 WindowState win = windowForClientLocked(session, client, false);
2856 WindowStateAnimator winAnimator = win.mWinAnimator;
2857 if (win.mRequestedWidth != requestedWidth
2858 || win.mRequestedHeight != requestedHeight) {
2859 win.mLayoutNeeded = true;
2860 win.mRequestedWidth = requestedWidth;
2861 win.mRequestedHeight = requestedHeight;
2864 if (attrs != null) {
2865 mPolicy.adjustWindowParamsLw(attrs);
2868 // if they don't have the permission, mask out the status bar bits
2869 int systemUiVisibility = 0;
2870 if (attrs != null) {
2871 systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility);
2872 if ((systemUiVisibility & StatusBarManager.DISABLE_MASK) != 0) {
2873 if (!hasStatusBarPermission) {
2874 systemUiVisibility &= ~StatusBarManager.DISABLE_MASK;
2879 if (attrs != null && seq == win.mSeq) {
2880 win.mSystemUiVisibility = systemUiVisibility;
2883 winAnimator.mSurfaceDestroyDeferred =
2884 (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
2886 int attrChanges = 0;
2887 int flagChanges = 0;
2888 if (attrs != null) {
2889 if (win.mAttrs.type != attrs.type) {
2890 throw new IllegalArgumentException(
2891 "Window type can not be changed after the window is added.");
2893 flagChanges = win.mAttrs.flags ^= attrs.flags;
2894 attrChanges = win.mAttrs.copyFrom(attrs);
2895 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
2896 | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
2897 win.mLayoutNeeded = true;
2901 if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
2902 + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
2904 win.mEnforceSizeCompat =
2905 (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
2907 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2908 winAnimator.mAlpha = attrs.alpha;
2911 final boolean scaledWindow =
2912 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
2915 // requested{Width|Height} Surface's physical size
2916 // attrs.{width|height} Size on screen
2917 win.mHScale = (attrs.width != requestedWidth) ?
2918 (attrs.width / (float)requestedWidth) : 1.0f;
2919 win.mVScale = (attrs.height != requestedHeight) ?
2920 (attrs.height / (float)requestedHeight) : 1.0f;
2922 win.mHScale = win.mVScale = 1;
2925 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
2927 final boolean isDefaultDisplay = win.isDefaultDisplay();
2928 boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
2929 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
2930 || (!win.mRelayoutCalled));
2932 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2933 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
2934 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
2936 win.mRelayoutCalled = true;
2937 final int oldVisibility = win.mViewVisibility;
2938 win.mViewVisibility = viewVisibility;
2939 if (DEBUG_SCREEN_ON) {
2940 RuntimeException stack = new RuntimeException();
2941 stack.fillInStackTrace();
2942 Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility
2943 + " newVis=" + viewVisibility, stack);
2945 if (viewVisibility == View.VISIBLE &&
2946 (win.mAppToken == null || !win.mAppToken.clientHidden)) {
2947 toBeDisplayed = !win.isVisibleLw();
2949 winAnimator.cancelExitAnimationForNextAnimationLocked();
2950 win.mExiting = false;
2952 if (win.mDestroying) {
2953 win.mDestroying = false;
2954 mDestroySurface.remove(win);
2956 if (oldVisibility == View.GONE) {
2957 winAnimator.mEnterAnimationPending = true;
2959 if (toBeDisplayed) {
2960 if (win.isDrawnLw() && okToDisplay()) {
2961 winAnimator.applyEnterAnimationLocked();
2963 if ((win.mAttrs.flags
2964 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
2965 if (DEBUG_VISIBILITY) Slog.v(TAG,
2966 "Relayout window turning screen on: " + win);
2967 win.mTurnOnScreen = true;
2969 if (win.isConfigChanged()) {
2970 if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win
2971 + " visible with new config: " + mCurConfiguration);
2972 outConfig.setTo(mCurConfiguration);
2975 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
2976 // To change the format, we need to re-build the surface.
2977 winAnimator.destroySurfaceLocked();
2978 toBeDisplayed = true;
2979 surfaceChanged = true;
2982 if (!win.mHasSurface) {
2983 surfaceChanged = true;
2985 SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
2986 if (surfaceControl != null) {
2987 outSurface.copyFrom(surfaceControl);
2988 if (SHOW_TRANSACTIONS) Slog.i(TAG,
2989 " OUT SURFACE " + outSurface + ": copied");
2991 // For some reason there isn't a surface. Clear the
2992 // caller's object so they see the same state.
2993 outSurface.release();
2995 } catch (Exception e) {
2996 mInputMonitor.updateInputWindowsLw(true /*force*/);
2998 Slog.w(TAG, "Exception thrown when creating surface for client "
2999 + client + " (" + win.mAttrs.getTitle() + ")",
3001 Binder.restoreCallingIdentity(origId);
3004 if (toBeDisplayed) {
3005 focusMayChange = isDefaultDisplay;
3007 if (win.mAttrs.type == TYPE_INPUT_METHOD
3008 && mInputMethodWindow == null) {
3009 mInputMethodWindow = win;
3012 if (win.mAttrs.type == TYPE_BASE_APPLICATION
3013 && win.mAppToken != null
3014 && win.mAppToken.startingWindow != null) {
3015 // Special handling of starting window over the base
3016 // window of the app: propagate lock screen flags to it,
3017 // to provide the correct semantics while starting.
3019 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
3020 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
3021 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
3022 WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
3023 sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
3026 winAnimator.mEnterAnimationPending = false;
3027 if (winAnimator.mSurfaceControl != null) {
3028 if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
3029 + ": mExiting=" + win.mExiting);
3030 // If we are not currently running the exit animation, we
3031 // need to see about starting one.
3032 if (!win.mExiting) {
3033 surfaceChanged = true;
3034 // Try starting an animation; if there isn't one, we
3035 // can destroy the surface right away.
3036 int transit = WindowManagerPolicy.TRANSIT_EXIT;
3037 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
3038 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
3040 if (win.isWinVisibleLw() &&
3041 winAnimator.applyAnimationLocked(transit, false)) {
3042 focusMayChange = isDefaultDisplay;
3043 win.mExiting = true;
3044 } else if (win.mWinAnimator.isAnimating()) {
3045 // Currently in a hide animation... turn this into
3047 win.mExiting = true;
3048 } else if (win == mWallpaperTarget) {
3049 // If the wallpaper is currently behind this
3050 // window, we need to change both of them inside
3051 // of a transaction to avoid artifacts.
3052 win.mExiting = true;
3053 win.mWinAnimator.mAnimating = true;
3055 if (mInputMethodWindow == win) {
3056 mInputMethodWindow = null;
3058 winAnimator.destroySurfaceLocked();
3060 //TODO (multidisplay): Magnification is supported only for the default
3061 if (mAccessibilityController != null
3062 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
3063 mAccessibilityController.onWindowTransitionLocked(win, transit);
3068 outSurface.release();
3069 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
3072 if (focusMayChange) {
3073 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
3074 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
3075 false /*updateInputWindows*/)) {
3078 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
3081 // updateFocusedWindowLocked() already assigned layers so we only need to
3082 // reassign them at this point if the IM window state gets shuffled
3083 if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) {
3084 // Little hack here -- we -should- be able to rely on the
3085 // function to return true if the IME has moved and needs
3086 // its layer recomputed. However, if the IME was hidden
3087 // and isn't actually moved in the list, its layer may be
3088 // out of data so we make sure to recompute it.
3089 assignLayersLocked(win.getWindowList());
3092 if (wallpaperMayMove) {
3093 getDefaultDisplayContentLocked().pendingLayoutChanges |=
3094 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
3097 final DisplayContent displayContent = win.getDisplayContent();
3098 if (displayContent != null) {
3099 displayContent.layoutNeeded = true;
3101 win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
3102 configChanged = updateOrientationFromAppTokensLocked(false);
3103 performLayoutAndPlaceSurfacesLocked();
3104 if (toBeDisplayed && win.mIsWallpaper) {
3105 DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
3106 updateWallpaperOffsetLocked(win,
3107 displayInfo.logicalWidth, displayInfo.logicalHeight, false);
3109 if (win.mAppToken != null) {
3110 win.mAppToken.updateReportedVisibilityLocked();
3112 outFrame.set(win.mCompatFrame);
3113 outOverscanInsets.set(win.mOverscanInsets);
3114 outContentInsets.set(win.mContentInsets);
3115 outVisibleInsets.set(win.mVisibleInsets);
3116 outStableInsets.set(win.mStableInsets);
3117 if (localLOGV) Slog.v(
3118 TAG, "Relayout given client " + client.asBinder()
3119 + ", requestedWidth=" + requestedWidth
3120 + ", requestedHeight=" + requestedHeight
3121 + ", viewVisibility=" + viewVisibility
3122 + "\nRelayout returning frame=" + outFrame
3123 + ", surface=" + outSurface);
3125 if (localLOGV || DEBUG_FOCUS) Slog.v(
3126 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
3128 inTouchMode = mInTouchMode;
3129 animating = mAnimator.mAnimating && win.mWinAnimator.isAnimating();
3130 if (animating && !mRelayoutWhileAnimating.contains(win)) {
3131 mRelayoutWhileAnimating.add(win);
3134 mInputMonitor.updateInputWindowsLw(true /*force*/);
3137 Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
3141 if (configChanged) {
3142 sendNewConfiguration();
3145 Binder.restoreCallingIdentity(origId);
3147 return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0)
3148 | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0)
3149 | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0)
3150 | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0);
3153 public void performDeferredDestroyWindow(Session session, IWindow client) {
3154 long origId = Binder.clearCallingIdentity();
3157 synchronized (mWindowMap) {
3158 WindowState win = windowForClientLocked(session, client, false);
3162 win.mWinAnimator.destroyDeferredSurfaceLocked();
3165 Binder.restoreCallingIdentity(origId);
3169 public boolean outOfMemoryWindow(Session session, IWindow client) {
3170 long origId = Binder.clearCallingIdentity();
3173 synchronized (mWindowMap) {
3174 WindowState win = windowForClientLocked(session, client, false);
3178 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false);
3181 Binder.restoreCallingIdentity(origId);
3185 public void finishDrawingWindow(Session session, IWindow client) {
3186 final long origId = Binder.clearCallingIdentity();
3188 synchronized (mWindowMap) {
3189 WindowState win = windowForClientLocked(session, client, false);
3190 if (win != null && win.mWinAnimator.finishDrawingLocked()) {
3191 if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
3192 getDefaultDisplayContentLocked().pendingLayoutChanges |=
3193 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
3195 final DisplayContent displayContent = win.getDisplayContent();
3196 if (displayContent != null) {
3197 displayContent.layoutNeeded = true;
3199 requestTraversalLocked();
3203 Binder.restoreCallingIdentity(origId);
3207 private boolean applyAnimationLocked(AppWindowToken atoken,
3208 WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) {
3209 // Only apply an animation if the display isn't frozen. If it is
3210 // frozen, there is no reason to animate and it can cause strange
3211 // artifacts when we unfreeze the display if some different animation
3213 if (okToDisplay()) {
3214 DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
3215 final int width = displayInfo.appWidth;
3216 final int height = displayInfo.appHeight;
3217 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken="
3220 // Determine the visible rect to calculate the thumbnail clip
3221 WindowState win = atoken.findMainWindow();
3222 Rect containingFrame = new Rect(0, 0, width, height);
3223 Rect contentInsets = new Rect();
3224 boolean isFullScreen = true;
3226 if (win.mContainingFrame != null) {
3227 containingFrame.set(win.mContainingFrame);
3229 if (win.mContentInsets != null) {
3230 contentInsets.set(win.mContentInsets);
3233 ((win.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) ==
3234 SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN);
3237 if (atoken.mLaunchTaskBehind) {
3238 // Differentiate the two animations. This one which is briefly on the screen
3239 // gets the !enter animation, and the other activity which remains on the
3240 // screen gets the enter animation. Both appear in the mOpeningApps set.
3243 Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height,
3244 mCurConfiguration.orientation, containingFrame, contentInsets, isFullScreen,
3245 isVoiceInteraction);
3248 RuntimeException e = null;
3249 if (!HIDE_STACK_CRAWLS) {
3250 e = new RuntimeException();
3251 e.fillInStackTrace();
3253 Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e);
3255 atoken.mAppAnimator.setAnimation(a, width, height);
3258 atoken.mAppAnimator.clearAnimation();
3261 return atoken.mAppAnimator.animation != null;
3264 // -------------------------------------------------------------
3265 // Application Window Tokens
3266 // -------------------------------------------------------------
3268 public void validateAppTokens(int stackId, List<TaskGroup> tasks) {
3269 synchronized (mWindowMap) {
3270 int t = tasks.size() - 1;
3272 Slog.w(TAG, "validateAppTokens: empty task list");
3276 TaskGroup task = tasks.get(0);
3277 int taskId = task.taskId;
3278 Task targetTask = mTaskIdToTask.get(taskId);
3279 DisplayContent displayContent = targetTask.getDisplayContent();
3280 if (displayContent == null) {
3281 Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId);
3285 final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks();
3287 for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) {
3288 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens;
3289 task = tasks.get(t);
3290 List<IApplicationToken> tokens = task.tokens;
3292 DisplayContent lastDisplayContent = displayContent;
3293 displayContent = mTaskIdToTask.get(taskId).getDisplayContent();
3294 if (displayContent != lastDisplayContent) {
3295 Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!");
3301 for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1;
3302 tokenNdx >= 0 && v >= 0; ) {
3303 final AppWindowToken atoken = localTokens.get(tokenNdx);
3304 if (atoken.removed) {
3308 if (tokens.get(v) != atoken.token) {
3315 if (tokenNdx >= 0 || v >= 0) {
3320 if (taskNdx >= 0 || t >= 0) {
3321 Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks);
3322 Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + localTasks);
3323 Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4));
3328 public void validateStackOrder(Integer[] remoteStackIds) {
3332 boolean checkCallingPermission(String permission, String func) {
3333 // Quick check: if the calling permission is me, it's all okay.
3334 if (Binder.getCallingPid() == Process.myPid()) {
3338 if (mContext.checkCallingPermission(permission)
3339 == PackageManager.PERMISSION_GRANTED) {
3342 String msg = "Permission Denial: " + func + " from pid="
3343 + Binder.getCallingPid()
3344 + ", uid=" + Binder.getCallingUid()
3345 + " requires " + permission;
3350 boolean okToDisplay() {
3351 return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully();
3354 AppWindowToken findAppWindowToken(IBinder token) {
3355 WindowToken wtoken = mTokenMap.get(token);
3356 if (wtoken == null) {
3359 return wtoken.appWindowToken;
3363 public void addWindowToken(IBinder token, int type) {
3364 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3365 "addWindowToken()")) {
3366 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3369 synchronized(mWindowMap) {
3370 WindowToken wtoken = mTokenMap.get(token);
3371 if (wtoken != null) {
3372 Slog.w(TAG, "Attempted to add existing input method token: " + token);
3375 wtoken = new WindowToken(this, token, type, true);
3376 mTokenMap.put(token, wtoken);
3377 if (type == TYPE_WALLPAPER) {
3378 mWallpaperTokens.add(wtoken);
3384 public void removeWindowToken(IBinder token) {
3385 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3386 "removeWindowToken()")) {
3387 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3390 final long origId = Binder.clearCallingIdentity();
3391 synchronized(mWindowMap) {
3392 DisplayContent displayContent = null;
3393 WindowToken wtoken = mTokenMap.remove(token);
3394 if (wtoken != null) {
3395 boolean delayed = false;
3396 if (!wtoken.hidden) {
3397 final int N = wtoken.windows.size();
3398 boolean changed = false;
3400 for (int i=0; i<N; i++) {
3401 WindowState win = wtoken.windows.get(i);
3402 displayContent = win.getDisplayContent();
3404 if (win.mWinAnimator.isAnimating()) {
3408 if (win.isVisibleNow()) {
3409 win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
3411 //TODO (multidisplay): Magnification is supported only for the default
3412 if (mAccessibilityController != null && win.isDefaultDisplay()) {
3413 mAccessibilityController.onWindowTransitionLocked(win,
3414 WindowManagerPolicy.TRANSIT_EXIT);
3417 if (displayContent != null) {
3418 displayContent.layoutNeeded = true;
3423 wtoken.hidden = true;
3426 performLayoutAndPlaceSurfacesLocked();
3427 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
3428 false /*updateInputWindows*/);
3432 if (displayContent != null) {
3433 displayContent.mExitingTokens.add(wtoken);
3435 } else if (wtoken.windowType == TYPE_WALLPAPER) {
3436 mWallpaperTokens.remove(wtoken);
3440 mInputMonitor.updateInputWindowsLw(true /*force*/);
3442 Slog.w(TAG, "Attempted to remove non-existing token: " + token);
3445 Binder.restoreCallingIdentity(origId);
3448 private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) {
3449 if (DEBUG_STACK) Slog.i(TAG, "createTask: taskId=" + taskId + " stackId=" + stackId
3450 + " atoken=" + atoken);
3451 final TaskStack stack = mStackIdToStack.get(stackId);
3452 if (stack == null) {
3453 throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
3455 EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
3456 Task task = new Task(atoken, stack, userId);
3457 mTaskIdToTask.put(taskId, task);
3458 stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */);
3463 public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
3464 int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
3465 int configChanges, boolean voiceInteraction, boolean launchTaskBehind) {
3466 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3468 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3471 // Get the dispatching timeout here while we are not holding any locks so that it
3472 // can be cached by the AppWindowToken. The timeout value is used later by the
3473 // input dispatcher in code that does hold locks. If we did not cache the value
3474 // here we would run the chance of introducing a deadlock between the window manager
3475 // (which holds locks while updating the input dispatcher state) and the activity manager
3476 // (which holds locks while querying the application token).
3477 long inputDispatchingTimeoutNanos;
3479 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
3480 } catch (RemoteException ex) {
3481 Slog.w(TAG, "Could not get dispatching timeout.", ex);
3482 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
3485 synchronized(mWindowMap) {
3486 AppWindowToken atoken = findAppWindowToken(token.asBinder());
3487 if (atoken != null) {
3488 Slog.w(TAG, "Attempted to add existing app token: " + token);
3491 atoken = new AppWindowToken(this, token, voiceInteraction);
3492 atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
3493 atoken.groupId = taskId;
3494 atoken.appFullscreen = fullscreen;
3495 atoken.showWhenLocked = showWhenLocked;
3496 atoken.requestedOrientation = requestedOrientation;
3497 atoken.layoutConfigChanges = (configChanges &
3498 (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
3499 atoken.mLaunchTaskBehind = launchTaskBehind;
3500 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
3501 + " to stack=" + stackId + " task=" + taskId + " at " + addPos);
3503 Task task = mTaskIdToTask.get(taskId);
3505 createTask(taskId, stackId, userId, atoken);
3507 task.addAppToken(addPos, atoken);
3510 mTokenMap.put(token.asBinder(), atoken);
3512 // Application tokens start out hidden.
3513 atoken.hidden = true;
3514 atoken.hiddenRequested = true;
3521 public void setAppGroupId(IBinder token, int groupId) {
3522 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3523 "setAppGroupId()")) {
3524 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3527 synchronized(mWindowMap) {
3528 final AppWindowToken atoken = findAppWindowToken(token);
3529 if (atoken == null) {
3530 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
3533 final Task oldTask = mTaskIdToTask.get(atoken.groupId);
3534 removeAppFromTaskLocked(atoken);
3536 atoken.groupId = groupId;
3537 Task newTask = mTaskIdToTask.get(groupId);
3538 if (newTask == null) {
3539 newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken);
3541 newTask.mAppTokens.add(atoken);
3546 public int getOrientationFromWindowsLocked() {
3547 if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
3548 // If the display is frozen, some activities may be in the middle
3549 // of restarting, and thus have removed their old window. If the
3550 // window has the flag to hide the lock screen, then the lock screen
3551 // can re-appear and inflict its own orientation on us. Keep the
3552 // orientation stable until this all settles down.
3553 return mLastWindowForcedOrientation;
3556 // TODO(multidisplay): Change to the correct display.
3557 final WindowList windows = getDefaultWindowListLocked();
3558 int pos = windows.size() - 1;
3560 WindowState win = windows.get(pos);
3562 if (win.mAppToken != null) {
3563 // We hit an application window. so the orientation will be determined by the
3564 // app window. No point in continuing further.
3565 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3567 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
3570 int req = win.mAttrs.screenOrientation;
3571 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
3572 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
3576 if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req);
3577 return (mLastWindowForcedOrientation=req);
3579 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3582 public int getOrientationFromAppTokensLocked() {
3583 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3584 boolean findingBehind = false;
3585 boolean lastFullscreen = false;
3586 // TODO: Multi window.
3587 DisplayContent displayContent = getDefaultDisplayContentLocked();
3588 final ArrayList<Task> tasks = displayContent.getTasks();
3589 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
3590 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
3591 final int firstToken = tokens.size() - 1;
3592 for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) {
3593 final AppWindowToken atoken = tokens.get(tokenNdx);
3595 if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
3597 // if we're about to tear down this window and not seek for
3598 // the behind activity, don't use it for orientation
3600 && (!atoken.hidden && atoken.hiddenRequested)) {
3601 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
3602 + " -- going to hide");
3606 if (tokenNdx == firstToken) {
3607 // If we have hit a new Task, and the bottom
3608 // of the previous group didn't explicitly say to use
3609 // the orientation behind it, and the last app was
3610 // full screen, then we'll stick with the
3611 // user's orientation.
3612 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
3613 && lastFullscreen) {
3614 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3615 + " -- end of group, return " + lastOrientation);
3616 return lastOrientation;
3620 // We ignore any hidden applications on the top.
3621 if (atoken.hiddenRequested || atoken.willBeHidden) {
3622 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
3623 + " -- hidden on top");
3627 if (tokenNdx == 0) {
3628 // Last token in this task.
3629 lastOrientation = atoken.requestedOrientation;
3632 int or = atoken.requestedOrientation;
3633 // If this application is fullscreen, and didn't explicitly say
3634 // to use the orientation behind it, then just take whatever
3635 // orientation it has and ignores whatever is under it.
3636 lastFullscreen = atoken.appFullscreen;
3638 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3639 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3640 + " -- full screen, return " + or);
3643 // If this application has requested an explicit orientation,
3645 if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
3646 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3647 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3648 + " -- explicitly set, return " + or);
3651 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
3654 if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation");
3655 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3659 public Configuration updateOrientationFromAppTokens(
3660 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3661 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3662 "updateOrientationFromAppTokens()")) {
3663 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3666 Configuration config = null;
3667 long ident = Binder.clearCallingIdentity();
3669 synchronized(mWindowMap) {
3670 config = updateOrientationFromAppTokensLocked(currentConfig,
3671 freezeThisOneIfNeeded);
3674 Binder.restoreCallingIdentity(ident);
3678 private Configuration updateOrientationFromAppTokensLocked(
3679 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3680 Configuration config = null;
3682 if (updateOrientationFromAppTokensLocked(false)) {
3683 if (freezeThisOneIfNeeded != null) {
3684 AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
3685 if (atoken != null) {
3686 startAppFreezingScreenLocked(atoken);
3689 config = computeNewConfigurationLocked();
3691 } else if (currentConfig != null) {
3692 // No obvious action we need to take, but if our current
3693 // state mismatches the activity manager's, update it,
3694 // disregarding font scale, which should remain set to
3695 // the value of the previous configuration.
3696 mTempConfiguration.setToDefaults();
3697 mTempConfiguration.fontScale = currentConfig.fontScale;
3698 if (computeScreenConfigurationLocked(mTempConfiguration)) {
3699 if (currentConfig.diff(mTempConfiguration) != 0) {
3700 mWaitingForConfig = true;
3701 final DisplayContent displayContent = getDefaultDisplayContentLocked();
3702 displayContent.layoutNeeded = true;
3703 int anim[] = new int[2];
3704 if (displayContent.isDimming()) {
3705 anim[0] = anim[1] = 0;
3707 mPolicy.selectRotationAnimationLw(anim);
3709 startFreezingDisplayLocked(false, anim[0], anim[1]);
3710 config = new Configuration(mTempConfiguration);
3719 * Determine the new desired orientation of the display, returning
3720 * a non-null new Configuration if it has changed from the current
3721 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL
3722 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3723 * SCREEN. This will typically be done for you if you call
3724 * sendNewConfiguration().
3726 * The orientation is computed from non-application windows first. If none of
3727 * the non-application windows specify orientation, the orientation is computed from
3728 * application tokens.
3729 * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3730 * android.os.IBinder)
3732 boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
3733 long ident = Binder.clearCallingIdentity();
3735 int req = getOrientationFromWindowsLocked();
3736 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
3737 req = getOrientationFromAppTokensLocked();
3740 if (req != mForcedAppOrientation) {
3741 mForcedAppOrientation = req;
3742 //send a message to Policy indicating orientation change to take
3743 //action like disabling/enabling sensors etc.,
3744 mPolicy.setCurrentOrientationLw(req);
3745 if (updateRotationUncheckedLocked(inTransaction)) {
3753 Binder.restoreCallingIdentity(ident);
3758 public void setNewConfiguration(Configuration config) {
3759 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3760 "setNewConfiguration()")) {
3761 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3764 synchronized(mWindowMap) {
3765 mCurConfiguration = new Configuration(config);
3766 if (mWaitingForConfig) {
3767 mWaitingForConfig = false;
3768 mLastFinishedFreezeSource = "new-config";
3770 performLayoutAndPlaceSurfacesLocked();
3775 public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3776 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3777 "setAppOrientation()")) {
3778 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3781 synchronized(mWindowMap) {
3782 AppWindowToken atoken = findAppWindowToken(token.asBinder());
3783 if (atoken == null) {
3784 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
3788 atoken.requestedOrientation = requestedOrientation;
3793 public int getAppOrientation(IApplicationToken token) {
3794 synchronized(mWindowMap) {
3795 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3796 if (wtoken == null) {
3797 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3800 return wtoken.requestedOrientation;
3804 /** Call while in a Surface transaction. */
3805 void setFocusedStackLayer() {
3806 mFocusedStackLayer = 0;
3807 if (mFocusedApp != null) {
3808 final WindowList windows = mFocusedApp.allAppWindows;
3809 for (int i = windows.size() - 1; i >= 0; --i) {
3810 final WindowState win = windows.get(i);
3811 final int animLayer = win.mWinAnimator.mAnimLayer;
3812 if (win.mAttachedWindow == null && win.isVisibleLw() &&
3813 animLayer > mFocusedStackLayer) {
3814 mFocusedStackLayer = animLayer + LAYER_OFFSET_FOCUSED_STACK;
3818 if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedStackFrame to layer=" +
3819 mFocusedStackLayer);
3820 mFocusedStackFrame.setLayer(mFocusedStackLayer);
3823 void setFocusedStackFrame() {
3824 final TaskStack stack;
3825 if (mFocusedApp != null) {
3826 Task task = mTaskIdToTask.get(mFocusedApp.groupId);
3827 stack = task.mStack;
3828 final DisplayContent displayContent = task.getDisplayContent();
3829 if (displayContent != null) {
3830 displayContent.setTouchExcludeRegion(stack);
3835 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame");
3836 SurfaceControl.openTransaction();
3838 if (stack == null) {
3839 mFocusedStackFrame.setVisibility(false);
3841 mFocusedStackFrame.setBounds(stack);
3842 final boolean multipleStacks = !stack.isFullscreen();
3843 mFocusedStackFrame.setVisibility(multipleStacks);
3846 SurfaceControl.closeTransaction();
3847 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame");
3852 public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3853 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3854 "setFocusedApp()")) {
3855 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3858 synchronized(mWindowMap) {
3859 final AppWindowToken newFocus;
3860 if (token == null) {
3861 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
3864 newFocus = findAppWindowToken(token);
3865 if (newFocus == null) {
3866 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
3868 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus
3869 + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
3872 final boolean changed = mFocusedApp != newFocus;
3874 mFocusedApp = newFocus;
3875 mInputMonitor.setFocusedAppLw(null);
3878 if (moveFocusNow && changed) {
3879 final long origId = Binder.clearCallingIdentity();
3880 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
3881 Binder.restoreCallingIdentity(origId);
3887 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
3888 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3889 "prepareAppTransition()")) {
3890 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3893 synchronized(mWindowMap) {
3894 if (DEBUG_APP_TRANSITIONS) Slog.v(
3895 TAG, "Prepare app transition: transit=" + transit
3896 + " " + mAppTransition
3897 + " alwaysKeepCurrent=" + alwaysKeepCurrent
3898 + " Callers=" + Debug.getCallers(3));
3899 if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) {
3900 mAppTransition.setAppTransition(transit);
3901 } else if (!alwaysKeepCurrent) {
3902 if (transit == AppTransition.TRANSIT_TASK_OPEN
3903 && mAppTransition.isTransitionEqual(
3904 AppTransition.TRANSIT_TASK_CLOSE)) {
3905 // Opening a new task always supersedes a close for the anim.
3906 mAppTransition.setAppTransition(transit);
3907 } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN
3908 && mAppTransition.isTransitionEqual(
3909 AppTransition.TRANSIT_ACTIVITY_CLOSE)) {
3910 // Opening a new activity always supersedes a close for the anim.
3911 mAppTransition.setAppTransition(transit);
3914 if (okToDisplay()) {
3915 mAppTransition.prepare();
3916 mStartingIconInTransition = false;
3917 mSkipAppTransitionAnimation = false;
3918 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
3919 mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000);
3925 public int getPendingAppTransition() {
3926 return mAppTransition.getAppTransition();
3930 public void overridePendingAppTransition(String packageName,
3931 int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
3932 synchronized(mWindowMap) {
3933 mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,
3939 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
3941 synchronized(mWindowMap) {
3942 mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth,
3948 public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
3949 int startY, IRemoteCallback startedCallback, boolean scaleUp) {
3950 synchronized(mWindowMap) {
3951 mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
3952 startedCallback, scaleUp);
3957 public void executeAppTransition() {
3958 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3959 "executeAppTransition()")) {
3960 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3963 synchronized(mWindowMap) {
3964 if (DEBUG_APP_TRANSITIONS) Slog.w(TAG, "Execute app transition: " + mAppTransition,
3965 new RuntimeException("here").fillInStackTrace());
3966 if (mAppTransition.isTransitionSet()) {
3967 mAppTransition.setReady();
3968 final long origId = Binder.clearCallingIdentity();
3970 performLayoutAndPlaceSurfacesLocked();
3972 Binder.restoreCallingIdentity(origId);
3979 public void setAppStartingWindow(IBinder token, String pkg,
3980 int theme, CompatibilityInfo compatInfo,
3981 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
3982 int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
3983 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3984 "setAppStartingWindow()")) {
3985 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3988 synchronized(mWindowMap) {
3989 if (DEBUG_STARTING_WINDOW) Slog.v(
3990 TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg
3991 + " transferFrom=" + transferFrom);
3993 AppWindowToken wtoken = findAppWindowToken(token);
3994 if (wtoken == null) {
3995 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
3999 // If the display is frozen, we won't do anything until the
4000 // actual window is displayed so there is no reason to put in
4001 // the starting window.
4002 if (!okToDisplay()) {
4006 if (wtoken.startingData != null) {
4010 if (transferFrom != null) {
4011 AppWindowToken ttoken = findAppWindowToken(transferFrom);
4012 if (ttoken != null) {
4013 WindowState startingWindow = ttoken.startingWindow;
4014 if (startingWindow != null) {
4015 if (mStartingIconInTransition) {
4016 // In this case, the starting icon has already
4017 // been displayed, so start letting windows get
4018 // shown immediately without any more transitions.
4019 mSkipAppTransitionAnimation = true;
4021 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
4022 "Moving existing starting " + startingWindow + " from " + ttoken
4024 final long origId = Binder.clearCallingIdentity();
4026 // Transfer the starting window over to the new
4028 wtoken.startingData = ttoken.startingData;
4029 wtoken.startingView = ttoken.startingView;
4030 wtoken.startingDisplayed = ttoken.startingDisplayed;
4031 ttoken.startingDisplayed = false;
4032 wtoken.startingWindow = startingWindow;
4033 wtoken.reportedVisible = ttoken.reportedVisible;
4034 ttoken.startingData = null;
4035 ttoken.startingView = null;
4036 ttoken.startingWindow = null;
4037 ttoken.startingMoved = true;
4038 startingWindow.mToken = wtoken;
4039 startingWindow.mRootToken = wtoken;
4040 startingWindow.mAppToken = wtoken;
4041 startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator;
4043 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
4044 Slog.v(TAG, "Removing starting window: " + startingWindow);
4046 startingWindow.getWindowList().remove(startingWindow);
4047 mWindowsChanged = true;
4048 if (DEBUG_ADD_REMOVE) Slog.v(TAG,
4049 "Removing starting " + startingWindow + " from " + ttoken);
4050 ttoken.windows.remove(startingWindow);
4051 ttoken.allAppWindows.remove(startingWindow);
4052 addWindowToListInOrderLocked(startingWindow, true);
4054 // Propagate other interesting state between the
4055 // tokens. If the old token is displayed, we should
4056 // immediately force the new one to be displayed. If
4057 // it is animating, we need to move that animation to
4059 if (ttoken.allDrawn) {
4060 wtoken.allDrawn = true;
4061 wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn;
4063 if (ttoken.firstWindowDrawn) {
4064 wtoken.firstWindowDrawn = true;
4066 if (!ttoken.hidden) {
4067 wtoken.hidden = false;
4068 wtoken.hiddenRequested = false;
4069 wtoken.willBeHidden = false;
4071 if (wtoken.clientHidden != ttoken.clientHidden) {
4072 wtoken.clientHidden = ttoken.clientHidden;
4073 wtoken.sendAppVisibilityToClients();
4075 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4076 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4077 if (tAppAnimator.animation != null) {
4078 wAppAnimator.animation = tAppAnimator.animation;
4079 wAppAnimator.animating = tAppAnimator.animating;
4080 wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment;
4081 tAppAnimator.animation = null;
4082 tAppAnimator.animLayerAdjustment = 0;
4083 wAppAnimator.updateLayers();
4084 tAppAnimator.updateLayers();
4087 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4088 true /*updateInputWindows*/);
4089 getDefaultDisplayContentLocked().layoutNeeded = true;
4090 performLayoutAndPlaceSurfacesLocked();
4091 Binder.restoreCallingIdentity(origId);
4093 } else if (ttoken.startingData != null) {
4094 // The previous app was getting ready to show a
4095 // starting window, but hasn't yet done so. Steal it!
4096 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
4097 "Moving pending starting from " + ttoken
4099 wtoken.startingData = ttoken.startingData;
4100 ttoken.startingData = null;
4101 ttoken.startingMoved = true;
4102 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4103 // Note: we really want to do sendMessageAtFrontOfQueue() because we
4104 // want to process the message ASAP, before any other queued
4106 mH.sendMessageAtFrontOfQueue(m);
4109 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4110 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4111 if (tAppAnimator.thumbnail != null) {
4112 // The old token is animating with a thumbnail, transfer
4113 // that to the new token.
4114 if (wAppAnimator.thumbnail != null) {
4115 wAppAnimator.thumbnail.destroy();
4117 wAppAnimator.thumbnail = tAppAnimator.thumbnail;
4118 wAppAnimator.thumbnailX = tAppAnimator.thumbnailX;
4119 wAppAnimator.thumbnailY = tAppAnimator.thumbnailY;
4120 wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
4121 wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
4122 tAppAnimator.thumbnail = null;
4127 // There is no existing starting window, and the caller doesn't
4128 // want us to create one, so that's it!
4129 if (!createIfNeeded) {
4133 // If this is a translucent window, then don't
4134 // show a starting window -- the current effect (a full-screen
4135 // opaque starting window that fades away to the real contents
4136 // when it is ready) does not work for this.
4137 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x"
4138 + Integer.toHexString(theme));
4140 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
4141 com.android.internal.R.styleable.Window, mCurrentUserId);
4143 // Whoops! App doesn't exist. Um. Okay. We'll just
4144 // pretend like we didn't see that.
4147 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent="
4148 + ent.array.getBoolean(
4149 com.android.internal.R.styleable.Window_windowIsTranslucent, false)
4151 + ent.array.getBoolean(
4152 com.android.internal.R.styleable.Window_windowIsFloating, false)
4154 + ent.array.getBoolean(
4155 com.android.internal.R.styleable.Window_windowShowWallpaper, false));
4156 if (ent.array.getBoolean(
4157 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
4160 if (ent.array.getBoolean(
4161 com.android.internal.R.styleable.Window_windowIsFloating, false)) {
4164 if (ent.array.getBoolean(
4165 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
4166 if (mWallpaperTarget == null) {
4167 // If this theme is requesting a wallpaper, and the wallpaper
4168 // is not curently visible, then this effectively serves as
4169 // an opaque window and our starting window transition animation
4170 // can still work. We just need to make sure the starting window
4171 // is also showing the wallpaper.
4172 windowFlags |= FLAG_SHOW_WALLPAPER;
4179 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData");
4180 mStartingIconInTransition = true;
4181 wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
4182 labelRes, icon, logo, windowFlags);
4183 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4184 // Note: we really want to do sendMessageAtFrontOfQueue() because we
4185 // want to process the message ASAP, before any other queued
4187 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
4188 mH.sendMessageAtFrontOfQueue(m);
4192 public void removeAppStartingWindow(IBinder token) {
4193 synchronized (mWindowMap) {
4194 AppWindowToken wtoken = mTokenMap.get(token).appWindowToken;
4195 if (wtoken.startingWindow != null) {
4196 scheduleRemoveStartingWindow(wtoken);
4202 public void setAppWillBeHidden(IBinder token) {
4203 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4204 "setAppWillBeHidden()")) {
4205 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4208 AppWindowToken wtoken;
4210 synchronized(mWindowMap) {
4211 wtoken = findAppWindowToken(token);
4212 if (wtoken == null) {
4213 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
4216 wtoken.willBeHidden = true;
4220 public void setAppFullscreen(IBinder token, boolean toOpaque) {
4221 AppWindowToken atoken = findAppWindowToken(token);
4222 if (atoken != null) {
4223 atoken.appFullscreen = toOpaque;
4224 // When making translucent, wait until windows below have been drawn.
4226 // Making opaque so do it now.
4227 setWindowOpaque(token, true);
4233 public void setWindowOpaque(IBinder token, boolean isOpaque) {
4234 AppWindowToken wtoken = findAppWindowToken(token);
4235 if (wtoken != null) {
4236 WindowState win = wtoken.findMainWindow();
4238 win.mWinAnimator.setOpaque(isOpaque);
4243 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
4244 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
4245 boolean delayed = false;
4247 if (wtoken.clientHidden == visible) {
4248 wtoken.clientHidden = !visible;
4249 wtoken.sendAppVisibilityToClients();
4252 wtoken.willBeHidden = false;
4253 if (wtoken.hidden == visible) {
4254 boolean changed = false;
4255 if (DEBUG_APP_TRANSITIONS) Slog.v(
4256 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
4257 + " performLayout=" + performLayout);
4259 boolean runningAppAnimation = false;
4261 if (transit != AppTransition.TRANSIT_UNSET) {
4262 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
4263 wtoken.mAppAnimator.animation = null;
4265 if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) {
4266 delayed = runningAppAnimation = true;
4268 WindowState window = wtoken.findMainWindow();
4269 //TODO (multidisplay): Magnification is supported only for the default display.
4270 if (window != null && mAccessibilityController != null
4271 && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
4272 mAccessibilityController.onAppWindowTransitionLocked(window, transit);
4277 final int N = wtoken.allAppWindows.size();
4278 for (int i=0; i<N; i++) {
4279 WindowState win = wtoken.allAppWindows.get(i);
4280 if (win == wtoken.startingWindow) {
4284 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
4287 if (!win.isVisibleNow()) {
4288 if (!runningAppAnimation) {
4289 win.mWinAnimator.applyAnimationLocked(
4290 WindowManagerPolicy.TRANSIT_ENTER, true);
4291 //TODO (multidisplay): Magnification is supported only for the default
4292 if (mAccessibilityController != null
4293 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4294 mAccessibilityController.onWindowTransitionLocked(win,
4295 WindowManagerPolicy.TRANSIT_ENTER);
4299 final DisplayContent displayContent = win.getDisplayContent();
4300 if (displayContent != null) {
4301 displayContent.layoutNeeded = true;
4304 } else if (win.isVisibleNow()) {
4305 if (!runningAppAnimation) {
4306 win.mWinAnimator.applyAnimationLocked(
4307 WindowManagerPolicy.TRANSIT_EXIT, false);
4308 //TODO (multidisplay): Magnification is supported only for the default
4309 if (mAccessibilityController != null
4310 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4311 mAccessibilityController.onWindowTransitionLocked(win,
4312 WindowManagerPolicy.TRANSIT_EXIT);
4316 final DisplayContent displayContent = win.getDisplayContent();
4317 if (displayContent != null) {
4318 displayContent.layoutNeeded = true;
4323 wtoken.hidden = wtoken.hiddenRequested = !visible;
4325 unsetAppFreezingScreenLocked(wtoken, true, true);
4327 // If we are being set visible, and the starting window is
4328 // not yet displayed, then make sure it doesn't get displayed.
4329 WindowState swin = wtoken.startingWindow;
4330 if (swin != null && !swin.isDrawnLw()) {
4331 swin.mPolicyVisibility = false;
4332 swin.mPolicyVisibilityAfterAnim = false;
4336 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
4337 + ": hidden=" + wtoken.hidden + " hiddenRequested="
4338 + wtoken.hiddenRequested);
4341 mInputMonitor.setUpdateInputWindowsNeededLw();
4342 if (performLayout) {
4343 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4344 false /*updateInputWindows*/);
4345 performLayoutAndPlaceSurfacesLocked();
4347 mInputMonitor.updateInputWindowsLw(false /*force*/);
4351 if (wtoken.mAppAnimator.animation != null) {
4355 for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
4356 if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) {
4365 public void setAppVisibility(IBinder token, boolean visible) {
4366 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4367 "setAppVisibility()")) {
4368 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4371 AppWindowToken wtoken;
4373 synchronized(mWindowMap) {
4374 wtoken = findAppWindowToken(token);
4375 if (wtoken == null) {
4376 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
4380 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG, "setAppVisibility(" +
4381 token + ", visible=" + visible + "): " + mAppTransition +
4382 " hidden=" + wtoken.hidden + " hiddenRequested=" +
4383 wtoken.hiddenRequested, HIDE_STACK_CRAWLS ?
4384 null : new RuntimeException("here").fillInStackTrace());
4386 // If we are preparing an app transition, then delay changing
4387 // the visibility of this token until we execute that transition.
4388 if (okToDisplay() && mAppTransition.isTransitionSet()) {
4389 wtoken.hiddenRequested = !visible;
4391 if (!wtoken.startingDisplayed) {
4392 if (DEBUG_APP_TRANSITIONS) Slog.v(
4393 TAG, "Setting dummy animation on: " + wtoken);
4394 wtoken.mAppAnimator.setDummyAnimation();
4396 mOpeningApps.remove(wtoken);
4397 mClosingApps.remove(wtoken);
4398 wtoken.waitingToShow = wtoken.waitingToHide = false;
4399 wtoken.inPendingTransaction = true;
4401 mOpeningApps.add(wtoken);
4402 wtoken.startingMoved = false;
4404 // If the token is currently hidden (should be the
4405 // common case), then we need to set up to wait for
4406 // its windows to be ready.
4407 if (wtoken.hidden) {
4408 wtoken.allDrawn = false;
4409 wtoken.deferClearAllDrawn = false;
4410 wtoken.waitingToShow = true;
4412 if (wtoken.clientHidden) {
4413 // In the case where we are making an app visible
4414 // but holding off for a transition, we still need
4415 // to tell the client to make its windows visible so
4416 // they get drawn. Otherwise, we will wait on
4417 // performing the transition until all windows have
4418 // been drawn, they never will be, and we are sad.
4419 wtoken.clientHidden = false;
4420 wtoken.sendAppVisibilityToClients();
4424 mClosingApps.add(wtoken);
4426 // If the token is currently visible (should be the
4427 // common case), then set up to wait for it to be hidden.
4428 if (!wtoken.hidden) {
4429 wtoken.waitingToHide = true;
4432 if (mAppTransition.getAppTransition() == AppTransition.TRANSIT_TASK_OPEN_BEHIND) {
4433 // We're launchingBehind, add the launching activity to mOpeningApps.
4434 final WindowState win =
4435 findFocusedWindowLocked(getDefaultDisplayContentLocked());
4437 final AppWindowToken focusedToken = win.mAppToken;
4438 if (focusedToken != null) {
4439 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "TRANSIT_TASK_OPEN_BEHIND, " +
4440 " adding " + focusedToken + " to mOpeningApps");
4441 // Force animation to be loaded.
4442 focusedToken.hidden = true;
4443 mOpeningApps.add(focusedToken);
4450 final long origId = Binder.clearCallingIdentity();
4451 setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
4452 true, wtoken.voiceInteraction);
4453 wtoken.updateReportedVisibilityLocked();
4454 Binder.restoreCallingIdentity(origId);
4458 void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
4459 boolean unfreezeSurfaceNow, boolean force) {
4460 if (wtoken.mAppAnimator.freezingScreen) {
4461 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
4462 + " force=" + force);
4463 final int N = wtoken.allAppWindows.size();
4464 boolean unfrozeWindows = false;
4465 for (int i=0; i<N; i++) {
4466 WindowState w = wtoken.allAppWindows.get(i);
4467 if (w.mAppFreezing) {
4468 w.mAppFreezing = false;
4469 if (w.mHasSurface && !w.mOrientationChanging) {
4470 if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w);
4471 w.mOrientationChanging = true;
4472 mInnerFields.mOrientationChangeComplete = false;
4474 w.mLastFreezeDuration = 0;
4475 unfrozeWindows = true;
4476 final DisplayContent displayContent = w.getDisplayContent();
4477 if (displayContent != null) {
4478 displayContent.layoutNeeded = true;
4482 if (force || unfrozeWindows) {
4483 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
4484 wtoken.mAppAnimator.freezingScreen = false;
4485 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime()
4486 - mDisplayFreezeTime);
4487 mAppsFreezingScreen--;
4488 mLastFinishedFreezeSource = wtoken;
4490 if (unfreezeSurfaceNow) {
4491 if (unfrozeWindows) {
4492 performLayoutAndPlaceSurfacesLocked();
4494 stopFreezingDisplayLocked();
4499 private void startAppFreezingScreenLocked(AppWindowToken wtoken) {
4500 if (DEBUG_ORIENTATION) {
4501 RuntimeException e = null;
4502 if (!HIDE_STACK_CRAWLS) {
4503 e = new RuntimeException();
4504 e.fillInStackTrace();
4506 Slog.i(TAG, "Set freezing of " + wtoken.appToken
4507 + ": hidden=" + wtoken.hidden + " freezing="
4508 + wtoken.mAppAnimator.freezingScreen, e);
4510 if (!wtoken.hiddenRequested) {
4511 if (!wtoken.mAppAnimator.freezingScreen) {
4512 wtoken.mAppAnimator.freezingScreen = true;
4513 wtoken.mAppAnimator.lastFreezeDuration = 0;
4514 mAppsFreezingScreen++;
4515 if (mAppsFreezingScreen == 1) {
4516 startFreezingDisplayLocked(false, 0, 0);
4517 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
4518 mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000);
4521 final int N = wtoken.allAppWindows.size();
4522 for (int i=0; i<N; i++) {
4523 WindowState w = wtoken.allAppWindows.get(i);
4524 w.mAppFreezing = true;
4530 public void startAppFreezingScreen(IBinder token, int configChanges) {
4531 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4532 "setAppFreezingScreen()")) {
4533 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4536 synchronized(mWindowMap) {
4537 if (configChanges == 0 && okToDisplay()) {
4538 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
4542 AppWindowToken wtoken = findAppWindowToken(token);
4543 if (wtoken == null || wtoken.appToken == null) {
4544 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
4547 final long origId = Binder.clearCallingIdentity();
4548 startAppFreezingScreenLocked(wtoken);
4549 Binder.restoreCallingIdentity(origId);
4554 public void stopAppFreezingScreen(IBinder token, boolean force) {
4555 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4556 "setAppFreezingScreen()")) {
4557 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4560 synchronized(mWindowMap) {
4561 AppWindowToken wtoken = findAppWindowToken(token);
4562 if (wtoken == null || wtoken.appToken == null) {
4565 final long origId = Binder.clearCallingIdentity();
4566 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
4567 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
4568 unsetAppFreezingScreenLocked(wtoken, true, force);
4569 Binder.restoreCallingIdentity(origId);
4573 void removeAppFromTaskLocked(AppWindowToken wtoken) {
4574 final Task task = mTaskIdToTask.get(wtoken.groupId);
4576 if (!task.removeAppToken(wtoken)) {
4577 Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found.");
4583 public void removeAppToken(IBinder token) {
4584 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4585 "removeAppToken()")) {
4586 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4589 AppWindowToken wtoken = null;
4590 AppWindowToken startingToken = null;
4591 boolean delayed = false;
4593 final long origId = Binder.clearCallingIdentity();
4594 synchronized(mWindowMap) {
4595 WindowToken basewtoken = mTokenMap.remove(token);
4596 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
4597 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
4598 delayed = setTokenVisibilityLocked(wtoken, null, false,
4599 AppTransition.TRANSIT_UNSET, true, wtoken.voiceInteraction);
4600 wtoken.inPendingTransaction = false;
4601 mOpeningApps.remove(wtoken);
4602 wtoken.waitingToShow = false;
4603 if (mClosingApps.contains(wtoken)) {
4605 } else if (mAppTransition.isTransitionSet()) {
4606 mClosingApps.add(wtoken);
4607 wtoken.waitingToHide = true;
4610 if (DEBUG_APP_TRANSITIONS) Slog.v(
4611 TAG, "Removing app " + wtoken + " delayed=" + delayed
4612 + " animation=" + wtoken.mAppAnimator.animation
4613 + " animating=" + wtoken.mAppAnimator.animating);
4614 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: "
4615 + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
4616 final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack;
4618 // set the token aside because it has an active animation to be finished
4619 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
4620 "removeAppToken make exiting: " + wtoken);
4621 stack.mExitingAppTokens.add(wtoken);
4622 wtoken.mDeferRemoval = true;
4624 // Make sure there is no animation running on this token,
4625 // so any windows associated with it will be removed as
4626 // soon as their animations are complete
4627 wtoken.mAppAnimator.clearAnimation();
4628 wtoken.mAppAnimator.animating = false;
4629 removeAppFromTaskLocked(wtoken);
4632 wtoken.removed = true;
4633 if (wtoken.startingData != null) {
4634 startingToken = wtoken;
4636 unsetAppFreezingScreenLocked(wtoken, true, true);
4637 if (mFocusedApp == wtoken) {
4638 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken);
4640 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
4641 mInputMonitor.setFocusedAppLw(null);
4644 Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
4647 if (!delayed && wtoken != null) {
4648 wtoken.updateReportedVisibilityLocked();
4651 Binder.restoreCallingIdentity(origId);
4653 // Will only remove if startingToken non null.
4654 scheduleRemoveStartingWindow(startingToken);
4657 void scheduleRemoveStartingWindow(AppWindowToken wtoken) {
4658 if (wtoken != null && wtoken.startingWindow != null) {
4659 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
4660 ": Schedule remove starting " + wtoken + (wtoken != null ?
4661 " startingWindow=" + wtoken.startingWindow : ""));
4662 Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
4667 private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
4668 WindowList windows = token.windows;
4669 final int NW = windows.size();
4671 mWindowsChanged = true;
4673 for (int i = 0; i < NW; i++) {
4674 WindowState win = windows.get(i);
4675 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
4676 win.getWindowList().remove(win);
4677 int j = win.mChildWindows.size();
4680 WindowState cwin = win.mChildWindows.get(j);
4681 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
4682 "Tmp removing child window " + cwin);
4683 cwin.getWindowList().remove(cwin);
4689 void dumpAppTokensLocked() {
4690 final int numStacks = mStackIdToStack.size();
4691 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
4692 final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
4693 Slog.v(TAG, " Stack #" + stack.mStackId + " tasks from bottom to top:");
4694 final ArrayList<Task> tasks = stack.getTasks();
4695 final int numTasks = tasks.size();
4696 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4697 final Task task = tasks.get(taskNdx);
4698 Slog.v(TAG, " Task #" + task.taskId + " activities from bottom to top:");
4699 AppTokenList tokens = task.mAppTokens;
4700 final int numTokens = tokens.size();
4701 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4702 Slog.v(TAG, " activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token);
4708 void dumpWindowsLocked() {
4709 final int numDisplays = mDisplayContents.size();
4710 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4711 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
4712 Slog.v(TAG, " Display #" + displayContent.getDisplayId());
4713 final WindowList windows = displayContent.getWindowList();
4714 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
4715 Slog.v(TAG, " #" + winNdx + ": " + windows.get(winNdx));
4720 private int findAppWindowInsertionPointLocked(AppWindowToken target) {
4721 final int taskId = target.groupId;
4722 Task targetTask = mTaskIdToTask.get(taskId);
4723 if (targetTask == null) {
4724 Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId="
4728 DisplayContent displayContent = targetTask.getDisplayContent();
4729 if (displayContent == null) {
4730 Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target);
4733 final WindowList windows = displayContent.getWindowList();
4734 final int NW = windows.size();
4736 boolean found = false;
4737 final ArrayList<Task> tasks = displayContent.getTasks();
4738 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
4739 final Task task = tasks.get(taskNdx);
4740 if (!found && task.taskId != taskId) {
4743 AppTokenList tokens = task.mAppTokens;
4744 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
4745 final AppWindowToken wtoken = tokens.get(tokenNdx);
4746 if (!found && wtoken == target) {
4750 // Find the first app token below the new position that has
4751 // a window displayed.
4752 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token);
4753 if (wtoken.sendingToBottom) {
4754 if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom");
4757 for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
4758 WindowState win = wtoken.windows.get(i);
4759 for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
4760 WindowState cwin = win.mChildWindows.get(j);
4761 if (cwin.mSubLayer >= 0) {
4762 for (int pos = NW - 1; pos >= 0; pos--) {
4763 if (windows.get(pos) == cwin) {
4764 if (DEBUG_REORDER) Slog.v(TAG,
4765 "Found child win @" + (pos + 1));
4771 for (int pos = NW - 1; pos >= 0; pos--) {
4772 if (windows.get(pos) == win) {
4773 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1));
4781 // Never put an app window underneath wallpaper.
4782 for (int pos = NW - 1; pos >= 0; pos--) {
4783 if (windows.get(pos).mIsWallpaper) {
4784 if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos);
4791 private final int reAddWindowLocked(int index, WindowState win) {
4792 final WindowList windows = win.getWindowList();
4793 final int NCW = win.mChildWindows.size();
4794 boolean added = false;
4795 for (int j=0; j<NCW; j++) {
4796 WindowState cwin = win.mChildWindows.get(j);
4797 if (!added && cwin.mSubLayer >= 0) {
4798 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
4799 + index + ": " + cwin);
4800 win.mRebuilding = false;
4801 windows.add(index, win);
4805 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4806 + index + ": " + cwin);
4807 cwin.mRebuilding = false;
4808 windows.add(index, cwin);
4812 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4813 + index + ": " + win);
4814 win.mRebuilding = false;
4815 windows.add(index, win);
4818 mWindowsChanged = true;
4822 private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index,
4823 WindowToken token) {
4824 final int NW = token.windows.size();
4825 for (int i=0; i<NW; i++) {
4826 final WindowState win = token.windows.get(i);
4827 final DisplayContent winDisplayContent = win.getDisplayContent();
4828 if (winDisplayContent == displayContent || winDisplayContent == null) {
4829 win.mDisplayContent = displayContent;
4830 index = reAddWindowLocked(index, win);
4836 void tmpRemoveTaskWindowsLocked(Task task) {
4837 AppTokenList tokens = task.mAppTokens;
4838 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
4839 tmpRemoveAppWindowsLocked(tokens.get(tokenNdx));
4843 void moveStackWindowsLocked(DisplayContent displayContent) {
4844 // First remove all of the windows from the list.
4845 final ArrayList<Task> tasks = displayContent.getTasks();
4846 final int numTasks = tasks.size();
4847 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4848 tmpRemoveTaskWindowsLocked(tasks.get(taskNdx));
4851 // And now add them back at the correct place.
4852 // Where to start adding?
4853 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4854 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
4855 final int numTokens = tokens.size();
4856 if (numTokens == 0) {
4859 int pos = findAppWindowInsertionPointLocked(tokens.get(0));
4860 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4861 final AppWindowToken wtoken = tokens.get(tokenNdx);
4862 if (wtoken != null) {
4863 final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
4864 if (newPos != pos) {
4865 displayContent.layoutNeeded = true;
4872 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4873 false /*updateInputWindows*/)) {
4874 assignLayersLocked(displayContent.getWindowList());
4877 mInputMonitor.setUpdateInputWindowsNeededLw();
4878 performLayoutAndPlaceSurfacesLocked();
4879 mInputMonitor.updateInputWindowsLw(false /*force*/);
4884 public void moveTaskToTop(int taskId) {
4885 final long origId = Binder.clearCallingIdentity();
4887 synchronized(mWindowMap) {
4888 Task task = mTaskIdToTask.get(taskId);
4890 // Normal behavior, addAppToken will be called next and task will be created.
4893 final TaskStack stack = task.mStack;
4894 final DisplayContent displayContent = task.getDisplayContent();
4895 displayContent.moveStack(stack, true);
4896 if (displayContent.isDefaultDisplay) {
4897 final TaskStack homeStack = displayContent.getHomeStack();
4898 if (homeStack != stack) {
4899 // When a non-home stack moves to the top, the home stack moves to the
4901 displayContent.moveStack(homeStack, false);
4904 stack.moveTaskToTop(task);
4907 Binder.restoreCallingIdentity(origId);
4911 public void moveTaskToBottom(int taskId) {
4912 final long origId = Binder.clearCallingIdentity();
4914 synchronized(mWindowMap) {
4915 Task task = mTaskIdToTask.get(taskId);
4917 Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId
4918 + " not found in mTaskIdToTask");
4921 final TaskStack stack = task.mStack;
4922 stack.moveTaskToBottom(task);
4923 moveStackWindowsLocked(stack.getDisplayContent());
4926 Binder.restoreCallingIdentity(origId);
4931 * Create a new TaskStack and place it on a DisplayContent.
4932 * @param stackId The unique identifier of the new stack.
4933 * @param displayId The unique identifier of the DisplayContent.
4935 public void attachStack(int stackId, int displayId) {
4936 final long origId = Binder.clearCallingIdentity();
4938 synchronized (mWindowMap) {
4939 final DisplayContent displayContent = mDisplayContents.get(displayId);
4940 if (displayContent != null) {
4941 TaskStack stack = mStackIdToStack.get(stackId);
4942 if (stack == null) {
4943 if (DEBUG_STACK) Slog.d(TAG, "attachStack: stackId=" + stackId);
4944 stack = new TaskStack(this, stackId);
4945 mStackIdToStack.put(stackId, stack);
4947 stack.attachDisplayContent(displayContent);
4948 displayContent.attachStack(stack);
4949 moveStackWindowsLocked(displayContent);
4950 final WindowList windows = displayContent.getWindowList();
4951 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
4952 windows.get(winNdx).reportResized();
4957 Binder.restoreCallingIdentity(origId);
4961 void detachStackLocked(DisplayContent displayContent, TaskStack stack) {
4962 displayContent.detachStack(stack);
4963 stack.detachDisplay();
4966 public void detachStack(int stackId) {
4967 synchronized (mWindowMap) {
4968 TaskStack stack = mStackIdToStack.get(stackId);
4969 if (stack != null) {
4970 final DisplayContent displayContent = stack.getDisplayContent();
4971 if (displayContent != null) {
4972 if (stack.isAnimating()) {
4973 stack.mDeferDetach = true;
4976 detachStackLocked(displayContent, stack);
4982 public void removeStack(int stackId) {
4983 mStackIdToStack.remove(stackId);
4986 void removeTaskLocked(Task task) {
4987 final int taskId = task.taskId;
4988 final TaskStack stack = task.mStack;
4989 if (stack.isAnimating()) {
4990 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId);
4991 task.mDeferRemoval = true;
4994 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId);
4995 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask");
4996 task.mDeferRemoval = false;
4997 task.mStack.removeTask(task);
4998 mTaskIdToTask.delete(task.taskId);
5001 public void removeTask(int taskId) {
5002 synchronized (mWindowMap) {
5003 Task task = mTaskIdToTask.get(taskId);
5005 if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId);
5008 removeTaskLocked(task);
5012 public void addTask(int taskId, int stackId, boolean toTop) {
5013 synchronized (mWindowMap) {
5014 if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId
5015 + " to " + (toTop ? "top" : "bottom"));
5016 Task task = mTaskIdToTask.get(taskId);
5020 TaskStack stack = mStackIdToStack.get(stackId);
5021 stack.addTask(task, toTop);
5022 final DisplayContent displayContent = stack.getDisplayContent();
5023 displayContent.layoutNeeded = true;
5024 performLayoutAndPlaceSurfacesLocked();
5028 public void resizeStack(int stackId, Rect bounds) {
5029 synchronized (mWindowMap) {
5030 final TaskStack stack = mStackIdToStack.get(stackId);
5031 if (stack == null) {
5032 throw new IllegalArgumentException("resizeStack: stackId " + stackId
5035 if (stack.setBounds(bounds)) {
5036 stack.resizeWindows();
5037 stack.getDisplayContent().layoutNeeded = true;
5038 performLayoutAndPlaceSurfacesLocked();
5043 public void getStackBounds(int stackId, Rect bounds) {
5044 final TaskStack stack = mStackIdToStack.get(stackId);
5045 if (stack != null) {
5046 stack.getBounds(bounds);
5052 // -------------------------------------------------------------
5053 // Misc IWindowSession methods
5054 // -------------------------------------------------------------
5057 public void startFreezingScreen(int exitAnim, int enterAnim) {
5058 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5059 "startFreezingScreen()")) {
5060 throw new SecurityException("Requires FREEZE_SCREEN permission");
5063 synchronized(mWindowMap) {
5064 if (!mClientFreezingScreen) {
5065 mClientFreezingScreen = true;
5066 final long origId = Binder.clearCallingIdentity();
5068 startFreezingDisplayLocked(false, exitAnim, enterAnim);
5069 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
5070 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
5072 Binder.restoreCallingIdentity(origId);
5079 public void stopFreezingScreen() {
5080 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5081 "stopFreezingScreen()")) {
5082 throw new SecurityException("Requires FREEZE_SCREEN permission");
5085 synchronized(mWindowMap) {
5086 if (mClientFreezingScreen) {
5087 mClientFreezingScreen = false;
5088 mLastFinishedFreezeSource = "client";
5089 final long origId = Binder.clearCallingIdentity();
5091 stopFreezingDisplayLocked();
5093 Binder.restoreCallingIdentity(origId);
5100 public void disableKeyguard(IBinder token, String tag) {
5101 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5102 != PackageManager.PERMISSION_GRANTED) {
5103 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5106 if (token == null) {
5107 throw new IllegalArgumentException("token == null");
5110 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5111 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
5115 public void reenableKeyguard(IBinder token) {
5116 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5117 != PackageManager.PERMISSION_GRANTED) {
5118 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5121 if (token == null) {
5122 throw new IllegalArgumentException("token == null");
5125 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5126 KeyguardDisableHandler.KEYGUARD_REENABLE, token));
5130 * @see android.app.KeyguardManager#exitKeyguardSecurely
5133 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
5134 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5135 != PackageManager.PERMISSION_GRANTED) {
5136 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5139 if (callback == null) {
5140 throw new IllegalArgumentException("callback == null");
5143 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
5145 public void onKeyguardExitResult(boolean success) {
5147 callback.onKeyguardExitResult(success);
5148 } catch (RemoteException e) {
5149 // Client has died, we don't care.
5156 public boolean inKeyguardRestrictedInputMode() {
5157 return mPolicy.inKeyguardRestrictedKeyInputMode();
5161 public boolean isKeyguardLocked() {
5162 return mPolicy.isKeyguardLocked();
5166 public boolean isKeyguardSecure() {
5167 return mPolicy.isKeyguardSecure();
5171 public void dismissKeyguard() {
5172 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5173 != PackageManager.PERMISSION_GRANTED) {
5174 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5176 synchronized(mWindowMap) {
5177 mPolicy.dismissKeyguardLw();
5182 public void keyguardGoingAway() {
5183 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5184 != PackageManager.PERMISSION_GRANTED) {
5185 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5187 synchronized (mWindowMap) {
5188 mAnimator.mKeyguardGoingAway = true;
5189 requestTraversalLocked();
5193 void showGlobalActions() {
5194 mPolicy.showGlobalActions();
5198 public void closeSystemDialogs(String reason) {
5199 synchronized(mWindowMap) {
5200 final int numDisplays = mDisplayContents.size();
5201 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5202 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5203 final int numWindows = windows.size();
5204 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5205 final WindowState w = windows.get(winNdx);
5206 if (w.mHasSurface) {
5208 w.mClient.closeSystemDialogs(reason);
5209 } catch (RemoteException e) {
5217 static float fixScale(float scale) {
5218 if (scale < 0) scale = 0;
5219 else if (scale > 20) scale = 20;
5220 return Math.abs(scale);
5224 public void setAnimationScale(int which, float scale) {
5225 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5226 "setAnimationScale()")) {
5227 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5230 scale = fixScale(scale);
5232 case 0: mWindowAnimationScaleSetting = scale; break;
5233 case 1: mTransitionAnimationScaleSetting = scale; break;
5234 case 2: mAnimatorDurationScaleSetting = scale; break;
5238 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5242 public void setAnimationScales(float[] scales) {
5243 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5244 "setAnimationScale()")) {
5245 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5248 if (scales != null) {
5249 if (scales.length >= 1) {
5250 mWindowAnimationScaleSetting = fixScale(scales[0]);
5252 if (scales.length >= 2) {
5253 mTransitionAnimationScaleSetting = fixScale(scales[1]);
5255 if (scales.length >= 3) {
5256 mAnimatorDurationScaleSetting = fixScale(scales[2]);
5257 dispatchNewAnimatorScaleLocked(null);
5262 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5265 private void setAnimatorDurationScale(float scale) {
5266 mAnimatorDurationScaleSetting = scale;
5267 ValueAnimator.setDurationScale(scale);
5270 public float getWindowAnimationScaleLocked() {
5271 return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting;
5274 public float getTransitionAnimationScaleLocked() {
5275 return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting;
5279 public float getAnimationScale(int which) {
5281 case 0: return mWindowAnimationScaleSetting;
5282 case 1: return mTransitionAnimationScaleSetting;
5283 case 2: return mAnimatorDurationScaleSetting;
5289 public float[] getAnimationScales() {
5290 return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting,
5291 mAnimatorDurationScaleSetting };
5295 public float getCurrentAnimatorScale() {
5296 synchronized(mWindowMap) {
5297 return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
5301 void dispatchNewAnimatorScaleLocked(Session session) {
5302 mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget();
5306 public void registerPointerEventListener(PointerEventListener listener) {
5307 mPointerEventDispatcher.registerInputEventListener(listener);
5311 public void unregisterPointerEventListener(PointerEventListener listener) {
5312 mPointerEventDispatcher.unregisterInputEventListener(listener);
5315 // Called by window manager policy. Not exposed externally.
5317 public int getLidState() {
5318 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5319 InputManagerService.SW_LID);
5321 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5323 } else if (sw == 0) {
5324 // Switch state: AKEY_STATE_UP.
5327 // Switch state: AKEY_STATE_UNKNOWN.
5332 // Called by window manager policy. Not exposed externally.
5334 public void switchKeyboardLayout(int deviceId, int direction) {
5335 mInputManager.switchKeyboardLayout(deviceId, direction);
5338 // Called by window manager policy. Not exposed externally.
5340 public void shutdown(boolean confirm) {
5341 ShutdownThread.shutdown(mContext, confirm);
5344 // Called by window manager policy. Not exposed externally.
5346 public void rebootSafeMode(boolean confirm) {
5347 ShutdownThread.rebootSafeMode(mContext, confirm);
5350 public void setCurrentProfileIds(final int[] currentProfileIds) {
5351 synchronized (mWindowMap) {
5352 mCurrentProfileIds = currentProfileIds;
5356 public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
5357 synchronized (mWindowMap) {
5358 mCurrentUserId = newUserId;
5359 mCurrentProfileIds = currentProfileIds;
5360 mAppTransition.setCurrentUser(newUserId);
5361 mPolicy.setCurrentUserLw(newUserId);
5363 // Hide windows that should not be seen by the new user.
5364 final int numDisplays = mDisplayContents.size();
5365 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5366 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
5367 displayContent.switchUserStacks(newUserId);
5368 rebuildAppWindowListLocked(displayContent);
5370 performLayoutAndPlaceSurfacesLocked();
5374 /* Called by WindowState */
5375 boolean isCurrentProfileLocked(int userId) {
5376 if (userId == mCurrentUserId) return true;
5377 for (int i = 0; i < mCurrentProfileIds.length; i++) {
5378 if (mCurrentProfileIds[i] == userId) return true;
5383 public void enableScreenAfterBoot() {
5384 synchronized(mWindowMap) {
5386 RuntimeException here = new RuntimeException("here");
5387 here.fillInStackTrace();
5388 Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
5389 + " mForceDisplayEnabled=" + mForceDisplayEnabled
5390 + " mShowingBootMessages=" + mShowingBootMessages
5391 + " mSystemBooted=" + mSystemBooted, here);
5393 if (mSystemBooted) {
5396 mSystemBooted = true;
5397 hideBootMessagesLocked();
5398 // If the screen still doesn't come up after 30 seconds, give
5399 // up and turn it on.
5400 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
5403 mPolicy.systemBooted();
5405 performEnableScreen();
5409 public void enableScreenIfNeeded() {
5410 synchronized (mWindowMap) {
5411 enableScreenIfNeededLocked();
5415 void enableScreenIfNeededLocked() {
5417 RuntimeException here = new RuntimeException("here");
5418 here.fillInStackTrace();
5419 Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
5420 + " mForceDisplayEnabled=" + mForceDisplayEnabled
5421 + " mShowingBootMessages=" + mShowingBootMessages
5422 + " mSystemBooted=" + mSystemBooted, here);
5424 if (mDisplayEnabled) {
5427 if (!mSystemBooted && !mShowingBootMessages) {
5430 mH.sendEmptyMessage(H.ENABLE_SCREEN);
5433 public void performBootTimeout() {
5434 synchronized(mWindowMap) {
5435 if (mDisplayEnabled) {
5438 Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled");
5439 mForceDisplayEnabled = true;
5441 performEnableScreen();
5444 public void performEnableScreen() {
5445 synchronized(mWindowMap) {
5447 RuntimeException here = new RuntimeException("here");
5448 here.fillInStackTrace();
5449 Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
5450 + " mForceDisplayEnabled=" + mForceDisplayEnabled
5451 + " mShowingBootMessages=" + mShowingBootMessages
5452 + " mSystemBooted=" + mSystemBooted
5453 + " mOnlyCore=" + mOnlyCore, here);
5455 if (mDisplayEnabled) {
5458 if (!mSystemBooted && !mShowingBootMessages) {
5462 if (!mForceDisplayEnabled) {
5463 // Don't enable the screen until all existing windows
5465 boolean haveBootMsg = false;
5466 boolean haveApp = false;
5467 // if the wallpaper service is disabled on the device, we're never going to have
5468 // wallpaper, don't bother waiting for it
5469 boolean haveWallpaper = false;
5470 boolean wallpaperEnabled = mContext.getResources().getBoolean(
5471 com.android.internal.R.bool.config_enableWallpaperService)
5473 boolean haveKeyguard = true;
5474 // TODO(multidisplay): Expand to all displays?
5475 final WindowList windows = getDefaultWindowListLocked();
5476 final int N = windows.size();
5477 for (int i=0; i<N; i++) {
5478 WindowState w = windows.get(i);
5479 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
5482 if (w.isDrawnLw()) {
5483 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
5485 } else if (w.mAttrs.type == TYPE_APPLICATION) {
5487 } else if (w.mAttrs.type == TYPE_WALLPAPER) {
5488 haveWallpaper = true;
5489 } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
5490 haveKeyguard = mPolicy.isKeyguardDrawnLw();
5495 if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
5496 Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
5497 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
5498 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
5499 + " haveKeyguard=" + haveKeyguard);
5502 // If we are turning on the screen to show the boot message,
5503 // don't do it until the boot message is actually displayed.
5504 if (!mSystemBooted && !haveBootMsg) {
5508 // If we are turning on the screen after the boot is completed
5509 // normally, don't do so until we have the application and
5511 if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
5512 (wallpaperEnabled && !haveWallpaper))) {
5517 mDisplayEnabled = true;
5518 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
5520 StringWriter sw = new StringWriter();
5521 PrintWriter pw = new FastPrintWriter(sw, false, 1024);
5522 this.dump(null, pw, null);
5524 Slog.i(TAG, sw.toString());
5527 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5528 if (surfaceFlinger != null) {
5529 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5530 Parcel data = Parcel.obtain();
5531 data.writeInterfaceToken("android.ui.ISurfaceComposer");
5532 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5536 } catch (RemoteException ex) {
5537 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
5540 // Enable input dispatch.
5541 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5544 mPolicy.enableScreenAfterBoot();
5546 // Make sure the last requested orientation has been applied.
5547 updateRotationUnchecked(false, false);
5550 public void showBootMessage(final CharSequence msg, final boolean always) {
5551 boolean first = false;
5552 synchronized(mWindowMap) {
5554 RuntimeException here = new RuntimeException("here");
5555 here.fillInStackTrace();
5556 Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always
5557 + " mAllowBootMessages=" + mAllowBootMessages
5558 + " mShowingBootMessages=" + mShowingBootMessages
5559 + " mSystemBooted=" + mSystemBooted, here);
5561 if (!mAllowBootMessages) {
5564 if (!mShowingBootMessages) {
5570 if (mSystemBooted) {
5573 mShowingBootMessages = true;
5574 mPolicy.showBootMessage(msg, always);
5577 performEnableScreen();
5581 public void hideBootMessagesLocked() {
5583 RuntimeException here = new RuntimeException("here");
5584 here.fillInStackTrace();
5585 Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
5586 + " mForceDisplayEnabled=" + mForceDisplayEnabled
5587 + " mShowingBootMessages=" + mShowingBootMessages
5588 + " mSystemBooted=" + mSystemBooted, here);
5590 if (mShowingBootMessages) {
5591 mShowingBootMessages = false;
5592 mPolicy.hideBootMessages();
5597 public void setInTouchMode(boolean mode) {
5598 synchronized(mWindowMap) {
5599 mInTouchMode = mode;
5603 // TODO: more accounting of which pid(s) turned it on, keep count,
5604 // only allow disables from pids which have count on, etc.
5606 public void showStrictModeViolation(boolean on) {
5607 int pid = Binder.getCallingPid();
5608 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
5611 private void showStrictModeViolation(int arg, int pid) {
5612 final boolean on = arg != 0;
5613 synchronized(mWindowMap) {
5614 // Ignoring requests to enable the red border from clients
5615 // which aren't on screen. (e.g. Broadcast Receivers in
5616 // the background..)
5618 boolean isVisible = false;
5619 final int numDisplays = mDisplayContents.size();
5620 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5621 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5622 final int numWindows = windows.size();
5623 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5624 final WindowState ws = windows.get(winNdx);
5625 if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
5636 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5637 ">>> OPEN TRANSACTION showStrictModeViolation");
5638 SurfaceControl.openTransaction();
5640 // TODO(multi-display): support multiple displays
5641 if (mStrictModeFlash == null) {
5642 mStrictModeFlash = new StrictModeFlash(
5643 getDefaultDisplayContentLocked().getDisplay(), mFxSession);
5645 mStrictModeFlash.setVisibility(on);
5647 SurfaceControl.closeTransaction();
5648 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5649 "<<< CLOSE TRANSACTION showStrictModeViolation");
5655 public void setStrictModeVisualIndicatorPreference(String value) {
5656 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
5660 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
5661 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
5662 * of the target image.
5664 * @param displayId the Display to take a screenshot of.
5665 * @param width the width of the target bitmap
5666 * @param height the height of the target bitmap
5667 * @param force565 if true the returned bitmap will be RGB_565, otherwise it
5668 * will be the same config as the surface
5671 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
5672 int height, boolean force565) {
5673 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5674 "screenshotApplications()")) {
5675 throw new SecurityException("Requires READ_FRAME_BUFFER permission");
5678 Bitmap rawss = null;
5681 final Rect frame = new Rect();
5685 int rot = Surface.ROTATION_0;
5687 boolean screenshotReady;
5689 if (appToken == null) {
5690 screenshotReady = true;
5693 screenshotReady = false;
5694 minLayer = Integer.MAX_VALUE;
5698 WindowState appWin = null;
5701 if (retryCount++ > 0) {
5704 } catch (InterruptedException e) {
5707 synchronized(mWindowMap) {
5708 final DisplayContent displayContent = getDisplayContentLocked(displayId);
5709 if (displayContent == null) {
5712 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5713 dw = displayInfo.logicalWidth;
5714 dh = displayInfo.logicalHeight;
5716 int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION)
5717 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
5718 aboveAppLayer += TYPE_LAYER_MULTIPLIER;
5720 boolean isImeTarget = mInputMethodTarget != null
5721 && mInputMethodTarget.mAppToken != null
5722 && mInputMethodTarget.mAppToken.appToken != null
5723 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
5725 // Figure out the part of the screen that is actually the app.
5726 boolean including = false;
5728 final WindowList windows = displayContent.getWindowList();
5729 final Rect stackBounds = new Rect();
5730 for (int i = windows.size() - 1; i >= 0; i--) {
5731 WindowState ws = windows.get(i);
5732 if (!ws.mHasSurface) {
5735 if (ws.mLayer >= aboveAppLayer) {
5738 // When we will skip windows: when we are not including
5739 // ones behind a window we didn't skip, and we are actually
5740 // taking a screenshot of a specific app.
5741 if (!including && appToken != null) {
5742 // Also, we can possibly skip this window if it is not
5743 // an IME target or the application for the screenshot
5744 // is not the current IME target.
5745 if (!ws.mIsImWindow || !isImeTarget) {
5746 // And finally, this window is of no interest if it
5747 // is not associated with the screenshot app.
5748 if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
5752 ws.getStackBounds(stackBounds);
5756 // We keep on including windows until we go past a full-screen
5758 including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh);
5760 final WindowStateAnimator winAnim = ws.mWinAnimator;
5761 if (maxLayer < winAnim.mSurfaceLayer) {
5762 maxLayer = winAnim.mSurfaceLayer;
5764 if (minLayer > winAnim.mSurfaceLayer) {
5765 minLayer = winAnim.mSurfaceLayer;
5768 // Don't include wallpaper in bounds calculation
5769 if (!ws.mIsWallpaper) {
5770 final Rect wf = ws.mFrame;
5771 final Rect cr = ws.mContentInsets;
5772 int left = wf.left + cr.left;
5773 int top = wf.top + cr.top;
5774 int right = wf.right - cr.right;
5775 int bottom = wf.bottom - cr.bottom;
5776 frame.union(left, top, right, bottom);
5777 frame.intersect(stackBounds);
5780 if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
5781 ws.isDisplayedLw()) {
5782 screenshotReady = true;
5786 if (appToken != null && appWin == null) {
5787 // Can't find a window to snapshot.
5788 if (DEBUG_SCREENSHOT) Slog.i(TAG,
5789 "Screenshot: Couldn't find a surface matching " + appToken);
5792 if (!screenshotReady) {
5793 // Delay and hope that window gets drawn.
5794 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken
5795 + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState);
5799 // Constrain frame to the screen size.
5800 frame.intersect(0, 0, dw, dh);
5802 if (frame.isEmpty() || maxLayer == 0) {
5803 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
5804 + ": returning null frame=" + frame.toShortString() + " maxLayer="
5809 // The screenshot API does not apply the current screen rotation.
5810 rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
5811 int fw = frame.width();
5812 int fh = frame.height();
5814 // Constrain thumbnail to smaller of screen width or height. Assumes aspect
5815 // of thumbnail is the same as the screen (in landscape) or square.
5816 scale = Math.max(width / (float) fw, height / (float) fh);
5818 float targetWidthScale = width / (float) fw;
5819 float targetHeightScale = height / (float) fh;
5821 scale = targetWidthScale;
5822 // If aspect of thumbnail is the same as the screen (in landscape),
5823 // select the slightly larger value so we fill the entire bitmap
5824 if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) {
5825 scale = targetHeightScale;
5828 scale = targetHeightScale;
5829 // If aspect of thumbnail is the same as the screen (in landscape),
5830 // select the slightly larger value so we fill the entire bitmap
5831 if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) {
5832 scale = targetWidthScale;
5837 // The screen shot will contain the entire screen.
5838 dw = (int)(dw*scale);
5839 dh = (int)(dh*scale);
5840 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
5844 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
5846 if (DEBUG_SCREENSHOT) {
5847 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
5848 + maxLayer + " appToken=" + appToken);
5849 for (int i = 0; i < windows.size(); i++) {
5850 WindowState win = windows.get(i);
5851 Slog.i(TAG, win + ": " + win.mLayer
5852 + " animLayer=" + win.mWinAnimator.mAnimLayer
5853 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
5856 // TODO: Replace 'false' in the following line with a variable that indicates
5857 // whether the screenshot should use the identity transformation matrix
5858 // (e.g., enable it when taking a screenshot for recents, since we might be in
5859 // the middle of the rotation animation, but don't want a rotated recent image).
5860 // TODO: Replace 'new Rect()' with the portion of the screen to capture for the
5862 rawss = SurfaceControl.screenshot(new Rect(), dw, dh, minLayer, maxLayer, false);
5864 } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES);
5865 if (retryCount > MAX_SCREENSHOT_RETRIES) Slog.i(TAG, "Screenshot max retries " +
5866 retryCount + " of " + appToken + " appWin=" + (appWin == null ?
5867 "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState)));
5869 if (rawss == null) {
5870 Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
5871 + ") to layer " + maxLayer);
5875 Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig());
5876 bm.eraseColor(0xFF000000);
5878 Matrix matrix = new Matrix();
5879 ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
5880 // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left
5881 matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top));
5882 Canvas canvas = new Canvas(bm);
5883 canvas.drawBitmap(rawss, matrix, null);
5884 canvas.setBitmap(null);
5886 if (DEBUG_SCREENSHOT) {
5887 // TEST IF IT's ALL BLACK
5888 int[] buffer = new int[bm.getWidth() * bm.getHeight()];
5889 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
5890 boolean allBlack = true;
5891 final int firstColor = buffer[0];
5892 for (int i = 0; i < buffer.length; i++) {
5893 if (buffer[i] != firstColor) {
5899 Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" +
5900 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
5901 (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") +
5902 " minLayer=" + minLayer + " maxLayer=" + maxLayer);
5911 * Freeze rotation changes. (Enable "rotation lock".)
5912 * Persists across reboots.
5913 * @param rotation The desired rotation to freeze to, or -1 to use the
5917 public void freezeRotation(int rotation) {
5918 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5919 "freezeRotation()")) {
5920 throw new SecurityException("Requires SET_ORIENTATION permission");
5922 if (rotation < -1 || rotation > Surface.ROTATION_270) {
5923 throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
5924 + "rotation constant.");
5927 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
5929 long origId = Binder.clearCallingIdentity();
5931 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
5932 rotation == -1 ? mRotation : rotation);
5934 Binder.restoreCallingIdentity(origId);
5937 updateRotationUnchecked(false, false);
5941 * Thaw rotation changes. (Disable "rotation lock".)
5942 * Persists across reboots.
5945 public void thawRotation() {
5946 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5947 "thawRotation()")) {
5948 throw new SecurityException("Requires SET_ORIENTATION permission");
5951 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
5953 long origId = Binder.clearCallingIdentity();
5955 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
5956 777); // rot not used
5958 Binder.restoreCallingIdentity(origId);
5961 updateRotationUnchecked(false, false);
5965 * Recalculate the current rotation.
5967 * Called by the window manager policy whenever the state of the system changes
5968 * such that the current rotation might need to be updated, such as when the
5969 * device is docked or rotated into a new posture.
5972 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
5973 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
5977 * Temporarily pauses rotation changes until resumed.
5979 * This can be used to prevent rotation changes from occurring while the user is
5980 * performing certain operations, such as drag and drop.
5982 * This call nests and must be matched by an equal number of calls to
5983 * {@link #resumeRotationLocked}.
5985 void pauseRotationLocked() {
5986 mDeferredRotationPauseCount += 1;
5990 * Resumes normal rotation changes after being paused.
5992 void resumeRotationLocked() {
5993 if (mDeferredRotationPauseCount > 0) {
5994 mDeferredRotationPauseCount -= 1;
5995 if (mDeferredRotationPauseCount == 0) {
5996 boolean changed = updateRotationUncheckedLocked(false);
5998 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6004 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
6005 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
6006 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
6008 long origId = Binder.clearCallingIdentity();
6010 synchronized(mWindowMap) {
6011 changed = updateRotationUncheckedLocked(false);
6012 if (!changed || forceRelayout) {
6013 getDefaultDisplayContentLocked().layoutNeeded = true;
6014 performLayoutAndPlaceSurfacesLocked();
6018 if (changed || alwaysSendConfiguration) {
6019 sendNewConfiguration();
6022 Binder.restoreCallingIdentity(origId);
6025 // TODO(multidisplay): Rotate any display?
6027 * Updates the current rotation.
6029 * Returns true if the rotation has been changed. In this case YOU
6030 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
6032 public boolean updateRotationUncheckedLocked(boolean inTransaction) {
6033 if (mDeferredRotationPauseCount > 0) {
6034 // Rotation updates have been paused temporarily. Defer the update until
6035 // updates have been resumed.
6036 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");
6040 ScreenRotationAnimation screenRotationAnimation =
6041 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6042 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
6043 // Rotation updates cannot be performed while the previous rotation change
6044 // animation is still in progress. Skip this update. We will try updating
6045 // again after the animation is finished and the display is unfrozen.
6046 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");
6050 if (!mDisplayEnabled) {
6051 // No point choosing a rotation if the display is not enabled.
6052 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");
6056 // TODO: Implement forced rotation changes.
6057 // Set mAltOrientation to indicate that the application is receiving
6058 // an orientation that has different metrics than it expected.
6059 // eg. Portrait instead of Landscape.
6061 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
6062 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
6063 mForcedAppOrientation, rotation);
6065 if (DEBUG_ORIENTATION) {
6066 Slog.v(TAG, "Application requested orientation "
6067 + mForcedAppOrientation + ", got rotation " + rotation
6068 + " which has " + (altOrientation ? "incompatible" : "compatible")
6072 if (mRotation == rotation && mAltOrientation == altOrientation) {
6077 if (DEBUG_ORIENTATION) {
6079 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
6080 + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
6081 + ", forceApp=" + mForcedAppOrientation);
6084 mRotation = rotation;
6085 mAltOrientation = altOrientation;
6086 mPolicy.setRotationLw(mRotation);
6088 mWindowsFreezingScreen = true;
6089 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
6090 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
6091 mWaitingForConfig = true;
6092 final DisplayContent displayContent = getDefaultDisplayContentLocked();
6093 displayContent.layoutNeeded = true;
6094 final int[] anim = new int[2];
6095 if (displayContent.isDimming()) {
6096 anim[0] = anim[1] = 0;
6098 mPolicy.selectRotationAnimationLw(anim);
6100 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
6101 // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
6102 screenRotationAnimation =
6103 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6105 // We need to update our screen size information to match the new
6106 // rotation. Note that this is redundant with the later call to
6107 // sendNewConfiguration() that must be called after this function
6108 // returns... however we need to do the screen size part of that
6109 // before then so we have the correct size to use when initializing
6110 // the rotation animation for the new rotation.
6111 computeScreenConfigurationLocked(null);
6113 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6114 if (!inTransaction) {
6115 if (SHOW_TRANSACTIONS) {
6116 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
6118 SurfaceControl.openTransaction();
6121 // NOTE: We disable the rotation in the emulator because
6122 // it doesn't support hardware OpenGL emulation yet.
6123 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
6124 && screenRotationAnimation.hasScreenshot()) {
6125 if (screenRotationAnimation.setRotationInTransaction(
6126 rotation, mFxSession,
6127 MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(),
6128 displayInfo.logicalWidth, displayInfo.logicalHeight)) {
6129 scheduleAnimationLocked();
6133 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
6135 if (!inTransaction) {
6136 SurfaceControl.closeTransaction();
6137 if (SHOW_LIGHT_TRANSACTIONS) {
6138 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
6143 final WindowList windows = displayContent.getWindowList();
6144 for (int i = windows.size() - 1; i >= 0; i--) {
6145 WindowState w = windows.get(i);
6146 if (w.mHasSurface) {
6147 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
6148 w.mOrientationChanging = true;
6149 mInnerFields.mOrientationChangeComplete = false;
6151 w.mLastFreezeDuration = 0;
6154 for (int i=mRotationWatchers.size()-1; i>=0; i--) {
6156 mRotationWatchers.get(i).watcher.onRotationChanged(rotation);
6157 } catch (RemoteException e) {
6161 //TODO (multidisplay): Magnification is supported only for the default display.
6162 if (mAccessibilityController != null
6163 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
6164 mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation);
6171 public int getRotation() {
6176 public boolean isRotationFrozen() {
6177 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6181 public int watchRotation(IRotationWatcher watcher) {
6182 final IBinder watcherBinder = watcher.asBinder();
6183 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6185 public void binderDied() {
6186 synchronized (mWindowMap) {
6187 for (int i=0; i<mRotationWatchers.size(); i++) {
6188 if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) {
6189 RotationWatcher removed = mRotationWatchers.remove(i);
6190 IBinder binder = removed.watcher.asBinder();
6191 if (binder != null) {
6192 binder.unlinkToDeath(this, 0);
6201 synchronized (mWindowMap) {
6203 watcher.asBinder().linkToDeath(dr, 0);
6204 mRotationWatchers.add(new RotationWatcher(watcher, dr));
6205 } catch (RemoteException e) {
6206 // Client died, no cleanup needed.
6214 public void removeRotationWatcher(IRotationWatcher watcher) {
6215 final IBinder watcherBinder = watcher.asBinder();
6216 synchronized (mWindowMap) {
6217 for (int i=0; i<mRotationWatchers.size(); i++) {
6218 RotationWatcher rotationWatcher = mRotationWatchers.get(i);
6219 if (watcherBinder == rotationWatcher.watcher.asBinder()) {
6220 RotationWatcher removed = mRotationWatchers.remove(i);
6221 IBinder binder = removed.watcher.asBinder();
6222 if (binder != null) {
6223 binder.unlinkToDeath(removed.deathRecipient, 0);
6232 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6233 * theme attribute) on devices that feature a physical options menu key attempt to position
6234 * their menu panel window along the edge of the screen nearest the physical menu key.
6235 * This lowers the travel distance between invoking the menu panel and selecting
6238 * This method helps control where that menu is placed. Its current implementation makes
6239 * assumptions about the menu key and its relationship to the screen based on whether
6240 * the device's natural orientation is portrait (width < height) or landscape.
6242 * The menu key is assumed to be located along the bottom edge of natural-portrait
6243 * devices and along the right edge of natural-landscape devices. If these assumptions
6244 * do not hold for the target device, this method should be changed to reflect that.
6246 * @return A {@link Gravity} value for placing the options menu window
6249 public int getPreferredOptionsPanelGravity() {
6250 synchronized (mWindowMap) {
6251 final int rotation = getRotation();
6253 // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6254 final DisplayContent displayContent = getDefaultDisplayContentLocked();
6255 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6256 // On devices with a natural orientation of portrait
6259 case Surface.ROTATION_0:
6260 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6261 case Surface.ROTATION_90:
6262 return Gravity.RIGHT | Gravity.BOTTOM;
6263 case Surface.ROTATION_180:
6264 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6265 case Surface.ROTATION_270:
6266 return Gravity.START | Gravity.BOTTOM;
6270 // On devices with a natural orientation of landscape
6273 case Surface.ROTATION_0:
6274 return Gravity.RIGHT | Gravity.BOTTOM;
6275 case Surface.ROTATION_90:
6276 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6277 case Surface.ROTATION_180:
6278 return Gravity.START | Gravity.BOTTOM;
6279 case Surface.ROTATION_270:
6280 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6286 * Starts the view server on the specified port.
6288 * @param port The port to listener to.
6290 * @return True if the server was successfully started, false otherwise.
6292 * @see com.android.server.wm.ViewServer
6293 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
6296 public boolean startViewServer(int port) {
6297 if (isSystemSecure()) {
6301 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
6309 if (mViewServer != null) {
6310 if (!mViewServer.isRunning()) {
6312 return mViewServer.start();
6313 } catch (IOException e) {
6314 Slog.w(TAG, "View server did not start");
6321 mViewServer = new ViewServer(this, port);
6322 return mViewServer.start();
6323 } catch (IOException e) {
6324 Slog.w(TAG, "View server did not start");
6329 private boolean isSystemSecure() {
6330 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
6331 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6335 * Stops the view server if it exists.
6337 * @return True if the server stopped, false if it wasn't started or
6338 * couldn't be stopped.
6340 * @see com.android.server.wm.ViewServer
6343 public boolean stopViewServer() {
6344 if (isSystemSecure()) {
6348 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
6352 if (mViewServer != null) {
6353 return mViewServer.stop();
6359 * Indicates whether the view server is running.
6361 * @return True if the server is running, false otherwise.
6363 * @see com.android.server.wm.ViewServer
6366 public boolean isViewServerRunning() {
6367 if (isSystemSecure()) {
6371 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
6375 return mViewServer != null && mViewServer.isRunning();
6379 * Lists all availble windows in the system. The listing is written in the
6380 * specified Socket's output stream with the following syntax:
6381 * windowHashCodeInHexadecimal windowName
6382 * Each line of the ouput represents a different window.
6384 * @param client The remote client to send the listing to.
6385 * @return False if an error occured, true otherwise.
6387 boolean viewServerListWindows(Socket client) {
6388 if (isSystemSecure()) {
6392 boolean result = true;
6394 WindowList windows = new WindowList();
6395 synchronized (mWindowMap) {
6396 //noinspection unchecked
6397 final int numDisplays = mDisplayContents.size();
6398 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6399 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
6400 windows.addAll(displayContent.getWindowList());
6404 BufferedWriter out = null;
6406 // Any uncaught exception will crash the system process
6408 OutputStream clientStream = client.getOutputStream();
6409 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6411 final int count = windows.size();
6412 for (int i = 0; i < count; i++) {
6413 final WindowState w = windows.get(i);
6414 out.write(Integer.toHexString(System.identityHashCode(w)));
6416 out.append(w.mAttrs.getTitle());
6420 out.write("DONE.\n");
6422 } catch (Exception e) {
6428 } catch (IOException e) {
6437 // TODO(multidisplay): Extend to multiple displays.
6439 * Returns the focused window in the following format:
6440 * windowHashCodeInHexadecimal windowName
6442 * @param client The remote client to send the listing to.
6443 * @return False if an error occurred, true otherwise.
6445 boolean viewServerGetFocusedWindow(Socket client) {
6446 if (isSystemSecure()) {
6450 boolean result = true;
6452 WindowState focusedWindow = getFocusedWindow();
6454 BufferedWriter out = null;
6456 // Any uncaught exception will crash the system process
6458 OutputStream clientStream = client.getOutputStream();
6459 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6461 if(focusedWindow != null) {
6462 out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
6464 out.append(focusedWindow.mAttrs.getTitle());
6468 } catch (Exception e) {
6474 } catch (IOException e) {
6484 * Sends a command to a target window. The result of the command, if any, will be
6485 * written in the output stream of the specified socket.
6487 * The parameters must follow this syntax:
6488 * windowHashcode extra
6490 * Where XX is the length in characeters of the windowTitle.
6492 * The first parameter is the target window. The window with the specified hashcode
6493 * will be the target. If no target can be found, nothing happens. The extra parameters
6494 * will be delivered to the target window and as parameters to the command itself.
6496 * @param client The remote client to sent the result, if any, to.
6497 * @param command The command to execute.
6498 * @param parameters The command parameters.
6500 * @return True if the command was successfully delivered, false otherwise. This does
6501 * not indicate whether the command itself was successful.
6503 boolean viewServerWindowCommand(Socket client, String command, String parameters) {
6504 if (isSystemSecure()) {
6508 boolean success = true;
6510 Parcel reply = null;
6512 BufferedWriter out = null;
6514 // Any uncaught exception will crash the system process
6516 // Find the hashcode of the window
6517 int index = parameters.indexOf(' ');
6519 index = parameters.length();
6521 final String code = parameters.substring(0, index);
6522 int hashCode = (int) Long.parseLong(code, 16);
6524 // Extract the command's parameter after the window description
6525 if (index < parameters.length()) {
6526 parameters = parameters.substring(index + 1);
6531 final WindowState window = findWindow(hashCode);
6532 if (window == null) {
6536 data = Parcel.obtain();
6537 data.writeInterfaceToken("android.view.IWindow");
6538 data.writeString(command);
6539 data.writeString(parameters);
6541 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
6543 reply = Parcel.obtain();
6545 final IBinder binder = window.mClient.asBinder();
6546 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
6547 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
6549 reply.readException();
6551 if (!client.isOutputShutdown()) {
6552 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
6553 out.write("DONE\n");
6557 } catch (Exception e) {
6558 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
6564 if (reply != null) {
6570 } catch (IOException e) {
6579 public void addWindowChangeListener(WindowChangeListener listener) {
6580 synchronized(mWindowMap) {
6581 mWindowChangeListeners.add(listener);
6585 public void removeWindowChangeListener(WindowChangeListener listener) {
6586 synchronized(mWindowMap) {
6587 mWindowChangeListeners.remove(listener);
6591 private void notifyWindowsChanged() {
6592 WindowChangeListener[] windowChangeListeners;
6593 synchronized(mWindowMap) {
6594 if(mWindowChangeListeners.isEmpty()) {
6597 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6598 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6600 int N = windowChangeListeners.length;
6601 for(int i = 0; i < N; i++) {
6602 windowChangeListeners[i].windowsChanged();
6606 private void notifyFocusChanged() {
6607 WindowChangeListener[] windowChangeListeners;
6608 synchronized(mWindowMap) {
6609 if(mWindowChangeListeners.isEmpty()) {
6612 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6613 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6615 int N = windowChangeListeners.length;
6616 for(int i = 0; i < N; i++) {
6617 windowChangeListeners[i].focusChanged();
6621 private WindowState findWindow(int hashCode) {
6622 if (hashCode == -1) {
6623 // TODO(multidisplay): Extend to multiple displays.
6624 return getFocusedWindow();
6627 synchronized (mWindowMap) {
6628 final int numDisplays = mDisplayContents.size();
6629 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6630 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
6631 final int numWindows = windows.size();
6632 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
6633 final WindowState w = windows.get(winNdx);
6634 if (System.identityHashCode(w) == hashCode) {
6645 * Instruct the Activity Manager to fetch the current configuration and broadcast
6646 * that to config-changed listeners if appropriate.
6648 void sendNewConfiguration() {
6650 mActivityManager.updateConfiguration(null);
6651 } catch (RemoteException e) {
6655 public Configuration computeNewConfiguration() {
6656 synchronized (mWindowMap) {
6657 Configuration config = computeNewConfigurationLocked();
6658 if (config == null && mWaitingForConfig) {
6659 // Nothing changed but we are waiting for something... stop that!
6660 mWaitingForConfig = false;
6661 mLastFinishedFreezeSource = "new-config";
6662 performLayoutAndPlaceSurfacesLocked();
6668 Configuration computeNewConfigurationLocked() {
6669 Configuration config = new Configuration();
6670 config.fontScale = 0;
6671 if (!computeScreenConfigurationLocked(config)) {
6677 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
6678 // TODO: Multidisplay: for now only use with default display.
6679 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
6680 if (width < displayInfo.smallestNominalAppWidth) {
6681 displayInfo.smallestNominalAppWidth = width;
6683 if (width > displayInfo.largestNominalAppWidth) {
6684 displayInfo.largestNominalAppWidth = width;
6686 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
6687 if (height < displayInfo.smallestNominalAppHeight) {
6688 displayInfo.smallestNominalAppHeight = height;
6690 if (height > displayInfo.largestNominalAppHeight) {
6691 displayInfo.largestNominalAppHeight = height;
6695 private int reduceConfigLayout(int curLayout, int rotation, float density,
6697 // TODO: Multidisplay: for now only use with default display.
6698 // Get the app screen size at this rotation.
6699 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6700 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6702 // Compute the screen layout size class for this rotation.
6705 if (longSize < shortSize) {
6707 longSize = shortSize;
6710 longSize = (int)(longSize/density);
6711 shortSize = (int)(shortSize/density);
6712 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
6715 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
6716 int dw, int dh, float density, Configuration outConfig) {
6717 // TODO: Multidisplay: for now only use with default display.
6719 // We need to determine the smallest width that will occur under normal
6720 // operation. To this, start with the base screen size and compute the
6721 // width under the different possible rotations. We need to un-rotate
6722 // the current screen dimensions before doing this.
6723 int unrotDw, unrotDh;
6731 displayInfo.smallestNominalAppWidth = 1<<30;
6732 displayInfo.smallestNominalAppHeight = 1<<30;
6733 displayInfo.largestNominalAppWidth = 0;
6734 displayInfo.largestNominalAppHeight = 0;
6735 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
6736 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
6737 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
6738 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
6739 int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
6740 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
6741 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
6742 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
6743 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
6744 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
6745 outConfig.screenLayout = sl;
6748 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
6750 // TODO: Multidisplay: for now only use with default display.
6751 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6752 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6753 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
6754 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
6755 if (curSize == 0 || size < curSize) {
6761 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) {
6762 // TODO: Multidisplay: for now only use with default display.
6763 mTmpDisplayMetrics.setTo(dm);
6764 final DisplayMetrics tmpDm = mTmpDisplayMetrics;
6765 final int unrotDw, unrotDh;
6773 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
6774 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
6775 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
6776 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
6780 boolean computeScreenConfigurationLocked(Configuration config) {
6781 if (!mDisplayReady) {
6785 // TODO(multidisplay): For now, apply Configuration to main screen only.
6786 final DisplayContent displayContent = getDefaultDisplayContentLocked();
6788 // Use the effective "visual" dimensions based on current rotation
6789 final boolean rotated = (mRotation == Surface.ROTATION_90
6790 || mRotation == Surface.ROTATION_270);
6791 final int realdw = rotated ?
6792 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
6793 final int realdh = rotated ?
6794 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
6798 if (mAltOrientation) {
6799 if (realdw > realdh) {
6800 // Turn landscape into portrait.
6801 int maxw = (int)(realdh/1.3f);
6802 if (maxw < realdw) {
6806 // Turn portrait into landscape.
6807 int maxh = (int)(realdw/1.3f);
6808 if (maxh < realdh) {
6814 if (config != null) {
6815 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
6816 Configuration.ORIENTATION_LANDSCAPE;
6819 // Update application display metrics.
6820 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
6821 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
6822 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6823 synchronized(displayContent.mDisplaySizeLock) {
6824 displayInfo.rotation = mRotation;
6825 displayInfo.logicalWidth = dw;
6826 displayInfo.logicalHeight = dh;
6827 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
6828 displayInfo.appWidth = appWidth;
6829 displayInfo.appHeight = appHeight;
6830 displayInfo.getLogicalMetrics(mRealDisplayMetrics,
6831 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
6832 displayInfo.getAppMetrics(mDisplayMetrics);
6833 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
6834 displayContent.getDisplayId(), displayInfo);
6837 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
6840 final DisplayMetrics dm = mDisplayMetrics;
6841 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
6842 mCompatDisplayMetrics);
6844 if (config != null) {
6845 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
6847 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
6849 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
6851 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
6852 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
6853 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
6854 config.densityDpi = displayContent.mBaseDisplayDensity;
6856 // Update the configuration based on available input devices, lid switch,
6857 // and platform configuration.
6858 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6859 config.keyboard = Configuration.KEYBOARD_NOKEYS;
6860 config.navigation = Configuration.NAVIGATION_NONAV;
6862 int keyboardPresence = 0;
6863 int navigationPresence = 0;
6864 final InputDevice[] devices = mInputManager.getInputDevices();
6865 final int len = devices.length;
6866 for (int i = 0; i < len; i++) {
6867 InputDevice device = devices[i];
6868 if (!device.isVirtual()) {
6869 final int sources = device.getSources();
6870 final int presenceFlag = device.isExternal() ?
6871 WindowManagerPolicy.PRESENCE_EXTERNAL :
6872 WindowManagerPolicy.PRESENCE_INTERNAL;
6874 if (mIsTouchDevice) {
6875 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
6876 InputDevice.SOURCE_TOUCHSCREEN) {
6877 config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
6880 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6883 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
6884 config.navigation = Configuration.NAVIGATION_TRACKBALL;
6885 navigationPresence |= presenceFlag;
6886 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
6887 && config.navigation == Configuration.NAVIGATION_NONAV) {
6888 config.navigation = Configuration.NAVIGATION_DPAD;
6889 navigationPresence |= presenceFlag;
6892 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
6893 config.keyboard = Configuration.KEYBOARD_QWERTY;
6894 keyboardPresence |= presenceFlag;
6899 // Determine whether a hard keyboard is available and enabled.
6900 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
6901 if (hardKeyboardAvailable != mHardKeyboardAvailable) {
6902 mHardKeyboardAvailable = hardKeyboardAvailable;
6903 mHardKeyboardEnabled = hardKeyboardAvailable;
6904 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6905 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6907 if (!mHardKeyboardEnabled) {
6908 config.keyboard = Configuration.KEYBOARD_NOKEYS;
6911 // Let the policy update hidden states.
6912 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
6913 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
6914 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
6915 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
6921 public boolean isHardKeyboardAvailable() {
6922 synchronized (mWindowMap) {
6923 return mHardKeyboardAvailable;
6927 public boolean isHardKeyboardEnabled() {
6928 synchronized (mWindowMap) {
6929 return mHardKeyboardEnabled;
6933 public void setHardKeyboardEnabled(boolean enabled) {
6934 synchronized (mWindowMap) {
6935 if (mHardKeyboardEnabled != enabled) {
6936 mHardKeyboardEnabled = enabled;
6937 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6942 public void setOnHardKeyboardStatusChangeListener(
6943 OnHardKeyboardStatusChangeListener listener) {
6944 synchronized (mWindowMap) {
6945 mHardKeyboardStatusChangeListener = listener;
6949 void notifyHardKeyboardStatusChange() {
6950 final boolean available, enabled;
6951 final OnHardKeyboardStatusChangeListener listener;
6952 synchronized (mWindowMap) {
6953 listener = mHardKeyboardStatusChangeListener;
6954 available = mHardKeyboardAvailable;
6955 enabled = mHardKeyboardEnabled;
6957 if (listener != null) {
6958 listener.onHardKeyboardStatusChange(available, enabled);
6962 // -------------------------------------------------------------
6964 // -------------------------------------------------------------
6966 IBinder prepareDragSurface(IWindow window, SurfaceSession session,
6967 int flags, int width, int height, Surface outSurface) {
6969 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height
6970 + " flags=" + Integer.toHexString(flags) + " win=" + window
6971 + " asbinder=" + window.asBinder());
6974 final int callerPid = Binder.getCallingPid();
6975 final long origId = Binder.clearCallingIdentity();
6976 IBinder token = null;
6979 synchronized (mWindowMap) {
6981 if (mDragState == null) {
6982 // TODO(multi-display): support other displays
6983 final DisplayContent displayContent = getDefaultDisplayContentLocked();
6984 final Display display = displayContent.getDisplay();
6985 SurfaceControl surface = new SurfaceControl(session, "drag surface",
6986 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
6987 surface.setLayerStack(display.getLayerStack());
6988 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG "
6989 + surface + ": CREATE");
6990 outSurface.copyFrom(surface);
6991 final IBinder winBinder = window.asBinder();
6992 token = new Binder();
6993 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
6994 token = mDragState.mToken = new Binder();
6996 // 5 second timeout for this window to actually begin the drag
6997 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
6998 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
6999 mH.sendMessageDelayed(msg, 5000);
7001 Slog.w(TAG, "Drag already in progress");
7003 } catch (OutOfResourcesException e) {
7004 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
7005 if (mDragState != null) {
7012 Binder.restoreCallingIdentity(origId);
7018 // -------------------------------------------------------------
7019 // Input Events and Focus Management
7020 // -------------------------------------------------------------
7022 final InputMonitor mInputMonitor = new InputMonitor(this);
7023 private boolean mEventDispatchingEnabled;
7026 public void pauseKeyDispatching(IBinder _token) {
7027 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7028 "pauseKeyDispatching()")) {
7029 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7032 synchronized (mWindowMap) {
7033 WindowToken token = mTokenMap.get(_token);
7034 if (token != null) {
7035 mInputMonitor.pauseDispatchingLw(token);
7041 public void resumeKeyDispatching(IBinder _token) {
7042 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7043 "resumeKeyDispatching()")) {
7044 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7047 synchronized (mWindowMap) {
7048 WindowToken token = mTokenMap.get(_token);
7049 if (token != null) {
7050 mInputMonitor.resumeDispatchingLw(token);
7056 public void setEventDispatching(boolean enabled) {
7057 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7058 "setEventDispatching()")) {
7059 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7062 synchronized (mWindowMap) {
7063 mEventDispatchingEnabled = enabled;
7064 if (mDisplayEnabled) {
7065 mInputMonitor.setEventDispatchingLw(enabled);
7070 private WindowState getFocusedWindow() {
7071 synchronized (mWindowMap) {
7072 return getFocusedWindowLocked();
7076 private WindowState getFocusedWindowLocked() {
7077 return mCurrentFocus;
7080 public boolean detectSafeMode() {
7081 if (!mInputMonitor.waitForInputDevicesReady(
7082 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
7083 Slog.w(TAG, "Devices still not ready after waiting "
7084 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
7085 + " milliseconds before attempting to detect safe mode.");
7088 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7089 KeyEvent.KEYCODE_MENU);
7090 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
7091 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
7092 KeyEvent.KEYCODE_DPAD_CENTER);
7093 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
7094 InputManagerService.BTN_MOUSE);
7095 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7096 KeyEvent.KEYCODE_VOLUME_DOWN);
7097 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
7098 || volumeDownState > 0;
7100 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
7102 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
7104 } catch (IllegalArgumentException e) {
7107 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
7108 + " dpad=" + dpadState + " trackball=" + trackballState + ")");
7110 Log.i(TAG, "SAFE MODE not enabled");
7112 mPolicy.setSafeMode(mSafeMode);
7116 public void displayReady() {
7117 displayReady(Display.DEFAULT_DISPLAY);
7119 synchronized(mWindowMap) {
7120 final DisplayContent displayContent = getDefaultDisplayContentLocked();
7121 readForcedDisplaySizeAndDensityLocked(displayContent);
7122 mDisplayReady = true;
7126 mActivityManager.updateConfiguration(null);
7127 } catch (RemoteException e) {
7130 synchronized(mWindowMap) {
7131 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
7132 PackageManager.FEATURE_TOUCHSCREEN);
7133 configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
7137 mActivityManager.updateConfiguration(null);
7138 } catch (RemoteException e) {
7142 private void displayReady(int displayId) {
7143 synchronized(mWindowMap) {
7144 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7145 if (displayContent != null) {
7146 mAnimator.addDisplayLocked(displayId);
7147 synchronized(displayContent.mDisplaySizeLock) {
7148 // Bootstrap the default logical display from the display manager.
7149 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7150 DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId);
7151 if (newDisplayInfo != null) {
7152 displayInfo.copyFrom(newDisplayInfo);
7154 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
7155 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
7156 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
7157 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
7158 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
7159 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
7160 displayContent.mBaseDisplayRect.set(0, 0,
7161 displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight);
7167 public void systemReady() {
7168 mPolicy.systemReady();
7171 // -------------------------------------------------------------
7173 // -------------------------------------------------------------
7175 final class H extends Handler {
7176 public static final int REPORT_FOCUS_CHANGE = 2;
7177 public static final int REPORT_LOSING_FOCUS = 3;
7178 public static final int DO_TRAVERSAL = 4;
7179 public static final int ADD_STARTING = 5;
7180 public static final int REMOVE_STARTING = 6;
7181 public static final int FINISHED_STARTING = 7;
7182 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
7183 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
7184 public static final int WINDOW_FREEZE_TIMEOUT = 11;
7186 public static final int APP_TRANSITION_TIMEOUT = 13;
7187 public static final int PERSIST_ANIMATION_SCALE = 14;
7188 public static final int FORCE_GC = 15;
7189 public static final int ENABLE_SCREEN = 16;
7190 public static final int APP_FREEZE_TIMEOUT = 17;
7191 public static final int SEND_NEW_CONFIGURATION = 18;
7192 public static final int REPORT_WINDOWS_CHANGE = 19;
7193 public static final int DRAG_START_TIMEOUT = 20;
7194 public static final int DRAG_END_TIMEOUT = 21;
7195 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
7196 public static final int BOOT_TIMEOUT = 23;
7197 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
7198 public static final int SHOW_STRICT_MODE_VIOLATION = 25;
7199 public static final int DO_ANIMATION_CALLBACK = 26;
7201 public static final int DO_DISPLAY_ADDED = 27;
7202 public static final int DO_DISPLAY_REMOVED = 28;
7203 public static final int DO_DISPLAY_CHANGED = 29;
7205 public static final int CLIENT_FREEZE_TIMEOUT = 30;
7206 public static final int TAP_OUTSIDE_STACK = 31;
7207 public static final int NOTIFY_ACTIVITY_DRAWN = 32;
7209 public static final int ALL_WINDOWS_DRAWN = 33;
7211 public static final int NEW_ANIMATOR_SCALE = 34;
7214 public void handleMessage(Message msg) {
7215 if (DEBUG_WINDOW_TRACE) {
7216 Slog.v(TAG, "handleMessage: entry what=" + msg.what);
7219 case REPORT_FOCUS_CHANGE: {
7220 WindowState lastFocus;
7221 WindowState newFocus;
7223 synchronized(mWindowMap) {
7224 lastFocus = mLastFocus;
7225 newFocus = mCurrentFocus;
7226 if (lastFocus == newFocus) {
7227 // Focus is not changing, so nothing to do.
7230 mLastFocus = newFocus;
7231 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus +
7233 if (newFocus != null && lastFocus != null
7234 && !newFocus.isDisplayedLw()) {
7235 //Slog.i(TAG, "Delaying loss of focus...");
7236 mLosingFocus.add(lastFocus);
7241 //System.out.println("Changing focus from " + lastFocus
7242 // + " to " + newFocus);
7243 if (newFocus != null) {
7244 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus);
7245 newFocus.reportFocusChangedSerialized(true, mInTouchMode);
7246 notifyFocusChanged();
7249 if (lastFocus != null) {
7250 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus);
7251 lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
7255 case REPORT_LOSING_FOCUS: {
7256 ArrayList<WindowState> losers;
7258 synchronized(mWindowMap) {
7259 losers = mLosingFocus;
7260 mLosingFocus = new ArrayList<WindowState>();
7263 final int N = losers.size();
7264 for (int i=0; i<N; i++) {
7265 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " +
7267 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
7271 case DO_TRAVERSAL: {
7272 synchronized(mWindowMap) {
7273 mTraversalScheduled = false;
7274 performLayoutAndPlaceSurfacesLocked();
7278 case ADD_STARTING: {
7279 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7280 final StartingData sd = wtoken.startingData;
7283 // Animation has been canceled... do nothing.
7287 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
7288 + wtoken + ": pkg=" + sd.pkg);
7292 view = mPolicy.addStartingWindow(
7293 wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
7294 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags);
7295 } catch (Exception e) {
7296 Slog.w(TAG, "Exception when adding starting window", e);
7300 boolean abort = false;
7302 synchronized(mWindowMap) {
7303 if (wtoken.removed || wtoken.startingData == null) {
7304 // If the window was successfully added, then
7305 // we need to remove it.
7306 if (wtoken.startingWindow != null) {
7307 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7308 "Aborted starting " + wtoken
7309 + ": removed=" + wtoken.removed
7310 + " startingData=" + wtoken.startingData);
7311 wtoken.startingWindow = null;
7312 wtoken.startingData = null;
7316 wtoken.startingView = view;
7318 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
7319 "Added starting " + wtoken
7320 + ": startingWindow="
7321 + wtoken.startingWindow + " startingView="
7322 + wtoken.startingView);
7327 mPolicy.removeStartingWindow(wtoken.token, view);
7328 } catch (Exception e) {
7329 Slog.w(TAG, "Exception when removing starting window", e);
7335 case REMOVE_STARTING: {
7336 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7337 IBinder token = null;
7339 synchronized (mWindowMap) {
7340 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
7341 + wtoken + ": startingWindow="
7342 + wtoken.startingWindow + " startingView="
7343 + wtoken.startingView);
7344 if (wtoken.startingWindow != null) {
7345 view = wtoken.startingView;
7346 token = wtoken.token;
7347 wtoken.startingData = null;
7348 wtoken.startingView = null;
7349 wtoken.startingWindow = null;
7350 wtoken.startingDisplayed = false;
7355 mPolicy.removeStartingWindow(token, view);
7356 } catch (Exception e) {
7357 Slog.w(TAG, "Exception when removing starting window", e);
7362 case FINISHED_STARTING: {
7363 IBinder token = null;
7366 synchronized (mWindowMap) {
7367 final int N = mFinishedStarting.size();
7371 AppWindowToken wtoken = mFinishedStarting.remove(N-1);
7373 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7374 "Finished starting " + wtoken
7375 + ": startingWindow=" + wtoken.startingWindow
7376 + " startingView=" + wtoken.startingView);
7378 if (wtoken.startingWindow == null) {
7382 view = wtoken.startingView;
7383 token = wtoken.token;
7384 wtoken.startingData = null;
7385 wtoken.startingView = null;
7386 wtoken.startingWindow = null;
7387 wtoken.startingDisplayed = false;
7391 mPolicy.removeStartingWindow(token, view);
7392 } catch (Exception e) {
7393 Slog.w(TAG, "Exception when removing starting window", e);
7398 case REPORT_APPLICATION_TOKEN_DRAWN: {
7399 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7402 if (DEBUG_VISIBILITY) Slog.v(
7403 TAG, "Reporting drawn in " + wtoken);
7404 wtoken.appToken.windowsDrawn();
7405 } catch (RemoteException ex) {
7409 case REPORT_APPLICATION_TOKEN_WINDOWS: {
7410 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7412 boolean nowVisible = msg.arg1 != 0;
7413 boolean nowGone = msg.arg2 != 0;
7416 if (DEBUG_VISIBILITY) Slog.v(
7417 TAG, "Reporting visible in " + wtoken
7418 + " visible=" + nowVisible
7419 + " gone=" + nowGone);
7421 wtoken.appToken.windowsVisible();
7423 wtoken.appToken.windowsGone();
7425 } catch (RemoteException ex) {
7429 case WINDOW_FREEZE_TIMEOUT: {
7430 // TODO(multidisplay): Can non-default displays rotate?
7431 synchronized (mWindowMap) {
7432 Slog.w(TAG, "Window freeze timeout expired.");
7433 final WindowList windows = getDefaultWindowListLocked();
7434 int i = windows.size();
7437 WindowState w = windows.get(i);
7438 if (w.mOrientationChanging) {
7439 w.mOrientationChanging = false;
7440 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
7441 - mDisplayFreezeTime);
7442 Slog.w(TAG, "Force clearing orientation change: " + w);
7445 performLayoutAndPlaceSurfacesLocked();
7450 case APP_TRANSITION_TIMEOUT: {
7451 synchronized (mWindowMap) {
7452 if (mAppTransition.isTransitionSet()) {
7453 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
7454 mAppTransition.setTimeout();
7455 performLayoutAndPlaceSurfacesLocked();
7461 case PERSIST_ANIMATION_SCALE: {
7462 Settings.Global.putFloat(mContext.getContentResolver(),
7463 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
7464 Settings.Global.putFloat(mContext.getContentResolver(),
7465 Settings.Global.TRANSITION_ANIMATION_SCALE,
7466 mTransitionAnimationScaleSetting);
7467 Settings.Global.putFloat(mContext.getContentResolver(),
7468 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting);
7473 synchronized (mWindowMap) {
7474 // Since we're holding both mWindowMap and mAnimator we don't need to
7475 // hold mAnimator.mLayoutToAnim.
7476 if (mAnimator.mAnimating || mAnimationScheduled) {
7477 // If we are animating, don't do the gc now but
7478 // delay a bit so we don't interrupt the animation.
7479 sendEmptyMessageDelayed(H.FORCE_GC, 2000);
7482 // If we are currently rotating the display, it will
7483 // schedule a new message when done.
7484 if (mDisplayFrozen) {
7488 Runtime.getRuntime().gc();
7492 case ENABLE_SCREEN: {
7493 performEnableScreen();
7497 case APP_FREEZE_TIMEOUT: {
7498 synchronized (mWindowMap) {
7499 Slog.w(TAG, "App freeze timeout expired.");
7500 final int numStacks = mStackIdToStack.size();
7501 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
7502 final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
7503 final ArrayList<Task> tasks = stack.getTasks();
7504 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
7505 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
7506 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
7507 AppWindowToken tok = tokens.get(tokenNdx);
7508 if (tok.mAppAnimator.freezingScreen) {
7509 Slog.w(TAG, "Force clearing freeze: " + tok);
7510 unsetAppFreezingScreenLocked(tok, true, true);
7519 case CLIENT_FREEZE_TIMEOUT: {
7520 synchronized (mWindowMap) {
7521 if (mClientFreezingScreen) {
7522 mClientFreezingScreen = false;
7523 mLastFinishedFreezeSource = "client-timeout";
7524 stopFreezingDisplayLocked();
7530 case SEND_NEW_CONFIGURATION: {
7531 removeMessages(SEND_NEW_CONFIGURATION);
7532 sendNewConfiguration();
7536 case REPORT_WINDOWS_CHANGE: {
7537 if (mWindowsChanged) {
7538 synchronized (mWindowMap) {
7539 mWindowsChanged = false;
7541 notifyWindowsChanged();
7546 case DRAG_START_TIMEOUT: {
7547 IBinder win = (IBinder)msg.obj;
7549 Slog.w(TAG, "Timeout starting drag by win " + win);
7551 synchronized (mWindowMap) {
7552 // !!! TODO: ANR the app that has failed to start the drag in time
7553 if (mDragState != null) {
7554 mDragState.unregister();
7555 mInputMonitor.updateInputWindowsLw(true /*force*/);
7563 case DRAG_END_TIMEOUT: {
7564 IBinder win = (IBinder)msg.obj;
7566 Slog.w(TAG, "Timeout ending drag to win " + win);
7568 synchronized (mWindowMap) {
7569 // !!! TODO: ANR the drag-receiving app
7570 if (mDragState != null) {
7571 mDragState.mDragResult = false;
7572 mDragState.endDragLw();
7578 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
7579 notifyHardKeyboardStatusChange();
7583 case BOOT_TIMEOUT: {
7584 performBootTimeout();
7588 case WAITING_FOR_DRAWN_TIMEOUT: {
7589 Runnable callback = null;
7590 synchronized (mWindowMap) {
7591 Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
7592 mWaitingForDrawn.clear();
7593 callback = mWaitingForDrawnCallback;
7594 mWaitingForDrawnCallback = null;
7596 if (callback != null) {
7602 case SHOW_STRICT_MODE_VIOLATION: {
7603 showStrictModeViolation(msg.arg1, msg.arg2);
7607 case DO_ANIMATION_CALLBACK: {
7609 ((IRemoteCallback)msg.obj).sendResult(null);
7610 } catch (RemoteException e) {
7615 case DO_DISPLAY_ADDED:
7616 handleDisplayAdded(msg.arg1);
7619 case DO_DISPLAY_REMOVED:
7620 synchronized (mWindowMap) {
7621 handleDisplayRemovedLocked(msg.arg1);
7625 case DO_DISPLAY_CHANGED:
7626 synchronized (mWindowMap) {
7627 handleDisplayChangedLocked(msg.arg1);
7631 case TAP_OUTSIDE_STACK: {
7633 synchronized (mWindowMap) {
7634 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
7638 mActivityManager.setFocusedStack(stackId);
7639 } catch (RemoteException e) {
7644 case NOTIFY_ACTIVITY_DRAWN:
7646 mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
7647 } catch (RemoteException e) {
7650 case ALL_WINDOWS_DRAWN: {
7652 synchronized (mWindowMap) {
7653 callback = mWaitingForDrawnCallback;
7654 mWaitingForDrawnCallback = null;
7656 if (callback != null) {
7660 case NEW_ANIMATOR_SCALE: {
7661 float scale = getCurrentAnimatorScale();
7662 ValueAnimator.setDurationScale(scale);
7663 Session session = (Session)msg.obj;
7664 if (session != null) {
7666 session.mCallback.onAnimatorScaleChanged(scale);
7667 } catch (RemoteException e) {
7670 ArrayList<IWindowSessionCallback> callbacks
7671 = new ArrayList<IWindowSessionCallback>();
7672 synchronized (mWindowMap) {
7673 for (int i=0; i<mSessions.size(); i++) {
7674 callbacks.add(mSessions.valueAt(i).mCallback);
7678 for (int i=0; i<callbacks.size(); i++) {
7680 callbacks.get(i).onAnimatorScaleChanged(scale);
7681 } catch (RemoteException e) {
7688 if (DEBUG_WINDOW_TRACE) {
7689 Slog.v(TAG, "handleMessage: exit");
7694 // -------------------------------------------------------------
7695 // IWindowManager API
7696 // -------------------------------------------------------------
7699 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
7700 IInputContext inputContext) {
7701 if (client == null) throw new IllegalArgumentException("null client");
7702 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
7703 Session session = new Session(this, callback, client, inputContext);
7708 public boolean inputMethodClientHasFocus(IInputMethodClient client) {
7709 synchronized (mWindowMap) {
7710 // The focus for the client is the window immediately below
7711 // where we would place the input method window.
7712 int idx = findDesiredInputMethodWindowIndexLocked(false);
7714 // TODO(multidisplay): IMEs are only supported on the default display.
7715 WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
7716 if (DEBUG_INPUT_METHOD) {
7717 Slog.i(TAG, "Desired input method target: " + imFocus);
7718 Slog.i(TAG, "Current focus: " + mCurrentFocus);
7719 Slog.i(TAG, "Last focus: " + mLastFocus);
7721 if (imFocus != null) {
7722 // This may be a starting window, in which case we still want
7723 // to count it as okay.
7724 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
7725 && imFocus.mAppToken != null) {
7726 // The client has definitely started, so it really should
7727 // have a window in this app token. Let's look for it.
7728 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
7729 WindowState w = imFocus.mAppToken.windows.get(i);
7731 Log.i(TAG, "Switching to real app window: " + w);
7737 if (DEBUG_INPUT_METHOD) {
7738 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient);
7739 if (imFocus.mSession.mClient != null) {
7740 Slog.i(TAG, "IM target client binder: "
7741 + imFocus.mSession.mClient.asBinder());
7742 Slog.i(TAG, "Requesting client binder: " + client.asBinder());
7745 if (imFocus.mSession.mClient != null &&
7746 imFocus.mSession.mClient.asBinder() == client.asBinder()) {
7752 // Okay, how about this... what is the current focus?
7753 // It seems in some cases we may not have moved the IM
7754 // target window, such as when it was in a pop-up window,
7755 // so let's also look at the current focus. (An example:
7756 // go to Gmail, start searching so the keyboard goes up,
7757 // press home. Sometimes the IME won't go down.)
7758 // Would be nice to fix this more correctly, but it's
7759 // way at the end of a release, and this should be good enough.
7760 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
7761 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
7769 public void getInitialDisplaySize(int displayId, Point size) {
7770 synchronized (mWindowMap) {
7771 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7772 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7773 synchronized(displayContent.mDisplaySizeLock) {
7774 size.x = displayContent.mInitialDisplayWidth;
7775 size.y = displayContent.mInitialDisplayHeight;
7782 public void getBaseDisplaySize(int displayId, Point size) {
7783 synchronized (mWindowMap) {
7784 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7785 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7786 synchronized(displayContent.mDisplaySizeLock) {
7787 size.x = displayContent.mBaseDisplayWidth;
7788 size.y = displayContent.mBaseDisplayHeight;
7795 public void setForcedDisplaySize(int displayId, int width, int height) {
7796 if (mContext.checkCallingOrSelfPermission(
7797 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7798 PackageManager.PERMISSION_GRANTED) {
7799 throw new SecurityException("Must hold permission " +
7800 android.Manifest.permission.WRITE_SECURE_SETTINGS);
7802 if (displayId != Display.DEFAULT_DISPLAY) {
7803 throw new IllegalArgumentException("Can only set the default display");
7805 final long ident = Binder.clearCallingIdentity();
7807 synchronized(mWindowMap) {
7808 // Set some sort of reasonable bounds on the size of the display that we
7809 // will try to emulate.
7810 final int MIN_WIDTH = 200;
7811 final int MIN_HEIGHT = 200;
7812 final int MAX_SCALE = 2;
7813 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7814 if (displayContent != null) {
7815 width = Math.min(Math.max(width, MIN_WIDTH),
7816 displayContent.mInitialDisplayWidth * MAX_SCALE);
7817 height = Math.min(Math.max(height, MIN_HEIGHT),
7818 displayContent.mInitialDisplayHeight * MAX_SCALE);
7819 setForcedDisplaySizeLocked(displayContent, width, height);
7820 Settings.Global.putString(mContext.getContentResolver(),
7821 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
7825 Binder.restoreCallingIdentity(ident);
7829 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
7830 String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
7831 Settings.Global.DISPLAY_SIZE_FORCED);
7832 if (sizeStr == null || sizeStr.length() == 0) {
7833 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
7835 if (sizeStr != null && sizeStr.length() > 0) {
7836 final int pos = sizeStr.indexOf(',');
7837 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
7840 width = Integer.parseInt(sizeStr.substring(0, pos));
7841 height = Integer.parseInt(sizeStr.substring(pos+1));
7842 synchronized(displayContent.mDisplaySizeLock) {
7843 if (displayContent.mBaseDisplayWidth != width
7844 || displayContent.mBaseDisplayHeight != height) {
7845 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
7846 displayContent.mBaseDisplayWidth = width;
7847 displayContent.mBaseDisplayHeight = height;
7850 } catch (NumberFormatException ex) {
7854 String densityStr = Settings.Global.getString(mContext.getContentResolver(),
7855 Settings.Global.DISPLAY_DENSITY_FORCED);
7856 if (densityStr == null || densityStr.length() == 0) {
7857 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
7859 if (densityStr != null && densityStr.length() > 0) {
7862 density = Integer.parseInt(densityStr);
7863 synchronized(displayContent.mDisplaySizeLock) {
7864 if (displayContent.mBaseDisplayDensity != density) {
7865 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
7866 displayContent.mBaseDisplayDensity = density;
7869 } catch (NumberFormatException ex) {
7874 // displayContent must not be null
7875 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
7876 Slog.i(TAG, "Using new display size: " + width + "x" + height);
7878 synchronized(displayContent.mDisplaySizeLock) {
7879 displayContent.mBaseDisplayWidth = width;
7880 displayContent.mBaseDisplayHeight = height;
7882 reconfigureDisplayLocked(displayContent);
7886 public void clearForcedDisplaySize(int displayId) {
7887 if (mContext.checkCallingOrSelfPermission(
7888 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7889 PackageManager.PERMISSION_GRANTED) {
7890 throw new SecurityException("Must hold permission " +
7891 android.Manifest.permission.WRITE_SECURE_SETTINGS);
7893 if (displayId != Display.DEFAULT_DISPLAY) {
7894 throw new IllegalArgumentException("Can only set the default display");
7896 final long ident = Binder.clearCallingIdentity();
7898 synchronized(mWindowMap) {
7899 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7900 if (displayContent != null) {
7901 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
7902 displayContent.mInitialDisplayHeight);
7903 Settings.Global.putString(mContext.getContentResolver(),
7904 Settings.Global.DISPLAY_SIZE_FORCED, "");
7908 Binder.restoreCallingIdentity(ident);
7913 public int getInitialDisplayDensity(int displayId) {
7914 synchronized (mWindowMap) {
7915 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7916 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7917 synchronized(displayContent.mDisplaySizeLock) {
7918 return displayContent.mInitialDisplayDensity;
7926 public int getBaseDisplayDensity(int displayId) {
7927 synchronized (mWindowMap) {
7928 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7929 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7930 synchronized(displayContent.mDisplaySizeLock) {
7931 return displayContent.mBaseDisplayDensity;
7939 public void setForcedDisplayDensity(int displayId, int density) {
7940 if (mContext.checkCallingOrSelfPermission(
7941 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7942 PackageManager.PERMISSION_GRANTED) {
7943 throw new SecurityException("Must hold permission " +
7944 android.Manifest.permission.WRITE_SECURE_SETTINGS);
7946 if (displayId != Display.DEFAULT_DISPLAY) {
7947 throw new IllegalArgumentException("Can only set the default display");
7949 final long ident = Binder.clearCallingIdentity();
7951 synchronized(mWindowMap) {
7952 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7953 if (displayContent != null) {
7954 setForcedDisplayDensityLocked(displayContent, density);
7955 Settings.Global.putString(mContext.getContentResolver(),
7956 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
7960 Binder.restoreCallingIdentity(ident);
7964 // displayContent must not be null
7965 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
7966 Slog.i(TAG, "Using new display density: " + density);
7968 synchronized(displayContent.mDisplaySizeLock) {
7969 displayContent.mBaseDisplayDensity = density;
7971 reconfigureDisplayLocked(displayContent);
7975 public void clearForcedDisplayDensity(int displayId) {
7976 if (mContext.checkCallingOrSelfPermission(
7977 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7978 PackageManager.PERMISSION_GRANTED) {
7979 throw new SecurityException("Must hold permission " +
7980 android.Manifest.permission.WRITE_SECURE_SETTINGS);
7982 if (displayId != Display.DEFAULT_DISPLAY) {
7983 throw new IllegalArgumentException("Can only set the default display");
7985 final long ident = Binder.clearCallingIdentity();
7987 synchronized(mWindowMap) {
7988 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7989 if (displayContent != null) {
7990 setForcedDisplayDensityLocked(displayContent,
7991 displayContent.mInitialDisplayDensity);
7992 Settings.Global.putString(mContext.getContentResolver(),
7993 Settings.Global.DISPLAY_DENSITY_FORCED, "");
7997 Binder.restoreCallingIdentity(ident);
8001 // displayContent must not be null
8002 private void reconfigureDisplayLocked(DisplayContent displayContent) {
8003 // TODO: Multidisplay: for now only use with default display.
8004 configureDisplayPolicyLocked(displayContent);
8005 displayContent.layoutNeeded = true;
8007 boolean configChanged = updateOrientationFromAppTokensLocked(false);
8008 mTempConfiguration.setToDefaults();
8009 mTempConfiguration.fontScale = mCurConfiguration.fontScale;
8010 if (computeScreenConfigurationLocked(mTempConfiguration)) {
8011 if (mCurConfiguration.diff(mTempConfiguration) != 0) {
8012 configChanged = true;
8016 if (configChanged) {
8017 mWaitingForConfig = true;
8018 startFreezingDisplayLocked(false, 0, 0);
8019 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
8022 performLayoutAndPlaceSurfacesLocked();
8025 private void configureDisplayPolicyLocked(DisplayContent displayContent) {
8026 mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
8027 displayContent.mBaseDisplayWidth,
8028 displayContent.mBaseDisplayHeight,
8029 displayContent.mBaseDisplayDensity);
8031 DisplayInfo displayInfo = displayContent.getDisplayInfo();
8032 mPolicy.setDisplayOverscan(displayContent.getDisplay(),
8033 displayInfo.overscanLeft, displayInfo.overscanTop,
8034 displayInfo.overscanRight, displayInfo.overscanBottom);
8038 public void setOverscan(int displayId, int left, int top, int right, int bottom) {
8039 if (mContext.checkCallingOrSelfPermission(
8040 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8041 PackageManager.PERMISSION_GRANTED) {
8042 throw new SecurityException("Must hold permission " +
8043 android.Manifest.permission.WRITE_SECURE_SETTINGS);
8045 final long ident = Binder.clearCallingIdentity();
8047 synchronized(mWindowMap) {
8048 DisplayContent displayContent = getDisplayContentLocked(displayId);
8049 if (displayContent != null) {
8050 setOverscanLocked(displayContent, left, top, right, bottom);
8054 Binder.restoreCallingIdentity(ident);
8058 private void setOverscanLocked(DisplayContent displayContent,
8059 int left, int top, int right, int bottom) {
8060 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
8061 synchronized (displayContent.mDisplaySizeLock) {
8062 displayInfo.overscanLeft = left;
8063 displayInfo.overscanTop = top;
8064 displayInfo.overscanRight = right;
8065 displayInfo.overscanBottom = bottom;
8068 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom);
8069 mDisplaySettings.writeSettingsLocked();
8071 reconfigureDisplayLocked(displayContent);
8074 // -------------------------------------------------------------
8076 // -------------------------------------------------------------
8078 final WindowState windowForClientLocked(Session session, IWindow client,
8079 boolean throwOnError) {
8080 return windowForClientLocked(session, client.asBinder(), throwOnError);
8083 final WindowState windowForClientLocked(Session session, IBinder client,
8084 boolean throwOnError) {
8085 WindowState win = mWindowMap.get(client);
8086 if (localLOGV) Slog.v(
8087 TAG, "Looking up client " + client + ": " + win);
8089 RuntimeException ex = new IllegalArgumentException(
8090 "Requested window " + client + " does not exist");
8094 Slog.w(TAG, "Failed looking up window", ex);
8097 if (session != null && win.mSession != session) {
8098 RuntimeException ex = new IllegalArgumentException(
8099 "Requested window " + client + " is in session " +
8100 win.mSession + ", not " + session);
8104 Slog.w(TAG, "Failed looking up window", ex);
8111 final void rebuildAppWindowListLocked() {
8112 rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
8115 private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
8116 final WindowList windows = displayContent.getWindowList();
8117 int NW = windows.size();
8122 if (mRebuildTmp.length < NW) {
8123 mRebuildTmp = new WindowState[NW+10];
8126 // First remove all existing app windows.
8129 WindowState w = windows.get(i);
8130 if (w.mAppToken != null) {
8131 WindowState win = windows.remove(i);
8132 win.mRebuilding = true;
8133 mRebuildTmp[numRemoved] = win;
8134 mWindowsChanged = true;
8135 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win);
8139 } else if (lastBelow == i-1) {
8140 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8147 // Keep whatever windows were below the app windows still below,
8148 // by skipping them.
8152 // First add all of the exiting app tokens... these are no longer
8153 // in the main app list, but still have windows shown. We put them
8154 // in the back because now that the animation is over we no longer
8155 // will care about them.
8156 final ArrayList<TaskStack> stacks = displayContent.getStacks();
8157 final int numStacks = stacks.size();
8158 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8159 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens;
8160 int NT = exitingAppTokens.size();
8161 for (int j = 0; j < NT; j++) {
8162 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
8166 // And add in the still active app tokens in Z order.
8167 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8168 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
8169 final int numTasks = tasks.size();
8170 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
8171 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8172 final int numTokens = tokens.size();
8173 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
8174 final AppWindowToken wtoken = tokens.get(tokenNdx);
8175 if (wtoken.mDeferRemoval) {
8178 i = reAddAppWindowsLocked(displayContent, i, wtoken);
8184 if (i != numRemoved) {
8185 Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " +
8186 numRemoved + " windows but added " + i,
8187 new RuntimeException("here").fillInStackTrace());
8188 for (i=0; i<numRemoved; i++) {
8189 WindowState ws = mRebuildTmp[i];
8190 if (ws.mRebuilding) {
8191 StringWriter sw = new StringWriter();
8192 PrintWriter pw = new FastPrintWriter(sw, false, 1024);
8193 ws.dump(pw, "", true);
8195 Slog.w(TAG, "This window was lost: " + ws);
8196 Slog.w(TAG, sw.toString());
8197 ws.mWinAnimator.destroySurfaceLocked();
8200 Slog.w(TAG, "Current app token list:");
8201 dumpAppTokensLocked();
8202 Slog.w(TAG, "Final window list:");
8203 dumpWindowsLocked();
8207 private final void assignLayersLocked(WindowList windows) {
8208 int N = windows.size();
8209 int curBaseLayer = 0;
8213 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows,
8214 new RuntimeException("here").fillInStackTrace());
8216 boolean anyLayerChanged = false;
8218 for (i=0; i<N; i++) {
8219 final WindowState w = windows.get(i);
8220 final WindowStateAnimator winAnimator = w.mWinAnimator;
8221 boolean layerChanged = false;
8222 int oldLayer = w.mLayer;
8223 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
8224 || (i > 0 && w.mIsWallpaper)) {
8225 curLayer += WINDOW_LAYER_MULTIPLIER;
8226 w.mLayer = curLayer;
8228 curBaseLayer = curLayer = w.mBaseLayer;
8229 w.mLayer = curLayer;
8231 if (w.mLayer != oldLayer) {
8232 layerChanged = true;
8233 anyLayerChanged = true;
8235 final AppWindowToken wtoken = w.mAppToken;
8236 oldLayer = winAnimator.mAnimLayer;
8237 if (w.mTargetAppToken != null) {
8238 winAnimator.mAnimLayer =
8239 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
8240 } else if (wtoken != null) {
8241 winAnimator.mAnimLayer =
8242 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment;
8244 winAnimator.mAnimLayer = w.mLayer;
8246 if (w.mIsImWindow) {
8247 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
8248 } else if (w.mIsWallpaper) {
8249 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
8251 if (winAnimator.mAnimLayer != oldLayer) {
8252 layerChanged = true;
8253 anyLayerChanged = true;
8255 if (layerChanged && w.getStack().isDimming(winAnimator)) {
8256 // Force an animation pass just to update the mDimLayer layer.
8257 scheduleAnimationLocked();
8259 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
8260 + "mBase=" + w.mBaseLayer
8261 + " mLayer=" + w.mLayer
8263 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment)
8264 + " =mAnimLayer=" + winAnimator.mAnimLayer);
8265 //System.out.println(
8266 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
8269 //TODO (multidisplay): Magnification is supported only for the default display.
8270 if (mAccessibilityController != null && anyLayerChanged
8271 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
8272 mAccessibilityController.onWindowLayersChangedLocked();
8276 private final void performLayoutAndPlaceSurfacesLocked() {
8279 mTraversalScheduled = false;
8280 performLayoutAndPlaceSurfacesLockedLoop();
8281 mH.removeMessages(H.DO_TRAVERSAL);
8283 } while (mTraversalScheduled && loopCount > 0);
8284 mInnerFields.mWallpaperActionPending = false;
8287 private boolean mInLayout = false;
8288 private final void performLayoutAndPlaceSurfacesLockedLoop() {
8291 throw new RuntimeException("Recursive call!");
8293 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
8294 + Debug.getCallers(3));
8298 if (mWaitingForConfig) {
8299 // Our configuration has changed (most likely rotation), but we
8300 // don't yet have the complete configuration to report to
8301 // applications. Don't do any window layout until we have it.
8305 if (!mDisplayReady) {
8306 // Not yet initialized, nothing to do.
8310 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
8312 boolean recoveringMemory = false;
8315 if (mForceRemoves != null) {
8316 recoveringMemory = true;
8317 // Wait a little bit for things to settle down, and off we go.
8318 for (int i=0; i<mForceRemoves.size(); i++) {
8319 WindowState ws = mForceRemoves.get(i);
8320 Slog.i(TAG, "Force removing: " + ws);
8321 removeWindowInnerLocked(ws.mSession, ws);
8323 mForceRemoves = null;
8324 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
8325 Object tmp = new Object();
8326 synchronized (tmp) {
8329 } catch (InterruptedException e) {
8333 } catch (RuntimeException e) {
8334 Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
8338 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
8342 if (needsLayout()) {
8343 if (++mLayoutRepeatCount < 6) {
8344 requestTraversalLocked();
8346 Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
8347 mLayoutRepeatCount = 0;
8350 mLayoutRepeatCount = 0;
8353 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
8354 mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
8355 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE);
8357 } catch (RuntimeException e) {
8359 Log.wtf(TAG, "Unhandled exception while laying out windows", e);
8362 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
8365 private final void performLayoutLockedInner(final DisplayContent displayContent,
8366 boolean initial, boolean updateInputWindows) {
8367 if (!displayContent.layoutNeeded) {
8370 displayContent.layoutNeeded = false;
8371 WindowList windows = displayContent.getWindowList();
8372 boolean isDefaultDisplay = displayContent.isDefaultDisplay;
8374 DisplayInfo displayInfo = displayContent.getDisplayInfo();
8375 final int dw = displayInfo.logicalWidth;
8376 final int dh = displayInfo.logicalHeight;
8378 final int NFW = mFakeWindows.size();
8379 for (int i=0; i<NFW; i++) {
8380 mFakeWindows.get(i).layout(dw, dh);
8383 final int N = windows.size();
8387 Slog.v(TAG, "-------------------------------------");
8388 Slog.v(TAG, "performLayout: needed="
8389 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
8392 WindowStateAnimator universeBackground = null;
8394 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
8395 if (isDefaultDisplay) {
8396 // Not needed on non-default displays.
8397 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw();
8398 mScreenRect.set(0, 0, dw, dh);
8401 mPolicy.getContentRectLw(mTmpContentRect);
8402 displayContent.resize(mTmpContentRect);
8404 int seq = mLayoutSeq+1;
8405 if (seq < 0) seq = 0;
8408 boolean behindDream = false;
8410 // First perform layout of any root windows (not attached
8411 // to another window).
8412 int topAttached = -1;
8413 for (i = N-1; i >= 0; i--) {
8414 final WindowState win = windows.get(i);
8416 // Don't do layout of a window if it is not visible, or
8417 // soon won't be visible, to avoid wasting time and funky
8418 // changes while a window is animating away.
8419 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
8420 || win.isGoneForLayoutLw();
8422 if (DEBUG_LAYOUT && !win.mLayoutAttached) {
8423 Slog.v(TAG, "1ST PASS " + win
8424 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
8425 + " mLayoutAttached=" + win.mLayoutAttached
8426 + " screen changed=" + win.isConfigChanged());
8427 final AppWindowToken atoken = win.mAppToken;
8428 if (gone) Slog.v(TAG, " GONE: mViewVisibility="
8429 + win.mViewVisibility + " mRelayoutCalled="
8430 + win.mRelayoutCalled + " hidden="
8431 + win.mRootToken.hidden + " hiddenRequested="
8432 + (atoken != null && atoken.hiddenRequested)
8433 + " mAttachedHidden=" + win.mAttachedHidden);
8434 else Slog.v(TAG, " VIS: mViewVisibility="
8435 + win.mViewVisibility + " mRelayoutCalled="
8436 + win.mRelayoutCalled + " hidden="
8437 + win.mRootToken.hidden + " hiddenRequested="
8438 + (atoken != null && atoken.hiddenRequested)
8439 + " mAttachedHidden=" + win.mAttachedHidden);
8442 // If this view is GONE, then skip it -- keep the current
8443 // frame, and let the caller know so they can ignore it
8444 // if they want. (We do the normal layout for INVISIBLE
8445 // windows, since that means "perform layout as normal,
8446 // just don't display").
8447 if (!gone || !win.mHaveFrame || win.mLayoutNeeded
8448 || ((win.isConfigChanged() || win.setInsetsChanged()) &&
8449 ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
8450 win.mAppToken != null && win.mAppToken.layoutConfigChanges))
8451 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8452 if (!win.mLayoutAttached) {
8454 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8455 win.mContentChanged = false;
8457 if (win.mAttrs.type == TYPE_DREAM) {
8458 // Don't layout windows behind a dream, so that if it
8459 // does stuff like hide the status bar we won't get a
8460 // bad transition when it goes away.
8463 win.mLayoutNeeded = false;
8465 mPolicy.layoutWindowLw(win, null);
8466 win.mLayoutSeq = seq;
8467 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame="
8468 + win.mFrame + " mContainingFrame="
8469 + win.mContainingFrame + " mDisplayFrame="
8470 + win.mDisplayFrame);
8472 if (topAttached < 0) topAttached = i;
8475 if (win.mViewVisibility == View.VISIBLE
8476 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
8477 && universeBackground == null) {
8478 universeBackground = win.mWinAnimator;
8482 if (mAnimator.mUniverseBackground != universeBackground) {
8483 mFocusMayChange = true;
8484 mAnimator.mUniverseBackground = universeBackground;
8487 boolean attachedBehindDream = false;
8489 // Now perform layout of attached windows, which usually
8490 // depend on the position of the window they are attached to.
8491 // XXX does not deal with windows that are attached to windows
8492 // that are themselves attached.
8493 for (i = topAttached; i >= 0; i--) {
8494 final WindowState win = windows.get(i);
8496 if (win.mLayoutAttached) {
8497 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
8498 + " mHaveFrame=" + win.mHaveFrame
8499 + " mViewVisibility=" + win.mViewVisibility
8500 + " mRelayoutCalled=" + win.mRelayoutCalled);
8501 // If this view is GONE, then skip it -- keep the current
8502 // frame, and let the caller know so they can ignore it
8503 // if they want. (We do the normal layout for INVISIBLE
8504 // windows, since that means "perform layout as normal,
8505 // just don't display").
8506 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
8509 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
8510 || !win.mHaveFrame || win.mLayoutNeeded) {
8512 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8513 win.mContentChanged = false;
8515 win.mLayoutNeeded = false;
8517 mPolicy.layoutWindowLw(win, win.mAttachedWindow);
8518 win.mLayoutSeq = seq;
8519 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame="
8520 + win.mFrame + " mContainingFrame="
8521 + win.mContainingFrame + " mDisplayFrame="
8522 + win.mDisplayFrame);
8524 } else if (win.mAttrs.type == TYPE_DREAM) {
8525 // Don't layout windows behind a dream, so that if it
8526 // does stuff like hide the status bar we won't get a
8527 // bad transition when it goes away.
8528 attachedBehindDream = behindDream;
8532 // Window frames may have changed. Tell the input dispatcher about it.
8533 mInputMonitor.setUpdateInputWindowsNeededLw();
8534 if (updateInputWindows) {
8535 mInputMonitor.updateInputWindowsLw(false /*force*/);
8538 mPolicy.finishLayoutLw();
8541 void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
8542 // If the screen is currently frozen or off, then keep
8543 // it frozen/off until this window draws at its new
8545 if (!okToDisplay()) {
8546 if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w);
8547 w.mOrientationChanging = true;
8548 w.mLastFreezeDuration = 0;
8549 mInnerFields.mOrientationChangeComplete = false;
8550 if (!mWindowsFreezingScreen) {
8551 mWindowsFreezingScreen = true;
8552 // XXX should probably keep timeout from
8553 // when we first froze the display.
8554 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8555 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
8556 WINDOW_FREEZE_TIMEOUT_DURATION);
8562 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8563 * @param windows List of windows on default display.
8564 * @return bitmap indicating if another pass through layout must be made.
8566 public int handleAppTransitionReadyLocked(WindowList windows) {
8569 int NN = mOpeningApps.size();
8570 boolean goodToGo = true;
8571 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8572 "Checking " + NN + " opening apps (frozen="
8573 + mDisplayFrozen + " timeout="
8574 + mAppTransition.isTimeout() + ")...");
8575 if (!mDisplayFrozen && !mAppTransition.isTimeout()) {
8576 // If the display isn't frozen, wait to do anything until
8577 // all of the apps are ready. Otherwise just go because
8578 // we'll unfreeze the display when everyone is ready.
8579 for (i=0; i<NN && goodToGo; i++) {
8580 AppWindowToken wtoken = mOpeningApps.valueAt(i);
8581 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8582 "Check opening app=" + wtoken + ": allDrawn="
8583 + wtoken.allDrawn + " startingDisplayed="
8584 + wtoken.startingDisplayed + " startingMoved="
8585 + wtoken.startingMoved);
8586 if (!wtoken.allDrawn && !wtoken.startingDisplayed
8587 && !wtoken.startingMoved) {
8593 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
8594 int transit = mAppTransition.getAppTransition();
8595 if (mSkipAppTransitionAnimation) {
8596 transit = AppTransition.TRANSIT_UNSET;
8598 mAppTransition.goodToGo();
8599 mStartingIconInTransition = false;
8600 mSkipAppTransitionAnimation = false;
8602 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
8604 rebuildAppWindowListLocked();
8606 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
8607 WindowState oldWallpaper =
8608 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
8609 && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
8610 ? null : mWallpaperTarget;
8612 mInnerFields.mWallpaperMayChange = false;
8614 // The top-most window will supply the layout params,
8615 // and we will determine it below.
8616 LayoutParams animLp = null;
8617 int bestAnimLayer = -1;
8618 boolean fullscreenAnim = false;
8619 boolean voiceInteraction = false;
8621 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8622 "New wallpaper target=" + mWallpaperTarget
8623 + ", oldWallpaper=" + oldWallpaper
8624 + ", lower target=" + mLowerWallpaperTarget
8625 + ", upper target=" + mUpperWallpaperTarget);
8627 boolean openingAppHasWallpaper = false;
8628 boolean closingAppHasWallpaper = false;
8629 final AppWindowToken lowerWallpaperAppToken;
8630 final AppWindowToken upperWallpaperAppToken;
8631 if (mLowerWallpaperTarget == null) {
8632 lowerWallpaperAppToken = upperWallpaperAppToken = null;
8634 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
8635 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
8638 // Do a first pass through the tokens for two
8640 // (1) Determine if both the closing and opening
8641 // app token sets are wallpaper targets, in which
8642 // case special animations are needed
8643 // (since the wallpaper needs to stay static
8645 // (2) Find the layout params of the top-most
8646 // application window in the tokens, which is
8647 // what will control the animation theme.
8648 final int NC = mClosingApps.size();
8649 NN = NC + mOpeningApps.size();
8650 for (i=0; i<NN; i++) {
8651 final AppWindowToken wtoken;
8653 wtoken = mClosingApps.valueAt(i);
8654 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8655 closingAppHasWallpaper = true;
8658 wtoken = mOpeningApps.valueAt(i - NC);
8659 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8660 openingAppHasWallpaper = true;
8664 voiceInteraction |= wtoken.voiceInteraction;
8666 if (wtoken.appFullscreen) {
8667 WindowState ws = wtoken.findMainWindow();
8670 bestAnimLayer = ws.mLayer;
8671 fullscreenAnim = true;
8673 } else if (!fullscreenAnim) {
8674 WindowState ws = wtoken.findMainWindow();
8676 if (ws.mLayer > bestAnimLayer) {
8678 bestAnimLayer = ws.mLayer;
8684 mAnimateWallpaperWithTarget = false;
8685 if (closingAppHasWallpaper && openingAppHasWallpaper) {
8686 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
8688 case AppTransition.TRANSIT_ACTIVITY_OPEN:
8689 case AppTransition.TRANSIT_TASK_OPEN:
8690 case AppTransition.TRANSIT_TASK_TO_FRONT:
8691 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
8693 case AppTransition.TRANSIT_ACTIVITY_CLOSE:
8694 case AppTransition.TRANSIT_TASK_CLOSE:
8695 case AppTransition.TRANSIT_TASK_TO_BACK:
8696 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
8699 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
8700 } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
8701 && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
8702 // We are transitioning from an activity with
8703 // a wallpaper to one without.
8704 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
8705 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8706 "New transit away from wallpaper: " + transit);
8707 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
8708 // We are transitioning from an activity without
8709 // a wallpaper to now showing the wallpaper
8710 transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
8711 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8712 "New transit into wallpaper: " + transit);
8714 mAnimateWallpaperWithTarget = true;
8717 // If all closing windows are obscured, then there is
8718 // no need to do an animation. This is the case, for
8719 // example, when this transition is being done behind
8721 if (!mPolicy.allowAppAnimationsLw()) {
8722 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8723 "Animations disallowed by keyguard or dream.");
8727 AppWindowToken topOpeningApp = null;
8728 int topOpeningLayer = 0;
8730 NN = mOpeningApps.size();
8731 for (i=0; i<NN; i++) {
8732 AppWindowToken wtoken = mOpeningApps.valueAt(i);
8733 final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
8734 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
8735 appAnimator.clearThumbnail();
8736 wtoken.inPendingTransaction = false;
8737 appAnimator.animation = null;
8738 setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction);
8739 wtoken.updateReportedVisibilityLocked();
8740 wtoken.waitingToShow = false;
8742 appAnimator.mAllAppWinAnimators.clear();
8743 final int N = wtoken.allAppWindows.size();
8744 for (int j = 0; j < N; j++) {
8745 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
8747 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
8749 if (animLp != null) {
8751 for (int j=0; j<wtoken.windows.size(); j++) {
8752 WindowState win = wtoken.windows.get(j);
8753 if (win.mWinAnimator.mAnimLayer > layer) {
8754 layer = win.mWinAnimator.mAnimLayer;
8757 if (topOpeningApp == null || layer > topOpeningLayer) {
8758 topOpeningApp = wtoken;
8759 topOpeningLayer = layer;
8763 NN = mClosingApps.size();
8764 for (i=0; i<NN; i++) {
8765 AppWindowToken wtoken = mClosingApps.valueAt(i);
8766 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
8767 wtoken.mAppAnimator.clearThumbnail();
8768 wtoken.inPendingTransaction = false;
8769 wtoken.mAppAnimator.animation = null;
8770 setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction);
8771 wtoken.updateReportedVisibilityLocked();
8772 wtoken.waitingToHide = false;
8773 // Force the allDrawn flag, because we want to start
8774 // this guy's animations regardless of whether it's
8776 wtoken.allDrawn = true;
8777 wtoken.deferClearAllDrawn = false;
8780 boolean useAlternateThumbnailAnimation = true;
8781 AppWindowAnimator appAnimator =
8782 topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
8783 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
8784 if (!useAlternateThumbnailAnimation && nextAppTransitionThumbnail != null
8785 && appAnimator != null && appAnimator.animation != null) {
8786 // This thumbnail animation is very special, we need to have
8787 // an extra surface with the thumbnail included with the animation.
8788 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
8789 nextAppTransitionThumbnail.getHeight());
8791 // TODO(multi-display): support other displays
8792 final DisplayContent displayContent = getDefaultDisplayContentLocked();
8793 final Display display = displayContent.getDisplay();
8794 SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
8796 dirty.width(), dirty.height(),
8797 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
8798 surfaceControl.setLayerStack(display.getLayerStack());
8799 appAnimator.thumbnail = surfaceControl;
8800 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE");
8801 Surface drawSurface = new Surface();
8802 drawSurface.copyFrom(surfaceControl);
8803 Canvas c = drawSurface.lockCanvas(dirty);
8804 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
8805 drawSurface.unlockCanvasAndPost(c);
8806 drawSurface.release();
8807 appAnimator.thumbnailLayer = topOpeningLayer;
8808 DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
8809 Animation anim = mAppTransition.createThumbnailScaleAnimationLocked(
8810 displayInfo.appWidth, displayInfo.appHeight, transit);
8811 appAnimator.thumbnailAnimation = anim;
8812 anim.restrictDuration(MAX_ANIMATION_DURATION);
8813 anim.scaleCurrentDuration(getTransitionAnimationScaleLocked());
8814 Point p = new Point();
8815 mAppTransition.getStartingPoint(p);
8816 appAnimator.thumbnailX = p.x;
8817 appAnimator.thumbnailY = p.y;
8818 } catch (OutOfResourcesException e) {
8819 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
8820 + " h=" + dirty.height(), e);
8821 appAnimator.clearThumbnail();
8825 mAppTransition.postAnimationCallback();
8826 mAppTransition.clear();
8828 mOpeningApps.clear();
8829 mClosingApps.clear();
8831 // This has changed the visibility of windows, so perform
8832 // a new layout to get them all up-to-date.
8833 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
8834 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
8835 getDefaultDisplayContentLocked().layoutNeeded = true;
8837 // TODO(multidisplay): IMEs are only supported on the default display.
8838 if (windows == getDefaultWindowListLocked()
8839 && !moveInputMethodWindowsIfNeededLocked(true)) {
8840 assignLayersLocked(windows);
8842 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/);
8843 mFocusMayChange = false;
8850 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8851 * @return bitmap indicating if another pass through layout must be made.
8853 private int handleAnimatingStoppedAndTransitionLocked() {
8856 mAppTransition.setIdle();
8857 // Restore window app tokens to the ActivityManager views
8858 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks();
8859 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
8860 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
8861 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
8862 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8863 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
8864 tokens.get(tokenNdx).sendingToBottom = false;
8868 rebuildAppWindowListLocked();
8870 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
8871 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
8872 "Wallpaper layer changed: assigning layers + relayout");
8873 moveInputMethodWindowsIfNeededLocked(true);
8874 mInnerFields.mWallpaperMayChange = true;
8875 // Since the window list has been rebuilt, focus might
8876 // have to be recomputed since the actual order of windows
8877 // might have changed again.
8878 mFocusMayChange = true;
8883 private void updateResizingWindows(final WindowState w) {
8884 final WindowStateAnimator winAnimator = w.mWinAnimator;
8885 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
8886 w.setInsetsChanged();
8887 boolean configChanged = w.isConfigChanged();
8888 if (DEBUG_CONFIGURATION && configChanged) {
8889 Slog.v(TAG, "Win " + w + " config changed: "
8890 + mCurConfiguration);
8892 if (localLOGV) Slog.v(TAG, "Resizing " + w
8893 + ": configChanged=" + configChanged
8894 + " last=" + w.mLastFrame + " frame=" + w.mFrame);
8895 w.mLastFrame.set(w.mFrame);
8896 if (w.mContentInsetsChanged
8897 || w.mVisibleInsetsChanged
8898 || winAnimator.mSurfaceResized
8900 if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
8901 Slog.v(TAG, "Resize reasons for w=" + w + ": "
8902 + " contentInsetsChanged=" + w.mContentInsetsChanged
8903 + " " + w.mContentInsets.toShortString()
8904 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
8905 + " " + w.mVisibleInsets.toShortString()
8906 + " stableInsetsChanged=" + w.mStableInsetsChanged
8907 + " " + w.mStableInsets.toShortString()
8908 + " surfaceResized=" + winAnimator.mSurfaceResized
8909 + " configChanged=" + configChanged);
8912 w.mLastOverscanInsets.set(w.mOverscanInsets);
8913 w.mLastContentInsets.set(w.mContentInsets);
8914 w.mLastVisibleInsets.set(w.mVisibleInsets);
8915 w.mLastStableInsets.set(w.mStableInsets);
8916 makeWindowFreezingScreenIfNeededLocked(w);
8917 // If the orientation is changing, then we need to
8918 // hold off on unfreezing the display until this
8919 // window has been redrawn; to do that, we need
8920 // to go through the process of getting informed
8921 // by the application when it has finished drawing.
8922 if (w.mOrientationChanging) {
8923 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
8924 "Orientation start waiting for draw mDrawState=DRAW_PENDING in "
8925 + w + ", surface " + winAnimator.mSurfaceControl);
8926 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
8927 if (w.mAppToken != null) {
8928 w.mAppToken.allDrawn = false;
8929 w.mAppToken.deferClearAllDrawn = false;
8932 if (!mResizingWindows.contains(w)) {
8933 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
8934 "Resizing window " + w + " to " + winAnimator.mSurfaceW
8935 + "x" + winAnimator.mSurfaceH);
8936 mResizingWindows.add(w);
8938 } else if (w.mOrientationChanging) {
8939 if (w.isDrawnLw()) {
8940 if (DEBUG_ORIENTATION) Slog.v(TAG,
8941 "Orientation not waiting for draw in "
8942 + w + ", surface " + winAnimator.mSurfaceControl);
8943 w.mOrientationChanging = false;
8944 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
8945 - mDisplayFreezeTime);
8952 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8954 * @param w WindowState this method is applied to.
8955 * @param currentTime The time which animations use for calculating transitions.
8956 * @param innerDw Width of app window.
8957 * @param innerDh Height of app window.
8959 private void handleNotObscuredLocked(final WindowState w, final long currentTime,
8960 final int innerDw, final int innerDh) {
8961 final WindowManager.LayoutParams attrs = w.mAttrs;
8962 final int attrFlags = attrs.flags;
8963 final boolean canBeSeen = w.isDisplayedLw();
8964 final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
8966 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
8967 // This window completely covers everything behind it,
8968 // so we want to leave all of them as undimmed (for
8969 // performance reasons).
8970 mInnerFields.mObscured = true;
8973 if (w.mHasSurface) {
8974 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
8975 mInnerFields.mHoldScreen = w.mSession;
8977 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0
8978 && mInnerFields.mScreenBrightness < 0) {
8979 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness;
8981 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0
8982 && mInnerFields.mButtonBrightness < 0) {
8983 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
8985 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
8986 && mInnerFields.mUserActivityTimeout < 0) {
8987 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
8990 final int type = attrs.type;
8992 && (type == TYPE_SYSTEM_DIALOG
8993 || type == TYPE_RECENTS_OVERLAY
8994 || type == TYPE_SYSTEM_ERROR
8995 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
8996 mInnerFields.mSyswin = true;
9000 // This function assumes that the contents of the default display are
9001 // processed first before secondary displays.
9002 final DisplayContent displayContent = w.getDisplayContent();
9003 if (displayContent != null && displayContent.isDefaultDisplay) {
9004 // While a dream or keyguard is showing, obscure ordinary application
9005 // content on secondary displays (by forcibly enabling mirroring unless
9006 // there is other content we want to show) but still allow opaque
9007 // keyguard dialogs to be shown.
9008 if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
9009 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true;
9011 mInnerFields.mDisplayHasContent = true;
9012 } else if (displayContent != null &&
9013 (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays
9014 || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) {
9015 // Allow full screen keyguard presentation dialogs to be seen.
9016 mInnerFields.mDisplayHasContent = true;
9022 private void handleFlagDimBehind(WindowState w) {
9023 final WindowManager.LayoutParams attrs = w.mAttrs;
9024 if ((attrs.flags & FLAG_DIM_BEHIND) != 0
9025 && w.isDisplayedLw()
9027 final WindowStateAnimator winAnimator = w.mWinAnimator;
9028 final TaskStack stack = w.getStack();
9029 stack.setDimmingTag();
9030 if (!stack.isDimming(winAnimator)) {
9031 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
9032 stack.startDimmingIfNeeded(winAnimator);
9037 private void updateAllDrawnLocked(DisplayContent displayContent) {
9038 // See if any windows have been drawn, so they (and others
9039 // associated with them) can now be shown.
9040 ArrayList<TaskStack> stacks = displayContent.getStacks();
9041 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
9042 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9043 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9044 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9045 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9046 final AppWindowToken wtoken = tokens.get(tokenNdx);
9047 if (!wtoken.allDrawn) {
9048 int numInteresting = wtoken.numInterestingWindows;
9049 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
9050 if (DEBUG_VISIBILITY) Slog.v(TAG,
9051 "allDrawn: " + wtoken
9052 + " interesting=" + numInteresting
9053 + " drawn=" + wtoken.numDrawnWindows);
9054 wtoken.allDrawn = true;
9055 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
9063 // "Something has changed! Let's make it correct now."
9064 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
9065 if (DEBUG_WINDOW_TRACE) {
9066 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
9067 + Debug.getCallers(3));
9070 final long currentTime = SystemClock.uptimeMillis();
9074 if (mFocusMayChange) {
9075 mFocusMayChange = false;
9076 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
9077 false /*updateInputWindows*/);
9080 // Initialize state of exiting tokens.
9081 final int numDisplays = mDisplayContents.size();
9082 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9083 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9084 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
9085 displayContent.mExitingTokens.get(i).hasVisible = false;
9089 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
9090 // Initialize state of exiting applications.
9091 final AppTokenList exitingAppTokens =
9092 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
9093 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9094 exitingAppTokens.get(tokenNdx).hasVisible = false;
9098 mInnerFields.mHoldScreen = null;
9099 mInnerFields.mScreenBrightness = -1;
9100 mInnerFields.mButtonBrightness = -1;
9101 mInnerFields.mUserActivityTimeout = -1;
9102 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false;
9104 mTransactionSequence++;
9106 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
9107 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
9108 final int defaultDw = defaultInfo.logicalWidth;
9109 final int defaultDh = defaultInfo.logicalHeight;
9111 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9112 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
9113 SurfaceControl.openTransaction();
9116 if (mWatermark != null) {
9117 mWatermark.positionSurface(defaultDw, defaultDh);
9119 if (mStrictModeFlash != null) {
9120 mStrictModeFlash.positionSurface(defaultDw, defaultDh);
9123 boolean focusDisplayed = false;
9125 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9126 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9127 boolean updateAllDrawn = false;
9128 WindowList windows = displayContent.getWindowList();
9129 DisplayInfo displayInfo = displayContent.getDisplayInfo();
9130 final int displayId = displayContent.getDisplayId();
9131 final int dw = displayInfo.logicalWidth;
9132 final int dh = displayInfo.logicalHeight;
9133 final int innerDw = displayInfo.appWidth;
9134 final int innerDh = displayInfo.appHeight;
9135 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
9137 // Reset for each display.
9138 mInnerFields.mDisplayHasContent = false;
9144 Slog.w(TAG, "Animation repeat aborted after too many iterations");
9145 displayContent.layoutNeeded = false;
9149 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
9150 displayContent.pendingLayoutChanges);
9152 if ((displayContent.pendingLayoutChanges &
9153 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
9154 (adjustWallpaperWindowsLocked() &
9155 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
9156 assignLayersLocked(windows);
9157 displayContent.layoutNeeded = true;
9160 if (isDefaultDisplay && (displayContent.pendingLayoutChanges
9161 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
9162 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
9163 if (updateOrientationFromAppTokensLocked(true)) {
9164 displayContent.layoutNeeded = true;
9165 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9169 if ((displayContent.pendingLayoutChanges
9170 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9171 displayContent.layoutNeeded = true;
9174 // FIRST LOOP: Perform a layout, if needed.
9176 performLayoutLockedInner(displayContent, repeats == 1,
9177 false /*updateInputWindows*/);
9179 Slog.w(TAG, "Layout repeat skipped after too many iterations");
9182 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
9184 displayContent.pendingLayoutChanges = 0;
9186 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
9187 + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
9189 if (isDefaultDisplay) {
9190 mPolicy.beginPostLayoutPolicyLw(dw, dh);
9191 for (i = windows.size() - 1; i >= 0; i--) {
9192 WindowState w = windows.get(i);
9193 if (w.mHasSurface) {
9194 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs);
9197 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
9198 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
9199 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
9201 } while (displayContent.pendingLayoutChanges != 0);
9203 mInnerFields.mObscured = false;
9204 mInnerFields.mSyswin = false;
9205 displayContent.resetDimming();
9207 // Only used if default window
9208 final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
9210 final int N = windows.size();
9211 for (i=N-1; i>=0; i--) {
9212 WindowState w = windows.get(i);
9213 final TaskStack stack = w.getStack();
9214 if (stack == null) {
9218 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
9221 w.mObscured = mInnerFields.mObscured;
9222 if (!mInnerFields.mObscured) {
9223 handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
9226 if (!stack.testDimmingTag()) {
9227 handleFlagDimBehind(w);
9230 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
9231 && w.isVisibleLw()) {
9232 // This is the wallpaper target and its obscured state
9233 // changed... make sure the current wallaper's visibility
9234 // has been updated accordingly.
9235 updateWallpaperVisibilityLocked();
9238 final WindowStateAnimator winAnimator = w.mWinAnimator;
9240 // If the window has moved due to its containing
9241 // content frame changing, then we'd like to animate
9243 if (w.mHasSurface && w.shouldAnimateMove()) {
9244 // Frame has moved, containing content frame
9245 // has also moved, and we're not currently animating...
9246 // let's do something.
9247 Animation a = AnimationUtils.loadAnimation(mContext,
9248 com.android.internal.R.anim.window_move_from_decor);
9249 winAnimator.setAnimation(a);
9250 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
9251 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
9253 //TODO (multidisplay): Accessibility supported only for the default display.
9254 if (mAccessibilityController != null
9255 && displayId == Display.DEFAULT_DISPLAY) {
9256 mAccessibilityController.onSomeWindowResizedOrMovedLocked();
9260 w.mClient.moved(w.mFrame.left, w.mFrame.top);
9261 } catch (RemoteException e) {
9265 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
9266 w.mContentChanged = false;
9268 // Moved from updateWindowsAndWallpaperLocked().
9269 if (w.mHasSurface) {
9270 // Take care of the window being ready to display.
9271 final boolean committed =
9272 winAnimator.commitFinishDrawingLocked(currentTime);
9273 if (isDefaultDisplay && committed) {
9274 if (w.mAttrs.type == TYPE_DREAM) {
9275 // HACK: When a dream is shown, it may at that
9276 // point hide the lock screen. So we need to
9277 // redo the layout to let the phone window manager
9278 // make this happen.
9279 displayContent.pendingLayoutChanges |=
9280 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9281 if (DEBUG_LAYOUT_REPEATS) {
9283 "dream and commitFinishDrawingLocked true",
9284 displayContent.pendingLayoutChanges);
9287 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
9288 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
9289 "First draw done in potential wallpaper target " + w);
9290 mInnerFields.mWallpaperMayChange = true;
9291 displayContent.pendingLayoutChanges |=
9292 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9293 if (DEBUG_LAYOUT_REPEATS) {
9295 "wallpaper and commitFinishDrawingLocked true",
9296 displayContent.pendingLayoutChanges);
9301 winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
9303 final AppWindowToken atoken = w.mAppToken;
9304 if (DEBUG_STARTING_WINDOW && atoken != null
9305 && w == atoken.startingWindow) {
9306 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
9307 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
9308 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
9311 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
9312 if (atoken.lastTransactionSequence != mTransactionSequence) {
9313 atoken.lastTransactionSequence = mTransactionSequence;
9314 atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9315 atoken.startingDisplayed = false;
9317 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
9318 && !w.mExiting && !w.mDestroying) {
9319 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
9320 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
9321 + ", isAnimating=" + winAnimator.isAnimating());
9322 if (!w.isDrawnLw()) {
9323 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
9324 + " pv=" + w.mPolicyVisibility
9325 + " mDrawState=" + winAnimator.mDrawState
9326 + " ah=" + w.mAttachedHidden
9327 + " th=" + atoken.hiddenRequested
9328 + " a=" + winAnimator.mAnimating);
9331 if (w != atoken.startingWindow) {
9332 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
9333 atoken.numInterestingWindows++;
9334 if (w.isDrawnLw()) {
9335 atoken.numDrawnWindows++;
9336 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
9337 "tokenMayBeDrawn: " + atoken
9338 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
9339 + " mAppFreezing=" + w.mAppFreezing);
9340 updateAllDrawn = true;
9343 } else if (w.isDrawnLw()) {
9344 atoken.startingDisplayed = true;
9350 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
9351 && w.isDisplayedLw()) {
9352 focusDisplayed = true;
9355 updateResizingWindows(w);
9358 mDisplayManagerInternal.setDisplayHasContent(displayId,
9359 mInnerFields.mDisplayHasContent,
9360 true /* inTraversal, must call performTraversalInTrans... below */);
9362 getDisplayContentLocked(displayId).stopDimmingIfNeeded();
9364 if (updateAllDrawn) {
9365 updateAllDrawnLocked(displayContent);
9369 if (focusDisplayed) {
9370 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
9373 // Give the display manager a chance to adjust properties
9374 // like display rotation if it needs to.
9375 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
9377 } catch (RuntimeException e) {
9378 Log.wtf(TAG, "Unhandled exception in Window Manager", e);
9380 SurfaceControl.closeTransaction();
9381 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9382 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
9385 final WindowList defaultWindows = defaultDisplay.getWindowList();
9387 // If we are ready to perform an app transition, check through
9388 // all of the app tokens to be shown and see if they are ready
9390 if (mAppTransition.isReady()) {
9391 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
9392 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
9393 defaultDisplay.pendingLayoutChanges);
9396 if (!mAnimator.mAnimating && mAppTransition.isRunning()) {
9397 // We have finished the animation of an app transition. To do
9398 // this, we have delayed a lot of operations like showing and
9399 // hiding apps, moving apps in Z-order, etc. The app token list
9400 // reflects the correct Z-order, but the window list may now
9401 // be out of sync with it. So here we will just rebuild the
9402 // entire app window list. Fun!
9403 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
9404 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
9405 defaultDisplay.pendingLayoutChanges);
9408 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
9409 && !mAppTransition.isReady()) {
9410 // At this point, there was a window with a wallpaper that
9411 // was force hiding other windows behind it, but now it
9412 // is going away. This may be simple -- just animate
9413 // away the wallpaper and its window -- or it may be
9414 // hard -- the wallpaper now needs to be shown behind
9415 // something that was hidden.
9416 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9417 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
9418 defaultDisplay.pendingLayoutChanges);
9420 mInnerFields.mWallpaperForceHidingChanged = false;
9422 if (mInnerFields.mWallpaperMayChange) {
9423 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting");
9424 defaultDisplay.pendingLayoutChanges |=
9425 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9426 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
9427 defaultDisplay.pendingLayoutChanges);
9430 if (mFocusMayChange) {
9431 mFocusMayChange = false;
9432 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
9433 false /*updateInputWindows*/)) {
9434 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
9438 if (needsLayout()) {
9439 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9440 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
9441 defaultDisplay.pendingLayoutChanges);
9444 for (i = mResizingWindows.size() - 1; i >= 0; i--) {
9445 WindowState win = mResizingWindows.get(i);
9446 if (win.mAppFreezing) {
9447 // Don't remove this window until rotation has completed.
9450 win.reportResized();
9451 mResizingWindows.remove(i);
9454 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
9455 "With display frozen, orientationChangeComplete="
9456 + mInnerFields.mOrientationChangeComplete);
9457 if (mInnerFields.mOrientationChangeComplete) {
9458 if (mWindowsFreezingScreen) {
9459 mWindowsFreezingScreen = false;
9460 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource;
9461 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9463 stopFreezingDisplayLocked();
9466 // Destroy the surface of any windows that are no longer visible.
9467 boolean wallpaperDestroyed = false;
9468 i = mDestroySurface.size();
9472 WindowState win = mDestroySurface.get(i);
9473 win.mDestroying = false;
9474 if (mInputMethodWindow == win) {
9475 mInputMethodWindow = null;
9477 if (win == mWallpaperTarget) {
9478 wallpaperDestroyed = true;
9480 win.mWinAnimator.destroySurfaceLocked();
9482 mDestroySurface.clear();
9485 // Time to remove any exiting tokens?
9486 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9487 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9488 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
9489 for (i = exitingTokens.size() - 1; i >= 0; i--) {
9490 WindowToken token = exitingTokens.get(i);
9491 if (!token.hasVisible) {
9492 exitingTokens.remove(i);
9493 if (token.windowType == TYPE_WALLPAPER) {
9494 mWallpaperTokens.remove(token);
9500 // Time to remove any exiting applications?
9501 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
9502 // Initialize state of exiting applications.
9503 final AppTokenList exitingAppTokens =
9504 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
9505 for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
9506 AppWindowToken token = exitingAppTokens.get(i);
9507 if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) {
9508 // Make sure there is no animation running on this token,
9509 // so any windows associated with it will be removed as
9510 // soon as their animations are complete
9511 token.mAppAnimator.clearAnimation();
9512 token.mAppAnimator.animating = false;
9513 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
9514 "performLayout: App token exiting now removed" + token);
9515 removeAppFromTaskLocked(token);
9516 exitingAppTokens.remove(i);
9521 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
9522 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
9524 mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
9525 } catch (RemoteException e) {
9528 mRelayoutWhileAnimating.clear();
9531 if (wallpaperDestroyed) {
9532 defaultDisplay.pendingLayoutChanges |=
9533 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9534 defaultDisplay.layoutNeeded = true;
9537 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9538 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9539 if (displayContent.pendingLayoutChanges != 0) {
9540 displayContent.layoutNeeded = true;
9544 // Finally update all input windows now that the window changes have stabilized.
9545 mInputMonitor.updateInputWindowsLw(true /*force*/);
9547 setHoldScreenLocked(mInnerFields.mHoldScreen);
9548 if (!mDisplayFrozen) {
9549 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
9550 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
9552 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
9553 toBrightnessOverride(mInnerFields.mScreenBrightness));
9555 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
9556 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
9558 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
9559 toBrightnessOverride(mInnerFields.mButtonBrightness));
9561 mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
9562 mInnerFields.mUserActivityTimeout);
9565 if (mTurnOnScreen) {
9566 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
9567 mPowerManager.wakeUp(SystemClock.uptimeMillis());
9568 mTurnOnScreen = false;
9571 if (mInnerFields.mUpdateRotation) {
9572 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
9573 if (updateRotationUncheckedLocked(false)) {
9574 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9576 mInnerFields.mUpdateRotation = false;
9580 if (mWaitingForDrawnCallback != null ||
9581 (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&
9582 !mInnerFields.mUpdateRotation)) {
9583 checkDrawnWindowsLocked();
9586 final int N = mPendingRemove.size();
9588 if (mPendingRemoveTmp.length < N) {
9589 mPendingRemoveTmp = new WindowState[N+10];
9591 mPendingRemove.toArray(mPendingRemoveTmp);
9592 mPendingRemove.clear();
9593 DisplayContentList displayList = new DisplayContentList();
9594 for (i = 0; i < N; i++) {
9595 WindowState w = mPendingRemoveTmp[i];
9596 removeWindowInnerLocked(w.mSession, w);
9597 final DisplayContent displayContent = w.getDisplayContent();
9598 if (displayContent != null && !displayList.contains(displayContent)) {
9599 displayList.add(displayContent);
9603 for (DisplayContent displayContent : displayList) {
9604 assignLayersLocked(displayContent.getWindowList());
9605 displayContent.layoutNeeded = true;
9609 // Remove all deferred displays stacks, tasks, and activities.
9610 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
9611 mDisplayContents.valueAt(displayNdx).checkForDeferredActions();
9614 setFocusedStackFrame();
9616 // Check to see if we are now in a state where the screen should
9617 // be enabled, because the window obscured flags have changed.
9618 enableScreenIfNeededLocked();
9620 scheduleAnimationLocked();
9622 if (DEBUG_WINDOW_TRACE) {
9623 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
9624 + mAnimator.mAnimating);
9628 private int toBrightnessOverride(float value) {
9629 return (int)(value * PowerManager.BRIGHTNESS_ON);
9632 void checkDrawnWindowsLocked() {
9633 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
9636 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
9637 WindowState win = mWaitingForDrawn.get(j);
9638 if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win +
9639 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
9640 " mHasSurface=" + win.mHasSurface +
9641 " drawState=" + win.mWinAnimator.mDrawState);
9642 if (win.mRemoved || !win.mHasSurface) {
9643 // Window has been removed; no draw will now happen, so stop waiting.
9644 if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win);
9645 mWaitingForDrawn.remove(win);
9646 } else if (win.hasDrawnLw()) {
9647 // Window is now drawn (and shown).
9648 if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win);
9649 mWaitingForDrawn.remove(win);
9652 if (mWaitingForDrawn.isEmpty()) {
9653 if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!");
9654 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
9655 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
9659 void setHoldScreenLocked(final Session newHoldScreen) {
9660 final boolean hold = newHoldScreen != null;
9662 if (hold && mHoldingScreenOn != newHoldScreen) {
9663 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
9665 mHoldingScreenOn = newHoldScreen;
9667 final boolean state = mHoldingScreenWakeLock.isHeld();
9668 if (hold != state) {
9670 mHoldingScreenWakeLock.acquire();
9671 mPolicy.keepScreenOnStartedLw();
9673 mPolicy.keepScreenOnStoppedLw();
9674 mHoldingScreenWakeLock.release();
9679 void requestTraversal() {
9680 synchronized (mWindowMap) {
9681 requestTraversalLocked();
9685 void requestTraversalLocked() {
9686 if (!mTraversalScheduled) {
9687 mTraversalScheduled = true;
9688 mH.sendEmptyMessage(H.DO_TRAVERSAL);
9692 /** Note that Locked in this case is on mLayoutToAnim */
9693 void scheduleAnimationLocked() {
9694 if (!mAnimationScheduled) {
9695 mAnimationScheduled = true;
9696 mChoreographer.postCallback(
9697 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
9701 private boolean needsLayout() {
9702 final int numDisplays = mDisplayContents.size();
9703 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9704 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9705 if (displayContent.layoutNeeded) {
9712 boolean copyAnimToLayoutParamsLocked() {
9713 boolean doRequest = false;
9715 final int bulkUpdateParams = mAnimator.mBulkUpdateParams;
9716 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
9717 mInnerFields.mUpdateRotation = true;
9720 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
9721 mInnerFields.mWallpaperMayChange = true;
9724 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
9725 mInnerFields.mWallpaperForceHidingChanged = true;
9728 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
9729 mInnerFields.mOrientationChangeComplete = false;
9731 mInnerFields.mOrientationChangeComplete = true;
9732 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource;
9733 if (mWindowsFreezingScreen) {
9737 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
9738 mTurnOnScreen = true;
9740 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) {
9741 mInnerFields.mWallpaperActionPending = true;
9747 /** If a window that has an animation specifying a colored background and the current wallpaper
9748 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
9749 * suddenly disappear. */
9750 int adjustAnimationBackground(WindowStateAnimator winAnimator) {
9751 WindowList windows = winAnimator.mWin.getWindowList();
9752 for (int i = windows.size() - 1; i >= 0; --i) {
9753 WindowState testWin = windows.get(i);
9754 if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
9755 return testWin.mWinAnimator.mAnimLayer;
9758 return winAnimator.mAnimLayer;
9761 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
9763 final SurfaceControl surface = winAnimator.mSurfaceControl;
9764 boolean leakedSurface = false;
9765 boolean killedApps = false;
9767 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
9768 winAnimator.mSession.mPid, operation);
9770 if (mForceRemoves == null) {
9771 mForceRemoves = new ArrayList<WindowState>();
9774 long callingIdentity = Binder.clearCallingIdentity();
9776 // There was some problem... first, do a sanity check of the
9777 // window list to make sure we haven't left any dangling surfaces
9780 Slog.i(TAG, "Out of memory for surface! Looking for leaks...");
9781 final int numDisplays = mDisplayContents.size();
9782 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9783 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9784 final int numWindows = windows.size();
9785 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9786 final WindowState ws = windows.get(winNdx);
9787 WindowStateAnimator wsa = ws.mWinAnimator;
9788 if (wsa.mSurfaceControl != null) {
9789 if (!mSessions.contains(wsa.mSession)) {
9790 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
9791 + ws + " surface=" + wsa.mSurfaceControl
9792 + " token=" + ws.mToken
9793 + " pid=" + ws.mSession.mPid
9794 + " uid=" + ws.mSession.mUid);
9795 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9796 wsa.mSurfaceControl.destroy();
9797 wsa.mSurfaceShown = false;
9798 wsa.mSurfaceControl = null;
9799 ws.mHasSurface = false;
9800 mForceRemoves.add(ws);
9801 leakedSurface = true;
9802 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
9803 Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
9804 + ws + " surface=" + wsa.mSurfaceControl
9805 + " token=" + ws.mAppToken);
9806 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9807 wsa.mSurfaceControl.destroy();
9808 wsa.mSurfaceShown = false;
9809 wsa.mSurfaceControl = null;
9810 ws.mHasSurface = false;
9811 leakedSurface = true;
9817 if (!leakedSurface) {
9818 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
9819 SparseIntArray pidCandidates = new SparseIntArray();
9820 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9821 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9822 final int numWindows = windows.size();
9823 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9824 final WindowState ws = windows.get(winNdx);
9825 if (mForceRemoves.contains(ws)) {
9828 WindowStateAnimator wsa = ws.mWinAnimator;
9829 if (wsa.mSurfaceControl != null) {
9830 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
9833 if (pidCandidates.size() > 0) {
9834 int[] pids = new int[pidCandidates.size()];
9835 for (int i=0; i<pids.length; i++) {
9836 pids[i] = pidCandidates.keyAt(i);
9839 if (mActivityManager.killPids(pids, "Free memory", secure)) {
9842 } catch (RemoteException e) {
9848 if (leakedSurface || killedApps) {
9849 // We managed to reclaim some memory, so get rid of the trouble
9850 // surface and ask the app to request another one.
9851 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
9852 if (surface != null) {
9853 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
9854 "RECOVER DESTROY", null);
9856 winAnimator.mSurfaceShown = false;
9857 winAnimator.mSurfaceControl = null;
9858 winAnimator.mWin.mHasSurface = false;
9859 scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken);
9863 winAnimator.mWin.mClient.dispatchGetNewSurface();
9864 } catch (RemoteException e) {
9868 Binder.restoreCallingIdentity(callingIdentity);
9871 return leakedSurface || killedApps;
9874 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
9875 WindowState newFocus = computeFocusedWindowLocked();
9876 if (mCurrentFocus != newFocus) {
9877 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
9878 // This check makes sure that we don't already have the focus
9879 // change message pending.
9880 mH.removeMessages(H.REPORT_FOCUS_CHANGE);
9881 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
9882 // TODO(multidisplay): Focused windows on default display only.
9883 final DisplayContent displayContent = getDefaultDisplayContentLocked();
9884 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
9885 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
9886 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
9887 if (imWindowChanged) {
9888 displayContent.layoutNeeded = true;
9889 newFocus = computeFocusedWindowLocked();
9892 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " +
9893 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
9894 final WindowState oldFocus = mCurrentFocus;
9895 mCurrentFocus = newFocus;
9896 mLosingFocus.remove(newFocus);
9898 // TODO(multidisplay): Accessibilty supported only of default desiplay.
9899 if (mAccessibilityController != null
9900 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
9901 mAccessibilityController.onWindowFocusChangedLocked();
9904 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
9906 if (imWindowChanged && oldFocus != mInputMethodWindow) {
9907 // Focus of the input method window changed. Perform layout if needed.
9908 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9909 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9910 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9911 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
9912 // Client will do the layout, but we need to assign layers
9913 // for handleNewWindowLocked() below.
9914 assignLayersLocked(displayContent.getWindowList());
9918 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9919 // The change in focus caused us to need to do a layout. Okay.
9920 displayContent.layoutNeeded = true;
9921 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9922 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9926 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
9927 // If we defer assigning layers, then the caller is responsible for
9929 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows);
9932 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
9938 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) {
9939 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
9942 private WindowState computeFocusedWindowLocked() {
9943 if (mAnimator.mUniverseBackground != null
9944 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
9945 return mAnimator.mUniverseBackground.mWin;
9948 final int displayCount = mDisplayContents.size();
9949 for (int i = 0; i < displayCount; i++) {
9950 final DisplayContent displayContent = mDisplayContents.valueAt(i);
9951 WindowState win = findFocusedWindowLocked(displayContent);
9959 private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
9960 final WindowList windows = displayContent.getWindowList();
9961 for (int i = windows.size() - 1; i >= 0; i--) {
9962 final WindowState win = windows.get(i);
9964 if (localLOGV || DEBUG_FOCUS) Slog.v(
9965 TAG, "Looking for focus: " + i
9967 + ", flags=" + win.mAttrs.flags
9968 + ", canReceive=" + win.canReceiveKeys());
9970 AppWindowToken wtoken = win.mAppToken;
9972 // If this window's application has been removed, just skip it.
9973 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
9974 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because "
9975 + (wtoken.removed ? "removed" : "sendingToBottom"));
9979 if (!win.canReceiveKeys()) {
9983 // Descend through all of the app tokens and find the first that either matches
9984 // win.mAppToken (return win) or mFocusedApp (return null).
9985 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
9986 mFocusedApp != null) {
9987 ArrayList<Task> tasks = displayContent.getTasks();
9988 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9989 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9990 int tokenNdx = tokens.size() - 1;
9991 for ( ; tokenNdx >= 0; --tokenNdx) {
9992 final AppWindowToken token = tokens.get(tokenNdx);
9993 if (wtoken == token) {
9996 if (mFocusedApp == token) {
9997 // Whoops, we are below the focused app... no focus for you!
9998 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG,
9999 "findFocusedWindow: Reached focused app=" + mFocusedApp);
10003 if (tokenNdx >= 0) {
10004 // Early exit from loop, must have found the matching token.
10010 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i +
10015 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows.");
10019 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
10020 if (mDisplayFrozen) {
10024 if (!mDisplayReady || !mPolicy.isScreenOnFully()) {
10025 // No need to freeze the screen before the system is ready or if
10026 // the screen is off.
10030 mScreenFrozenLock.acquire();
10032 mDisplayFrozen = true;
10033 mDisplayFreezeTime = SystemClock.elapsedRealtime();
10034 mLastFinishedFreezeSource = null;
10036 mInputMonitor.freezeInputDispatchingLw();
10038 // Clear the last input window -- that is just used for
10039 // clean transitions between IMEs, and if we are freezing
10040 // the screen then the whole world is changing behind the scenes.
10041 mPolicy.setLastInputMethodWindowLw(null, null);
10043 if (mAppTransition.isTransitionSet()) {
10044 mAppTransition.freeze();
10047 if (PROFILE_ORIENTATION) {
10048 File file = new File("/data/system/frozen");
10049 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
10052 if (CUSTOM_SCREEN_ROTATION) {
10053 mExitAnimId = exitAnim;
10054 mEnterAnimId = enterAnim;
10055 final DisplayContent displayContent = getDefaultDisplayContentLocked();
10056 final int displayId = displayContent.getDisplayId();
10057 ScreenRotationAnimation screenRotationAnimation =
10058 mAnimator.getScreenRotationAnimationLocked(displayId);
10059 if (screenRotationAnimation != null) {
10060 screenRotationAnimation.kill();
10063 // Check whether the current screen contains any secure content.
10064 boolean isSecure = false;
10065 final WindowList windows = getDefaultWindowListLocked();
10066 final int N = windows.size();
10067 for (int i = 0; i < N; i++) {
10068 WindowState ws = windows.get(i);
10069 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
10075 // TODO(multidisplay): rotation on main screen only.
10076 displayContent.updateDisplayInfo();
10077 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
10078 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure);
10079 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10083 private void stopFreezingDisplayLocked() {
10084 if (!mDisplayFrozen) {
10088 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
10089 || mClientFreezingScreen) {
10090 if (DEBUG_ORIENTATION) Slog.d(TAG,
10091 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
10092 + ", mAppsFreezingScreen=" + mAppsFreezingScreen
10093 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
10094 + ", mClientFreezingScreen=" + mClientFreezingScreen);
10098 mDisplayFrozen = false;
10099 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
10100 StringBuilder sb = new StringBuilder(128);
10101 sb.append("Screen frozen for ");
10102 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
10103 if (mLastFinishedFreezeSource != null) {
10104 sb.append(" due to ");
10105 sb.append(mLastFinishedFreezeSource);
10107 Slog.i(TAG, sb.toString());
10108 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
10109 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
10110 if (PROFILE_ORIENTATION) {
10111 Debug.stopMethodTracing();
10114 boolean updateRotation = false;
10116 final DisplayContent displayContent = getDefaultDisplayContentLocked();
10117 final int displayId = displayContent.getDisplayId();
10118 ScreenRotationAnimation screenRotationAnimation =
10119 mAnimator.getScreenRotationAnimationLocked(displayId);
10120 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
10121 && screenRotationAnimation.hasScreenshot()) {
10122 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
10123 // TODO(multidisplay): rotation on main screen only.
10124 DisplayInfo displayInfo = displayContent.getDisplayInfo();
10125 // Get rotation animation again, with new top window
10126 boolean isDimming = displayContent.isDimming();
10127 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
10128 mExitAnimId = mEnterAnimId = 0;
10130 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
10131 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
10132 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
10133 scheduleAnimationLocked();
10135 screenRotationAnimation.kill();
10136 screenRotationAnimation = null;
10137 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10138 updateRotation = true;
10141 if (screenRotationAnimation != null) {
10142 screenRotationAnimation.kill();
10143 screenRotationAnimation = null;
10144 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10146 updateRotation = true;
10149 mInputMonitor.thawInputDispatchingLw();
10151 boolean configChanged;
10153 // While the display is frozen we don't re-compute the orientation
10154 // to avoid inconsistent states. However, something interesting
10155 // could have actually changed during that time so re-evaluate it
10156 // now to catch that.
10157 configChanged = updateOrientationFromAppTokensLocked(false);
10159 // A little kludge: a lot could have happened while the
10160 // display was frozen, so now that we are coming back we
10161 // do a gc so that any remote references the system
10162 // processes holds on others can be released if they are
10163 // no longer needed.
10164 mH.removeMessages(H.FORCE_GC);
10165 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
10167 mScreenFrozenLock.release();
10169 if (updateRotation) {
10170 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
10171 configChanged |= updateRotationUncheckedLocked(false);
10174 if (configChanged) {
10175 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
10179 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
10180 DisplayMetrics dm) {
10181 if (index < tokens.length) {
10182 String str = tokens[index];
10183 if (str != null && str.length() > 0) {
10185 int val = Integer.parseInt(str);
10187 } catch (Exception e) {
10191 if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
10194 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
10198 void createWatermarkInTransaction() {
10199 if (mWatermark != null) {
10203 File file = new File("/system/etc/setup.conf");
10204 FileInputStream in = null;
10205 DataInputStream ind = null;
10207 in = new FileInputStream(file);
10208 ind = new DataInputStream(in);
10209 String line = ind.readLine();
10210 if (line != null) {
10211 String[] toks = line.split("%");
10212 if (toks != null && toks.length > 0) {
10213 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
10214 mRealDisplayMetrics, mFxSession, toks);
10217 } catch (FileNotFoundException e) {
10218 } catch (IOException e) {
10223 } catch (IOException e) {
10225 } else if (in != null) {
10228 } catch (IOException e) {
10235 public void statusBarVisibilityChanged(int visibility) {
10236 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
10237 != PackageManager.PERMISSION_GRANTED) {
10238 throw new SecurityException("Caller does not hold permission "
10239 + android.Manifest.permission.STATUS_BAR);
10242 synchronized (mWindowMap) {
10243 mLastStatusBarVisibility = visibility;
10244 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
10245 updateStatusBarVisibilityLocked(visibility);
10249 // TOOD(multidisplay): StatusBar on multiple screens?
10250 void updateStatusBarVisibilityLocked(int visibility) {
10251 mInputManager.setSystemUiVisibility(visibility);
10252 final WindowList windows = getDefaultWindowListLocked();
10253 final int N = windows.size();
10254 for (int i = 0; i < N; i++) {
10255 WindowState ws = windows.get(i);
10257 int curValue = ws.mSystemUiVisibility;
10258 int diff = curValue ^ visibility;
10259 // We are only interested in differences of one of the
10260 // clearable flags...
10261 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
10262 // ...if it has actually been cleared.
10263 diff &= ~visibility;
10264 int newValue = (curValue&~diff) | (visibility&diff);
10265 if (newValue != curValue) {
10267 ws.mSystemUiVisibility = newValue;
10269 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
10270 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
10271 visibility, newValue, diff);
10273 } catch (RemoteException e) {
10280 public void reevaluateStatusBarVisibility() {
10281 synchronized (mWindowMap) {
10282 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
10283 updateStatusBarVisibilityLocked(visibility);
10284 performLayoutAndPlaceSurfacesLocked();
10289 public FakeWindow addFakeWindow(Looper looper,
10290 InputEventReceiver.Factory inputEventReceiverFactory,
10291 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags,
10292 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) {
10293 synchronized (mWindowMap) {
10294 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
10296 layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys,
10297 hasFocus, touchFullscreen);
10299 while (i<mFakeWindows.size()) {
10300 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
10304 mFakeWindows.add(i, fw);
10305 mInputMonitor.updateInputWindowsLw(true);
10310 boolean removeFakeWindowLocked(FakeWindow window) {
10311 synchronized (mWindowMap) {
10312 if (mFakeWindows.remove(window)) {
10313 mInputMonitor.updateInputWindowsLw(true);
10320 // It is assumed that this method is called only by InputMethodManagerService.
10321 public void saveLastInputMethodWindowForTransition() {
10322 synchronized (mWindowMap) {
10323 // TODO(multidisplay): Pass in the displayID.
10324 DisplayContent displayContent = getDefaultDisplayContentLocked();
10325 if (mInputMethodWindow != null) {
10326 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
10331 public int getInputMethodWindowVisibleHeight() {
10332 synchronized (mWindowMap) {
10333 return mPolicy.getInputMethodWindowVisibleHeightLw();
10338 public boolean hasNavigationBar() {
10339 return mPolicy.hasNavigationBar();
10343 public void lockNow(Bundle options) {
10344 mPolicy.lockNow(options);
10347 public void showRecentApps() {
10348 mPolicy.showRecentApps();
10352 public boolean isSafeModeEnabled() {
10357 public boolean clearWindowContentFrameStats(IBinder token) {
10358 if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10359 "clearWindowContentFrameStats()")) {
10360 throw new SecurityException("Requires FRAME_STATS permission");
10362 synchronized (mWindowMap) {
10363 WindowState windowState = mWindowMap.get(token);
10364 if (windowState == null) {
10367 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
10368 if (surfaceControl == null) {
10371 return surfaceControl.clearContentFrameStats();
10376 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
10377 if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10378 "getWindowContentFrameStats()")) {
10379 throw new SecurityException("Requires FRAME_STATS permission");
10381 synchronized (mWindowMap) {
10382 WindowState windowState = mWindowMap.get(token);
10383 if (windowState == null) {
10386 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
10387 if (surfaceControl == null) {
10390 if (mTempWindowRenderStats == null) {
10391 mTempWindowRenderStats = new WindowContentFrameStats();
10393 WindowContentFrameStats stats = mTempWindowRenderStats;
10394 if (!surfaceControl.getContentFrameStats(stats)) {
10401 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10402 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
10403 mPolicy.dump(" ", pw, args);
10406 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10407 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
10408 mAnimator.dumpLocked(pw, " ", dumpAll);
10411 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
10412 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
10413 if (mTokenMap.size() > 0) {
10414 pw.println(" All tokens:");
10415 Iterator<WindowToken> it = mTokenMap.values().iterator();
10416 while (it.hasNext()) {
10417 WindowToken token = it.next();
10418 pw.print(" "); pw.print(token);
10421 token.dump(pw, " ");
10427 if (mWallpaperTokens.size() > 0) {
10429 pw.println(" Wallpaper tokens:");
10430 for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
10431 WindowToken token = mWallpaperTokens.get(i);
10432 pw.print(" Wallpaper #"); pw.print(i);
10433 pw.print(' '); pw.print(token);
10436 token.dump(pw, " ");
10442 if (mFinishedStarting.size() > 0) {
10444 pw.println(" Finishing start of application tokens:");
10445 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10446 WindowToken token = mFinishedStarting.get(i);
10447 pw.print(" Finished Starting #"); pw.print(i);
10448 pw.print(' '); pw.print(token);
10451 token.dump(pw, " ");
10457 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
10459 if (mOpeningApps.size() > 0) {
10460 pw.print(" mOpeningApps="); pw.println(mOpeningApps);
10462 if (mClosingApps.size() > 0) {
10463 pw.print(" mClosingApps="); pw.println(mClosingApps);
10468 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
10469 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
10470 for (int i=0; i<mSessions.size(); i++) {
10471 Session s = mSessions.valueAt(i);
10472 pw.print(" Session "); pw.print(s); pw.println(':');
10477 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
10478 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
10479 if (mDisplayReady) {
10480 final int numDisplays = mDisplayContents.size();
10481 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10482 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10483 displayContent.dump(" ", pw);
10486 pw.println(" NO DISPLAY");
10490 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
10491 ArrayList<WindowState> windows) {
10492 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
10493 dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
10496 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
10497 ArrayList<WindowState> windows) {
10498 final int numDisplays = mDisplayContents.size();
10499 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10500 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
10501 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10502 final WindowState w = windowList.get(winNdx);
10503 if (windows == null || windows.contains(w)) {
10504 pw.print(" Window #"); pw.print(winNdx); pw.print(' ');
10505 pw.print(w); pw.println(":");
10506 w.dump(pw, " ", dumpAll || windows != null);
10510 if (mInputMethodDialogs.size() > 0) {
10512 pw.println(" Input method dialogs:");
10513 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10514 WindowState w = mInputMethodDialogs.get(i);
10515 if (windows == null || windows.contains(w)) {
10516 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
10520 if (mPendingRemove.size() > 0) {
10522 pw.println(" Remove pending for:");
10523 for (int i=mPendingRemove.size()-1; i>=0; i--) {
10524 WindowState w = mPendingRemove.get(i);
10525 if (windows == null || windows.contains(w)) {
10526 pw.print(" Remove #"); pw.print(i); pw.print(' ');
10530 w.dump(pw, " ", true);
10537 if (mForceRemoves != null && mForceRemoves.size() > 0) {
10539 pw.println(" Windows force removing:");
10540 for (int i=mForceRemoves.size()-1; i>=0; i--) {
10541 WindowState w = mForceRemoves.get(i);
10542 pw.print(" Removing #"); pw.print(i); pw.print(' ');
10546 w.dump(pw, " ", true);
10552 if (mDestroySurface.size() > 0) {
10554 pw.println(" Windows waiting to destroy their surface:");
10555 for (int i=mDestroySurface.size()-1; i>=0; i--) {
10556 WindowState w = mDestroySurface.get(i);
10557 if (windows == null || windows.contains(w)) {
10558 pw.print(" Destroy #"); pw.print(i); pw.print(' ');
10562 w.dump(pw, " ", true);
10569 if (mLosingFocus.size() > 0) {
10571 pw.println(" Windows losing focus:");
10572 for (int i=mLosingFocus.size()-1; i>=0; i--) {
10573 WindowState w = mLosingFocus.get(i);
10574 if (windows == null || windows.contains(w)) {
10575 pw.print(" Losing #"); pw.print(i); pw.print(' ');
10579 w.dump(pw, " ", true);
10586 if (mResizingWindows.size() > 0) {
10588 pw.println(" Windows waiting to resize:");
10589 for (int i=mResizingWindows.size()-1; i>=0; i--) {
10590 WindowState w = mResizingWindows.get(i);
10591 if (windows == null || windows.contains(w)) {
10592 pw.print(" Resizing #"); pw.print(i); pw.print(' ');
10596 w.dump(pw, " ", true);
10603 if (mWaitingForDrawn.size() > 0) {
10605 pw.println(" Clients waiting for these windows to be drawn:");
10606 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
10607 WindowState win = mWaitingForDrawn.get(i);
10608 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
10612 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration);
10613 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
10614 if (mLastFocus != mCurrentFocus) {
10615 pw.print(" mLastFocus="); pw.println(mLastFocus);
10617 pw.print(" mFocusedApp="); pw.println(mFocusedApp);
10618 if (mInputMethodTarget != null) {
10619 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
10621 pw.print(" mInTouchMode="); pw.print(mInTouchMode);
10622 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
10623 pw.print(" mLastDisplayFreezeDuration=");
10624 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
10625 if ( mLastFinishedFreezeSource != null) {
10626 pw.print(" due to ");
10627 pw.print(mLastFinishedFreezeSource);
10631 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer);
10632 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
10633 if (mLastStatusBarVisibility != 0) {
10634 pw.print(" mLastStatusBarVisibility=0x");
10635 pw.println(Integer.toHexString(mLastStatusBarVisibility));
10637 if (mInputMethodWindow != null) {
10638 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
10640 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget);
10641 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
10642 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
10643 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
10645 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX);
10646 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
10647 if (mInputMethodAnimLayerAdjustment != 0 ||
10648 mWallpaperAnimLayerAdjustment != 0) {
10649 pw.print(" mInputMethodAnimLayerAdjustment=");
10650 pw.print(mInputMethodAnimLayerAdjustment);
10651 pw.print(" mWallpaperAnimLayerAdjustment=");
10652 pw.println(mWallpaperAnimLayerAdjustment);
10654 pw.print(" mSystemBooted="); pw.print(mSystemBooted);
10655 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10656 if (needsLayout()) {
10657 pw.print(" layoutNeeded on displays=");
10658 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10659 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10660 if (displayContent.layoutNeeded) {
10661 pw.print(displayContent.getDisplayId());
10666 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence);
10667 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
10668 pw.print(" windows="); pw.print(mWindowsFreezingScreen);
10669 pw.print(" client="); pw.print(mClientFreezingScreen);
10670 pw.print(" apps="); pw.print(mAppsFreezingScreen);
10671 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
10672 pw.print(" mRotation="); pw.print(mRotation);
10673 pw.print(" mAltOrientation="); pw.println(mAltOrientation);
10674 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
10675 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
10676 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
10677 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled);
10678 pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
10679 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
10680 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
10681 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled);
10682 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
10683 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
10684 pw.println(" mLayoutToAnim:");
10685 mAppTransition.dump(pw);
10689 boolean dumpWindows(PrintWriter pw, String name, String[] args,
10690 int opti, boolean dumpAll) {
10691 WindowList windows = new WindowList();
10692 if ("visible".equals(name)) {
10693 synchronized(mWindowMap) {
10694 final int numDisplays = mDisplayContents.size();
10695 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10696 final WindowList windowList =
10697 mDisplayContents.valueAt(displayNdx).getWindowList();
10698 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10699 final WindowState w = windowList.get(winNdx);
10700 if (w.mWinAnimator.mSurfaceShown) {
10708 // See if this is an object ID.
10710 objectId = Integer.parseInt(name, 16);
10712 } catch (RuntimeException e) {
10714 synchronized(mWindowMap) {
10715 final int numDisplays = mDisplayContents.size();
10716 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10717 final WindowList windowList =
10718 mDisplayContents.valueAt(displayNdx).getWindowList();
10719 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10720 final WindowState w = windowList.get(winNdx);
10721 if (name != null) {
10722 if (w.mAttrs.getTitle().toString().contains(name)) {
10725 } else if (System.identityHashCode(w) == objectId) {
10733 if (windows.size() <= 0) {
10737 synchronized(mWindowMap) {
10738 dumpWindowsLocked(pw, dumpAll, windows);
10743 void dumpLastANRLocked(PrintWriter pw) {
10744 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
10745 if (mLastANRState == null) {
10746 pw.println(" <no ANR has occurred since boot>");
10748 pw.println(mLastANRState);
10753 * Saves information about the state of the window manager at
10754 * the time an ANR occurred before anything else in the system changes
10757 * @param appWindowToken The application that ANR'd, may be null.
10758 * @param windowState The window that ANR'd, may be null.
10759 * @param reason The reason for the ANR, may be null.
10761 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
10763 StringWriter sw = new StringWriter();
10764 PrintWriter pw = new FastPrintWriter(sw, false, 1024);
10765 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date()));
10766 if (appWindowToken != null) {
10767 pw.println(" Application at fault: " + appWindowToken.stringName);
10769 if (windowState != null) {
10770 pw.println(" Window at fault: " + windowState.mAttrs.getTitle());
10772 if (reason != null) {
10773 pw.println(" Reason: " + reason);
10776 dumpWindowsNoHeaderLocked(pw, true, null);
10778 mLastANRState = sw.toString();
10782 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10783 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
10784 != PackageManager.PERMISSION_GRANTED) {
10785 pw.println("Permission Denial: can't dump WindowManager from from pid="
10786 + Binder.getCallingPid()
10787 + ", uid=" + Binder.getCallingUid());
10791 boolean dumpAll = false;
10794 while (opti < args.length) {
10795 String opt = args[opti];
10796 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10800 if ("-a".equals(opt)) {
10802 } else if ("-h".equals(opt)) {
10803 pw.println("Window manager dump options:");
10804 pw.println(" [-a] [-h] [cmd] ...");
10805 pw.println(" cmd may be one of:");
10806 pw.println(" l[astanr]: last ANR information");
10807 pw.println(" p[policy]: policy state");
10808 pw.println(" a[animator]: animator state");
10809 pw.println(" s[essions]: active sessions");
10810 pw.println(" d[isplays]: active display contents");
10811 pw.println(" t[okens]: token list");
10812 pw.println(" w[indows]: window list");
10813 pw.println(" cmd may also be a NAME to dump windows. NAME may");
10814 pw.println(" be a partial substring in a window name, a");
10815 pw.println(" Window hex object identifier, or");
10816 pw.println(" \"all\" for all windows, or");
10817 pw.println(" \"visible\" for the visible windows.");
10818 pw.println(" -a: include all available server state.");
10821 pw.println("Unknown argument: " + opt + "; use -h for help");
10825 // Is the caller requesting to dump a particular piece of data?
10826 if (opti < args.length) {
10827 String cmd = args[opti];
10829 if ("lastanr".equals(cmd) || "l".equals(cmd)) {
10830 synchronized(mWindowMap) {
10831 dumpLastANRLocked(pw);
10834 } else if ("policy".equals(cmd) || "p".equals(cmd)) {
10835 synchronized(mWindowMap) {
10836 dumpPolicyLocked(pw, args, true);
10839 } else if ("animator".equals(cmd) || "a".equals(cmd)) {
10840 synchronized(mWindowMap) {
10841 dumpAnimatorLocked(pw, args, true);
10844 } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
10845 synchronized(mWindowMap) {
10846 dumpSessionsLocked(pw, true);
10849 } else if ("displays".equals(cmd) || "d".equals(cmd)) {
10850 synchronized(mWindowMap) {
10851 dumpDisplayContentsLocked(pw, true);
10854 } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
10855 synchronized(mWindowMap) {
10856 dumpTokensLocked(pw, true);
10859 } else if ("windows".equals(cmd) || "w".equals(cmd)) {
10860 synchronized(mWindowMap) {
10861 dumpWindowsLocked(pw, true, null);
10864 } else if ("all".equals(cmd) || "a".equals(cmd)) {
10865 synchronized(mWindowMap) {
10866 dumpWindowsLocked(pw, true, null);
10870 // Dumping a single name?
10871 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
10872 pw.println("Bad window command, or no windows match: " + cmd);
10873 pw.println("Use -h for help.");
10879 synchronized(mWindowMap) {
10882 pw.println("-------------------------------------------------------------------------------");
10884 dumpLastANRLocked(pw);
10887 pw.println("-------------------------------------------------------------------------------");
10889 dumpPolicyLocked(pw, args, dumpAll);
10892 pw.println("-------------------------------------------------------------------------------");
10894 dumpAnimatorLocked(pw, args, dumpAll);
10897 pw.println("-------------------------------------------------------------------------------");
10899 dumpSessionsLocked(pw, dumpAll);
10902 pw.println("-------------------------------------------------------------------------------");
10904 dumpDisplayContentsLocked(pw, dumpAll);
10907 pw.println("-------------------------------------------------------------------------------");
10909 dumpTokensLocked(pw, dumpAll);
10912 pw.println("-------------------------------------------------------------------------------");
10914 dumpWindowsLocked(pw, dumpAll, null);
10918 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
10920 public void monitor() {
10921 synchronized (mWindowMap) { }
10924 public interface OnHardKeyboardStatusChangeListener {
10925 public void onHardKeyboardStatusChange(boolean available, boolean enabled);
10928 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
10929 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
10930 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
10931 Integer.toHexString(pendingLayoutChanges));
10935 private DisplayContent newDisplayContentLocked(final Display display) {
10936 DisplayContent displayContent = new DisplayContent(display, this);
10937 final int displayId = display.getDisplayId();
10938 if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display);
10939 mDisplayContents.put(displayId, displayContent);
10941 DisplayInfo displayInfo = displayContent.getDisplayInfo();
10942 final Rect rect = new Rect();
10943 mDisplaySettings.getOverscanLocked(displayInfo.name, rect);
10944 synchronized (displayContent.mDisplaySizeLock) {
10945 displayInfo.overscanLeft = rect.left;
10946 displayInfo.overscanTop = rect.top;
10947 displayInfo.overscanRight = rect.right;
10948 displayInfo.overscanBottom = rect.bottom;
10949 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
10950 displayId, displayInfo);
10952 configureDisplayPolicyLocked(displayContent);
10954 // TODO: Create an input channel for each display with touch capability.
10955 if (displayId == Display.DEFAULT_DISPLAY) {
10956 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent);
10957 registerPointerEventListener(displayContent.mTapDetector);
10960 return displayContent;
10963 public void createDisplayContentLocked(final Display display) {
10964 if (display == null) {
10965 throw new IllegalArgumentException("getDisplayContent: display must not be null");
10967 getDisplayContentLocked(display.getDisplayId());
10971 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
10972 * there is a Display for the displayId.
10973 * @param displayId The display the caller is interested in.
10974 * @return The DisplayContent associated with displayId or null if there is no Display for it.
10976 public DisplayContent getDisplayContentLocked(final int displayId) {
10977 DisplayContent displayContent = mDisplayContents.get(displayId);
10978 if (displayContent == null) {
10979 final Display display = mDisplayManager.getDisplay(displayId);
10980 if (display != null) {
10981 displayContent = newDisplayContentLocked(display);
10984 return displayContent;
10987 // There is an inherent assumption that this will never return null.
10988 public DisplayContent getDefaultDisplayContentLocked() {
10989 return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
10992 public WindowList getDefaultWindowListLocked() {
10993 return getDefaultDisplayContentLocked().getWindowList();
10996 public DisplayInfo getDefaultDisplayInfoLocked() {
10997 return getDefaultDisplayContentLocked().getDisplayInfo();
11001 * Return the list of WindowStates associated on the passed display.
11002 * @param display The screen to return windows from.
11003 * @return The list of WindowStates on the screen, or null if the there is no screen.
11005 public WindowList getWindowListLocked(final Display display) {
11006 return getWindowListLocked(display.getDisplayId());
11010 * Return the list of WindowStates associated on the passed display.
11011 * @param displayId The screen to return windows from.
11012 * @return The list of WindowStates on the screen, or null if the there is no screen.
11014 public WindowList getWindowListLocked(final int displayId) {
11015 final DisplayContent displayContent = getDisplayContentLocked(displayId);
11016 return displayContent != null ? displayContent.getWindowList() : null;
11019 public void onDisplayAdded(int displayId) {
11020 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
11023 public void handleDisplayAdded(int displayId) {
11024 synchronized (mWindowMap) {
11025 final Display display = mDisplayManager.getDisplay(displayId);
11026 if (display != null) {
11027 createDisplayContentLocked(display);
11028 displayReady(displayId);
11033 public void onDisplayRemoved(int displayId) {
11034 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
11037 private void handleDisplayRemovedLocked(int displayId) {
11038 final DisplayContent displayContent = getDisplayContentLocked(displayId);
11039 if (displayContent != null) {
11040 if (displayContent.isAnimating()) {
11041 displayContent.mDeferredRemoval = true;
11044 if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent);
11045 mDisplayContents.delete(displayId);
11046 displayContent.close();
11047 if (displayId == Display.DEFAULT_DISPLAY) {
11048 unregisterPointerEventListener(displayContent.mTapDetector);
11051 mAnimator.removeDisplayLocked(displayId);
11054 public void onDisplayChanged(int displayId) {
11055 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
11058 private void handleDisplayChangedLocked(int displayId) {
11059 final DisplayContent displayContent = getDisplayContentLocked(displayId);
11060 if (displayContent != null) {
11061 displayContent.updateDisplayInfo();
11066 public Object getWindowManagerLock() {
11070 private final class LocalService extends WindowManagerInternal {
11072 public void requestTraversalFromDisplayManager() {
11073 requestTraversal();
11077 public void setMagnificationSpec(MagnificationSpec spec) {
11078 synchronized (mWindowMap) {
11079 if (mAccessibilityController != null) {
11080 mAccessibilityController.setMagnificationSpecLocked(spec);
11082 throw new IllegalStateException("Magnification callbacks not set!");
11085 if (Binder.getCallingPid() != android.os.Process.myPid()) {
11091 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
11092 synchronized (mWindowMap) {
11093 WindowState windowState = mWindowMap.get(windowToken);
11094 if (windowState == null) {
11097 MagnificationSpec spec = null;
11098 if (mAccessibilityController != null) {
11099 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState);
11101 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
11104 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
11105 spec.scale *= windowState.mGlobalScale;
11111 public void setMagnificationCallbacks(MagnificationCallbacks callbacks) {
11112 synchronized (mWindowMap) {
11113 if (mAccessibilityController == null) {
11114 mAccessibilityController = new AccessibilityController(
11115 WindowManagerService.this);
11117 mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
11118 if (!mAccessibilityController.hasCallbacksLocked()) {
11119 mAccessibilityController = null;
11125 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
11126 synchronized (mWindowMap) {
11127 if (mAccessibilityController == null) {
11128 mAccessibilityController = new AccessibilityController(
11129 WindowManagerService.this);
11131 mAccessibilityController.setWindowsForAccessibilityCallback(callback);
11132 if (!mAccessibilityController.hasCallbacksLocked()) {
11133 mAccessibilityController = null;
11139 public void setInputFilter(IInputFilter filter) {
11140 mInputManager.setInputFilter(filter);
11144 public IBinder getFocusedWindowToken() {
11145 synchronized (mWindowMap) {
11146 WindowState windowState = getFocusedWindowLocked();
11147 if (windowState != null) {
11148 return windowState.mClient.asBinder();
11155 public boolean isKeyguardLocked() {
11156 return WindowManagerService.this.isKeyguardLocked();
11160 public void showGlobalActions() {
11161 WindowManagerService.this.showGlobalActions();
11165 public void getWindowFrame(IBinder token, Rect outBounds) {
11166 synchronized (mWindowMap) {
11167 WindowState windowState = mWindowMap.get(token);
11168 if (windowState != null) {
11169 outBounds.set(windowState.mFrame);
11171 outBounds.setEmpty();
11176 public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
11177 synchronized (mWindowMap) {
11178 mWaitingForDrawnCallback = callback;
11179 final WindowList windows = getDefaultWindowListLocked();
11180 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
11181 final WindowState win = windows.get(winNdx);
11182 if (win.mHasSurface) {
11183 win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
11184 // Force add to mResizingWindows.
11185 win.mLastContentInsets.set(-1, -1, -1, -1);
11186 mWaitingForDrawn.add(win);
11189 requestTraversalLocked();
11191 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
11192 if (mWaitingForDrawn.isEmpty()) {
11195 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
11196 checkDrawnWindowsLocked();