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 com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
23 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
25 import android.app.AppOpsManager;
26 import android.util.TimeUtils;
27 import android.view.IWindowId;
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.EventLogTags;
39 import com.android.server.UiThread;
40 import com.android.server.Watchdog;
41 import com.android.server.am.BatteryStatsService;
42 import com.android.server.display.DisplayManagerService;
43 import com.android.server.input.InputManagerService;
44 import com.android.server.power.PowerManagerService;
45 import com.android.server.power.ShutdownThread;
47 import android.Manifest;
48 import android.app.ActivityManager.StackBoxInfo;
49 import android.app.ActivityManagerNative;
50 import android.app.IActivityManager;
51 import android.app.StatusBarManager;
52 import android.app.admin.DevicePolicyManager;
53 import android.animation.ValueAnimator;
54 import android.content.BroadcastReceiver;
55 import android.content.Context;
56 import android.content.Intent;
57 import android.content.IntentFilter;
58 import android.content.pm.ActivityInfo;
59 import android.content.pm.PackageManager;
60 import android.content.res.CompatibilityInfo;
61 import android.content.res.Configuration;
62 import android.graphics.Bitmap;
63 import android.graphics.Bitmap.Config;
64 import android.graphics.Canvas;
65 import android.graphics.Matrix;
66 import android.graphics.PixelFormat;
67 import android.graphics.Point;
68 import android.graphics.Rect;
69 import android.graphics.RectF;
70 import android.graphics.Region;
71 import android.hardware.display.DisplayManager;
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.Process;
84 import android.os.RemoteException;
85 import android.os.ServiceManager;
86 import android.os.StrictMode;
87 import android.os.SystemClock;
88 import android.os.SystemProperties;
89 import android.os.Trace;
90 import android.os.WorkSource;
91 import android.provider.Settings;
92 import android.util.DisplayMetrics;
93 import android.util.EventLog;
94 import android.util.FloatMath;
95 import android.util.Log;
96 import android.util.SparseArray;
97 import android.util.Pair;
98 import android.util.Slog;
99 import android.util.SparseIntArray;
100 import android.util.TypedValue;
101 import android.view.Choreographer;
102 import android.view.Display;
103 import android.view.DisplayInfo;
104 import android.view.Gravity;
105 import android.view.IApplicationToken;
106 import android.view.IInputFilter;
107 import android.view.IMagnificationCallbacks;
108 import android.view.IOnKeyguardExitResult;
109 import android.view.IRotationWatcher;
110 import android.view.IWindow;
111 import android.view.IWindowManager;
112 import android.view.IWindowSession;
113 import android.view.InputChannel;
114 import android.view.InputDevice;
115 import android.view.InputEvent;
116 import android.view.InputEventReceiver;
117 import android.view.KeyEvent;
118 import android.view.MagnificationSpec;
119 import android.view.MotionEvent;
120 import android.view.Surface.OutOfResourcesException;
121 import android.view.Surface;
122 import android.view.SurfaceControl;
123 import android.view.SurfaceSession;
124 import android.view.View;
125 import android.view.ViewTreeObserver;
126 import android.view.WindowManager;
127 import android.view.WindowManagerGlobal;
128 import android.view.WindowManagerPolicy;
129 import android.view.WindowManager.LayoutParams;
130 import android.view.WindowManagerPolicy.FakeWindow;
131 import android.view.WindowManagerPolicy.PointerEventListener;
132 import android.view.animation.Animation;
133 import android.view.animation.AnimationUtils;
134 import android.view.animation.Transformation;
136 import java.io.BufferedWriter;
137 import java.io.DataInputStream;
139 import java.io.FileDescriptor;
140 import java.io.FileInputStream;
141 import java.io.FileNotFoundException;
142 import java.io.IOException;
143 import java.io.OutputStream;
144 import java.io.OutputStreamWriter;
145 import java.io.PrintWriter;
146 import java.io.StringWriter;
147 import java.net.Socket;
148 import java.text.DateFormat;
149 import java.util.ArrayList;
150 import java.util.Date;
151 import java.util.HashMap;
152 import java.util.HashSet;
153 import java.util.Iterator;
154 import java.util.List;
157 public class WindowManagerService extends IWindowManager.Stub
158 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs,
159 DisplayManagerService.WindowManagerFuncs, DisplayManager.DisplayListener {
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 = true;
191 static final boolean SHOW_SURFACE_ALLOC = false;
192 static final boolean SHOW_TRANSACTIONS = false;
193 static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
194 static final boolean HIDE_STACK_CRAWLS = true;
195 static final int LAYOUT_REPEAT_THRESHOLD = 4;
197 static final boolean PROFILE_ORIENTATION = false;
198 static final boolean localLOGV = DEBUG;
200 /** How much to multiply the policy's type layer, to reserve room
201 * for multiple windows of the same type and Z-ordering adjustment
202 * with TYPE_LAYER_OFFSET. */
203 static final int TYPE_LAYER_MULTIPLIER = 10000;
205 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
206 * or below others in the same layer. */
207 static final int TYPE_LAYER_OFFSET = 1000;
209 /** How much to increment the layer for each window, to reserve room
210 * for effect surfaces between them.
212 static final int WINDOW_LAYER_MULTIPLIER = 5;
215 * Dim surface layer is immediately below target window.
217 static final int LAYER_OFFSET_DIM = 1;
220 * Blur surface layer is immediately below dim layer.
222 static final int LAYER_OFFSET_BLUR = 2;
225 * FocusedStackFrame layer is immediately above focused window.
227 static final int LAYER_OFFSET_FOCUSED_STACK = 1;
230 * Animation thumbnail is as far as possible below the window above
231 * the thumbnail (or in other words as far as possible above the window
234 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1;
237 * Layer at which to put the rotation freeze snapshot.
239 static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1;
242 * Layer at which to put the mask for emulated screen sizes.
244 static final int MASK_LAYER = TYPE_LAYER_MULTIPLIER * 200;
246 /** The maximum length we will accept for a loaded animation duration:
247 * this is 10 seconds.
249 static final int MAX_ANIMATION_DURATION = 10*1000;
251 /** Amount of time (in milliseconds) to animate the fade-in-out transition for
252 * compatible windows.
254 static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
256 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
257 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
259 /** Amount of time (in milliseconds) to delay before declaring a starting window leaked. */
260 static final int STARTING_WINDOW_TIMEOUT_DURATION = 10000;
263 * If true, the window manager will do its own custom freezing and general
264 * management of the screen during rotation.
266 static final boolean CUSTOM_SCREEN_ROTATION = true;
268 // Maximum number of milliseconds to wait for input devices to be enumerated before
269 // proceding with safe mode detection.
270 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
272 // Default input dispatching timeout in nanoseconds.
273 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
275 /** Minimum value for createStack and resizeStack weight value */
276 public static final float STACK_WEIGHT_MIN = 0.2f;
278 /** Maximum value for createStack and resizeStack weight value */
279 public static final float STACK_WEIGHT_MAX = 0.8f;
281 static final int UPDATE_FOCUS_NORMAL = 0;
282 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
283 static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
284 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
286 private static final String SYSTEM_SECURE = "ro.secure";
287 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
289 private static final String DENSITY_OVERRIDE = "ro.config.density_override";
290 private static final String SIZE_OVERRIDE = "ro.config.size_override";
292 private static final int MAX_SCREENSHOT_RETRIES = 3;
294 final private KeyguardDisableHandler mKeyguardDisableHandler;
296 private final boolean mHeadless;
298 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
300 public void onReceive(Context context, Intent intent) {
301 final String action = intent.getAction();
302 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
303 mKeyguardDisableHandler.sendEmptyMessage(
304 KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED);
309 // Current user when multi-user is enabled. Don't show windows of non-current user.
312 final Context mContext;
314 final boolean mHaveInputMethods;
316 final boolean mAllowBootMessages;
318 final boolean mLimitedAlphaCompositing;
320 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
322 final IActivityManager mActivityManager;
324 final IBatteryStats mBatteryStats;
326 final AppOpsManager mAppOps;
328 final DisplaySettings mDisplaySettings;
331 * All currently active sessions with clients.
333 final HashSet<Session> mSessions = new HashSet<Session>();
336 * Mapping from an IWindow IBinder to the server's Window object.
337 * This is also used as the lock for all of our state.
338 * NOTE: Never call into methods that lock ActivityManagerService while holding this object.
340 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
343 * Mapping from a token IBinder to a WindowToken object.
345 final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>();
348 * List of window tokens that have finished starting their application,
349 * and now need to have the policy remove their windows.
351 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
354 * Fake windows added to the window manager. Note: ordered from top to
355 * bottom, opposite of mWindows.
357 final ArrayList<FakeWindowImpl> mFakeWindows = new ArrayList<FakeWindowImpl>();
360 * Windows that are being resized. Used so we can tell the client about
361 * the resize after closing the transaction in which we resized the
362 * underlying surface.
364 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
367 * Windows whose animations have ended and now must be removed.
369 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
372 * Used when processing mPendingRemove to avoid working on the original array.
374 WindowState[] mPendingRemoveTmp = new WindowState[20];
377 * Windows whose surface should be destroyed.
379 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
382 * Windows that have lost input focus and are waiting for the new
383 * focus window to be displayed before they are told about this.
385 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
388 * This is set when we have run out of memory, and will either be an empty
389 * list or contain windows that need to be force removed.
391 ArrayList<WindowState> mForceRemoves;
394 * Windows that clients are waiting to have drawn.
396 ArrayList<Pair<WindowState, IRemoteCallback>> mWaitingForDrawn
397 = new ArrayList<Pair<WindowState, IRemoteCallback>>();
400 * Windows that have called relayout() while we were running animations,
401 * so we need to tell when the animation is done.
403 final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>();
406 * Used when rebuilding window list to keep track of windows that have
409 WindowState[] mRebuildTmp = new WindowState[20];
411 IInputMethodManager mInputMethodManager;
413 DisplayMagnifier mDisplayMagnifier;
415 final SurfaceSession mFxSession;
416 Watermark mWatermark;
417 StrictModeFlash mStrictModeFlash;
418 FocusedStackFrame mFocusedStackFrame;
420 int mFocusedStackLayer;
422 final float[] mTmpFloats = new float[9];
423 final Rect mTmpContentRect = new Rect();
425 boolean mDisplayReady;
427 boolean mDisplayEnabled = false;
428 boolean mSystemBooted = false;
429 boolean mForceDisplayEnabled = false;
430 boolean mShowingBootMessages = false;
432 String mLastANRState;
434 /** All DisplayContents in the world, kept here */
435 SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(2);
438 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
439 boolean mAltOrientation = false;
440 ArrayList<IRotationWatcher> mRotationWatchers
441 = new ArrayList<IRotationWatcher>();
442 int mDeferredRotationPauseCount;
444 int mSystemDecorLayer = 0;
445 final Rect mScreenRect = new Rect();
447 boolean mTraversalScheduled = false;
448 boolean mDisplayFrozen = false;
449 long mDisplayFreezeTime = 0;
450 int mLastDisplayFreezeDuration = 0;
451 Object mLastFinishedFreezeSource = null;
452 boolean mWaitingForConfig = false;
453 boolean mWindowsFreezingScreen = false;
454 boolean mClientFreezingScreen = false;
455 int mAppsFreezingScreen = 0;
456 int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
460 int mLastStatusBarVisibility = 0;
462 // State while inside of layoutAndPlaceSurfacesLocked().
463 boolean mFocusMayChange;
465 Configuration mCurConfiguration = new Configuration();
467 // This is held as long as we have the screen frozen, to give us time to
468 // perform a rotation animation when turning off shows the lock screen which
469 // changes the orientation.
470 private final PowerManager.WakeLock mScreenFrozenLock;
472 final AppTransition mAppTransition;
473 boolean mStartingIconInTransition = false;
474 boolean mSkipAppTransitionAnimation = false;
476 final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
477 final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
479 boolean mIsTouchDevice;
481 final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
482 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
483 final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
484 final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
486 final H mH = new H();
488 final Choreographer mChoreographer = Choreographer.getInstance();
490 WindowState mCurrentFocus = null;
491 WindowState mLastFocus = null;
493 /** This just indicates the window the input method is on top of, not
494 * necessarily the window its input is going to. */
495 WindowState mInputMethodTarget = null;
497 /** If true hold off on modifying the animation layer of mInputMethodTarget */
498 boolean mInputMethodTargetWaitingAnim;
499 int mInputMethodAnimLayerAdjustment;
501 WindowState mInputMethodWindow = null;
502 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
504 boolean mHardKeyboardAvailable;
505 boolean mHardKeyboardEnabled;
506 OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
508 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
510 // If non-null, this is the currently visible window that is associated
511 // with the wallpaper.
512 WindowState mWallpaperTarget = null;
513 // If non-null, we are in the middle of animating from one wallpaper target
514 // to another, and this is the lower one in Z-order.
515 WindowState mLowerWallpaperTarget = null;
516 // If non-null, we are in the middle of animating from one wallpaper target
517 // to another, and this is the higher one in Z-order.
518 WindowState mUpperWallpaperTarget = null;
519 int mWallpaperAnimLayerAdjustment;
520 float mLastWallpaperX = -1;
521 float mLastWallpaperY = -1;
522 float mLastWallpaperXStep = -1;
523 float mLastWallpaperYStep = -1;
524 // This is set when we are waiting for a wallpaper to tell us it is done
525 // changing its scroll position.
526 WindowState mWaitingOnWallpaper;
527 // The last time we had a timeout when waiting for a wallpaper.
528 long mLastWallpaperTimeoutTime;
529 // We give a wallpaper up to 150ms to finish scrolling.
530 static final long WALLPAPER_TIMEOUT = 150;
531 // Time we wait after a timeout before trying to wait again.
532 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
534 AppWindowToken mFocusedApp = null;
536 PowerManagerService mPowerManager;
538 float mWindowAnimationScale = 1.0f;
539 float mTransitionAnimationScale = 1.0f;
540 float mAnimatorDurationScale = 1.0f;
542 final InputManagerService mInputManager;
543 final DisplayManagerService mDisplayManagerService;
544 final DisplayManager mDisplayManager;
546 // Who is holding the screen on.
547 Session mHoldingScreenOn;
548 PowerManager.WakeLock mHoldingScreenWakeLock;
550 boolean mTurnOnScreen;
552 DragState mDragState = null;
554 // For frozen screen animations.
555 int mExitAnimId, mEnterAnimId;
557 /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple
560 static final int SET_UPDATE_ROTATION = 1 << 0;
561 static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1;
562 static final int SET_FORCE_HIDING_CHANGED = 1 << 2;
563 static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 3;
564 static final int SET_TURN_ON_SCREEN = 1 << 4;
565 static final int SET_WALLPAPER_ACTION_PENDING = 1 << 5;
567 boolean mWallpaperForceHidingChanged = false;
568 boolean mWallpaperMayChange = false;
569 boolean mOrientationChangeComplete = true;
570 Object mLastWindowFreezeSource = null;
571 private Session mHoldScreen = null;
572 private boolean mObscured = false;
573 private boolean mSyswin = false;
574 private float mScreenBrightness = -1;
575 private float mButtonBrightness = -1;
576 private long mUserActivityTimeout = -1;
577 private boolean mUpdateRotation = false;
578 boolean mWallpaperActionPending = false;
580 private static final int DISPLAY_CONTENT_UNKNOWN = 0;
581 private static final int DISPLAY_CONTENT_MIRROR = 1;
582 private static final int DISPLAY_CONTENT_UNIQUE = 2;
583 private int mDisplayHasContent = DISPLAY_CONTENT_UNKNOWN;
585 final LayoutFields mInnerFields = new LayoutFields();
587 boolean mAnimationScheduled;
589 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
590 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
591 private int mTransactionSequence;
593 /** Only do a maximum of 6 repeated layouts. After that quit */
594 private int mLayoutRepeatCount;
596 final WindowAnimator mAnimator;
598 SparseArray<Task> mTaskIdToTask = new SparseArray<Task>();
599 SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>();
601 private final PointerEventDispatcher mPointerEventDispatcher;
603 final class DragInputEventReceiver extends InputEventReceiver {
604 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
605 super(inputChannel, looper);
609 public void onInputEvent(InputEvent event) {
610 boolean handled = false;
612 if (event instanceof MotionEvent
613 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
614 && mDragState != null) {
615 final MotionEvent motionEvent = (MotionEvent)event;
616 boolean endDrag = false;
617 final float newX = motionEvent.getRawX();
618 final float newY = motionEvent.getRawY();
620 switch (motionEvent.getAction()) {
621 case MotionEvent.ACTION_DOWN: {
623 Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer");
627 case MotionEvent.ACTION_MOVE: {
628 synchronized (mWindowMap) {
629 // move the surface and tell the involved window(s) where we are
630 mDragState.notifyMoveLw(newX, newY);
634 case MotionEvent.ACTION_UP: {
635 if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at "
636 + newX + "," + newY);
637 synchronized (mWindowMap) {
638 endDrag = mDragState.notifyDropLw(newX, newY);
642 case MotionEvent.ACTION_CANCEL: {
643 if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!");
649 if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state");
650 // tell all the windows that the drag has ended
651 synchronized (mWindowMap) {
652 mDragState.endDragLw();
658 } catch (Exception e) {
659 Slog.e(TAG, "Exception caught by drag handleMotion", e);
661 finishInputEvent(event, handled);
667 * Whether the UI is currently running in touch mode (not showing
668 * navigational focus because the user is directly pressing the screen).
670 boolean mInTouchMode = true;
672 private ViewServer mViewServer;
673 private final ArrayList<WindowChangeListener> mWindowChangeListeners =
674 new ArrayList<WindowChangeListener>();
675 private boolean mWindowsChanged = false;
677 public interface WindowChangeListener {
678 public void windowsChanged();
679 public void focusChanged();
682 final Configuration mTempConfiguration = new Configuration();
684 // The desired scaling factor for compatible apps.
685 float mCompatibleScreenScale;
687 // If true, only the core apps and services are being launched because the device
688 // is in a special boot mode, such as being encrypted or waiting for a decryption password.
689 // For example, when this flag is true, there will be no wallpaper service.
690 final boolean mOnlyCore;
692 public static WindowManagerService main(final Context context,
693 final PowerManagerService pm, final DisplayManagerService dm,
694 final InputManagerService im, final Handler wmHandler,
695 final boolean haveInputMethods, final boolean showBootMsgs,
696 final boolean onlyCore) {
697 final WindowManagerService[] holder = new WindowManagerService[1];
698 wmHandler.runWithScissors(new Runnable() {
701 holder[0] = new WindowManagerService(context, pm, dm, im,
702 haveInputMethods, showBootMsgs, onlyCore);
708 private void initPolicy(Handler uiHandler) {
709 uiHandler.runWithScissors(new Runnable() {
712 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
714 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
715 mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer()
716 * TYPE_LAYER_MULTIPLIER
722 private WindowManagerService(Context context, PowerManagerService pm,
723 DisplayManagerService displayManager, InputManagerService inputManager,
724 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
726 mHaveInputMethods = haveInputMethods;
727 mAllowBootMessages = showBootMsgs;
728 mOnlyCore = onlyCore;
729 mLimitedAlphaCompositing = context.getResources().getBoolean(
730 com.android.internal.R.bool.config_sf_limitedAlpha);
731 mInputManager = inputManager; // Must be before createDisplayContentLocked.
732 mDisplayManagerService = displayManager;
733 mHeadless = displayManager.isHeadless();
734 mDisplaySettings = new DisplaySettings(context);
735 mDisplaySettings.readSettingsLocked();
737 mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG));
739 mFxSession = new SurfaceSession();
740 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
741 mDisplayManager.registerDisplayListener(this, null);
742 Display[] displays = mDisplayManager.getDisplays();
743 for (Display display : displays) {
744 createDisplayContentLocked(display);
747 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
750 mPowerManager.setPolicy(mPolicy);
751 PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
752 mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
753 mScreenFrozenLock.setReferenceCounted(false);
755 mAppTransition = new AppTransition(context, mH);
757 mActivityManager = ActivityManagerNative.getDefault();
758 mBatteryStats = BatteryStatsService.getService();
759 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
760 mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null,
761 new AppOpsManager.OnOpChangedInternalListener() {
763 public void onOpChanged(int op, String packageName) {
769 // Get persisted window scale setting
770 mWindowAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
771 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
772 mTransitionAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
773 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
774 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
775 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale));
777 // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
778 IntentFilter filter = new IntentFilter();
779 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
780 mContext.registerReceiver(mBroadcastReceiver, filter);
782 mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
783 | PowerManager.ON_AFTER_RELEASE, TAG);
784 mHoldingScreenWakeLock.setReferenceCounted(false);
786 mAnimator = new WindowAnimator(this);
788 initPolicy(UiThread.getHandler());
790 // Add ourself to the Watchdog monitors.
791 Watchdog.getInstance().addMonitor(this);
793 SurfaceControl.openTransaction();
795 createWatermarkInTransaction();
796 mFocusedStackFrame = new FocusedStackFrame(
797 getDefaultDisplayContentLocked().getDisplay(), mFxSession);
799 SurfaceControl.closeTransaction();
803 public InputMonitor getInputMonitor() {
804 return mInputMonitor;
808 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
809 throws RemoteException {
811 return super.onTransact(code, data, reply, flags);
812 } catch (RuntimeException e) {
813 // The window manager only throws security exceptions, so let's
815 if (!(e instanceof SecurityException)) {
816 Slog.wtf(TAG, "Window Manager Crash", e);
822 private void placeWindowAfter(WindowState pos, WindowState window) {
823 final WindowList windows = pos.getWindowList();
824 final int i = windows.indexOf(pos);
825 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
826 TAG, "Adding window " + window + " at "
827 + (i+1) + " of " + windows.size() + " (after " + pos + ")");
828 windows.add(i+1, window);
829 mWindowsChanged = true;
832 private void placeWindowBefore(WindowState pos, WindowState window) {
833 final WindowList windows = pos.getWindowList();
834 int i = windows.indexOf(pos);
835 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
836 TAG, "Adding window " + window + " at "
837 + i + " of " + windows.size() + " (before " + pos + ")");
839 Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows);
842 windows.add(i, window);
843 mWindowsChanged = true;
846 //This method finds out the index of a window that has the same app token as
847 //win. used for z ordering the windows in mWindows
848 private int findIdxBasedOnAppTokens(WindowState win) {
849 WindowList windows = win.getWindowList();
850 for(int j = windows.size() - 1; j >= 0; j--) {
851 WindowState wentry = windows.get(j);
852 if(wentry.mAppToken == win.mAppToken) {
860 * Return the list of Windows from the passed token on the given Display.
861 * @param token The token with all the windows.
862 * @param displayContent The display we are interested in.
863 * @return List of windows from token that are on displayContent.
865 WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) {
866 final WindowList windowList = new WindowList();
867 final int count = token.windows.size();
868 for (int i = 0; i < count; i++) {
869 final WindowState win = token.windows.get(i);
870 if (win.mDisplayContent == displayContent) {
878 * Recursive search through a WindowList and all of its windows' children.
879 * @param targetWin The window to search for.
880 * @param windows The list to search.
881 * @return The index of win in windows or of the window that is an ancestor of win.
883 private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) {
884 for (int i = windows.size() - 1; i >= 0; i--) {
885 final WindowState w = windows.get(i);
886 if (w == targetWin) {
889 if (!w.mChildWindows.isEmpty()) {
890 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) {
898 private int addAppWindowToListLocked(final WindowState win) {
899 final IWindow client = win.mClient;
900 final WindowToken token = win.mToken;
901 final DisplayContent displayContent = win.mDisplayContent;
903 final WindowList windows = win.getWindowList();
904 final int N = windows.size();
905 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
906 int tokenWindowsPos = 0;
907 int windowListPos = tokenWindowList.size();
908 if (!tokenWindowList.isEmpty()) {
909 // If this application has existing windows, we
910 // simply place the new window on top of them... but
911 // keep the starting window on top.
912 if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
913 // Base windows go behind everything else.
914 WindowState lowestWindow = tokenWindowList.get(0);
915 placeWindowBefore(lowestWindow, win);
916 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows);
918 AppWindowToken atoken = win.mAppToken;
919 WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
920 if (atoken != null && lastWindow == atoken.startingWindow) {
921 placeWindowBefore(lastWindow, win);
922 tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows);
924 int newIdx = findIdxBasedOnAppTokens(win);
925 //there is a window above this one associated with the same
926 //apptoken note that the window could be a floating window
927 //that was created later or a window at the top of the list of
928 //windows associated with this token.
929 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
930 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " +
932 windows.add(newIdx + 1, win);
934 // No window from token found on win's display.
937 tokenWindowsPos = indexOfWinInWindowList(
938 windows.get(newIdx), token.windows) + 1;
940 mWindowsChanged = true;
943 return tokenWindowsPos;
946 // No windows from this token on this display
947 if (localLOGV) Slog.v(TAG, "Figuring out where to add app window " + client.asBinder()
948 + " (token=" + token + ")");
949 // Figure out where the window should go, based on the
950 // order of applications.
951 WindowState pos = null;
953 final ArrayList<Task> tasks = displayContent.getTasks();
956 for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
957 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
958 for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
959 final AppWindowToken t = tokens.get(tokenNdx);
965 tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1;
971 // We haven't reached the token yet; if this token
972 // is not going to the bottom and has windows on this display, we can
973 // use it as an anchor for when we do reach the token.
974 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
975 if (!t.sendingToBottom && tokenWindowList.size() > 0) {
976 pos = tokenWindowList.get(0);
985 // We now know the index into the apps. If we found
986 // an app window above, that gives us the position; else
987 // we need to look some more.
989 // Move behind any windows attached to this one.
990 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
991 if (atoken != null) {
993 getTokenWindowsOnDisplay(atoken, displayContent);
994 final int NC = tokenWindowList.size();
996 WindowState bottom = tokenWindowList.get(0);
997 if (bottom.mSubLayer < 0) {
1002 placeWindowBefore(pos, win);
1003 return tokenWindowsPos;
1006 // Continue looking down until we find the first
1007 // token that has windows on this display.
1008 for ( ; taskNdx >= 0; --taskNdx) {
1009 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
1010 for ( ; tokenNdx >= 0; --tokenNdx) {
1011 final AppWindowToken t = tokens.get(tokenNdx);
1012 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
1013 final int NW = tokenWindowList.size();
1015 pos = tokenWindowList.get(NW-1);
1019 if (tokenNdx >= 0) {
1026 // Move in front of any windows attached to this
1028 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
1029 if (atoken != null) {
1030 final int NC = atoken.windows.size();
1032 WindowState top = atoken.windows.get(NC-1);
1033 if (top.mSubLayer >= 0) {
1038 placeWindowAfter(pos, win);
1039 return tokenWindowsPos;
1042 // Just search for the start of this layer.
1043 final int myLayer = win.mBaseLayer;
1045 for (i = 0; i < N; i++) {
1046 WindowState w = windows.get(i);
1047 if (w.mBaseLayer > myLayer) {
1051 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
1052 "Based on layer: Adding window " + win + " at " + i + " of " + N);
1053 windows.add(i, win);
1054 mWindowsChanged = true;
1055 return tokenWindowsPos;
1058 private void addFreeWindowToListLocked(final WindowState win) {
1059 final WindowList windows = win.getWindowList();
1061 // Figure out where window should go, based on layer.
1062 final int myLayer = win.mBaseLayer;
1064 for (i = windows.size() - 1; i >= 0; i--) {
1065 if (windows.get(i).mBaseLayer <= myLayer) {
1070 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
1071 "Free window: Adding window " + win + " at " + i + " of " + windows.size());
1072 windows.add(i, win);
1073 mWindowsChanged = true;
1076 private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) {
1077 final WindowToken token = win.mToken;
1078 final DisplayContent displayContent = win.mDisplayContent;
1079 final WindowState attached = win.mAttachedWindow;
1081 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
1083 // Figure out this window's ordering relative to the window
1084 // it is attached to.
1085 final int NA = tokenWindowList.size();
1086 final int sublayer = win.mSubLayer;
1087 int largestSublayer = Integer.MIN_VALUE;
1088 WindowState windowWithLargestSublayer = null;
1090 for (i = 0; i < NA; i++) {
1091 WindowState w = tokenWindowList.get(i);
1092 final int wSublayer = w.mSubLayer;
1093 if (wSublayer >= largestSublayer) {
1094 largestSublayer = wSublayer;
1095 windowWithLargestSublayer = w;
1098 // For negative sublayers, we go below all windows
1099 // in the same sublayer.
1100 if (wSublayer >= sublayer) {
1102 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1103 token.windows.add(i, win);
1105 placeWindowBefore(wSublayer >= 0 ? attached : w, win);
1109 // For positive sublayers, we go above all windows
1110 // in the same sublayer.
1111 if (wSublayer > sublayer) {
1113 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1114 token.windows.add(i, win);
1116 placeWindowBefore(w, win);
1123 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1124 token.windows.add(win);
1127 placeWindowBefore(attached, win);
1129 placeWindowAfter(largestSublayer >= 0
1130 ? windowWithLargestSublayer
1137 private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) {
1138 if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win +
1139 " Callers=" + Debug.getCallers(4));
1140 if (win.mAttachedWindow == null) {
1141 final WindowToken token = win.mToken;
1142 int tokenWindowsPos = 0;
1143 if (token.appWindowToken != null) {
1144 tokenWindowsPos = addAppWindowToListLocked(win);
1146 addFreeWindowToListLocked(win);
1149 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1150 token.windows.add(tokenWindowsPos, win);
1153 addAttachedWindowToListLocked(win, addToToken);
1156 if (win.mAppToken != null && addToToken) {
1157 win.mAppToken.allAppWindows.add(win);
1161 static boolean canBeImeTarget(WindowState w) {
1162 final int fl = w.mAttrs.flags
1163 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
1164 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)
1165 || w.mAttrs.type == TYPE_APPLICATION_STARTING) {
1166 if (DEBUG_INPUT_METHOD) {
1167 Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
1168 if (!w.isVisibleOrAdding()) {
1169 Slog.i(TAG, " mSurface=" + w.mWinAnimator.mSurfaceControl
1170 + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility
1171 + " policyVis=" + w.mPolicyVisibility
1172 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
1173 + " attachHid=" + w.mAttachedHidden
1174 + " exiting=" + w.mExiting + " destroying=" + w.mDestroying);
1175 if (w.mAppToken != null) {
1176 Slog.i(TAG, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
1180 return w.isVisibleOrAdding();
1186 * Dig through the WindowStates and find the one that the Input Method will target.
1188 * @return The index+1 in mWindows of the discovered target.
1190 int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
1191 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
1192 // same display. Or even when the current IME/target are not on the same screen as the next
1193 // IME/target. For now only look for input windows on the main screen.
1194 WindowList windows = getDefaultWindowListLocked();
1195 WindowState w = null;
1197 for (i = windows.size() - 1; i >= 0; --i) {
1198 WindowState win = windows.get(i);
1200 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i
1201 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
1202 if (canBeImeTarget(win)) {
1204 //Slog.i(TAG, "Putting input method here!");
1206 // Yet more tricksyness! If this window is a "starting"
1207 // window, we do actually want to be on top of it, but
1208 // it is not -really- where input will go. So if the caller
1209 // is not actually looking to move the IME, look down below
1210 // for a real window to target...
1212 && w.mAttrs.type == TYPE_APPLICATION_STARTING
1214 WindowState wb = windows.get(i-1);
1215 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
1224 // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
1226 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w);
1228 // Now, a special case -- if the last target's window is in the
1229 // process of exiting, and is above the new target, keep on the
1230 // last target to avoid flicker. Consider for example a Dialog with
1231 // the IME shown: when the Dialog is dismissed, we want to keep
1232 // the IME above it until it is completely gone so it doesn't drop
1233 // behind the dialog or its full-screen scrim.
1234 final WindowState curTarget = mInputMethodTarget;
1235 if (curTarget != null
1236 && curTarget.isDisplayedLw()
1237 && curTarget.isClosing()
1238 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
1239 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing");
1240 return windows.indexOf(curTarget) + 1;
1243 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
1244 + w + " willMove=" + willMove);
1246 if (willMove && w != null) {
1247 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
1248 if (token != null) {
1250 // Now some fun for dealing with window animations that
1251 // modify the Z order. We need to look at all windows below
1252 // the current target that are in this app, finding the highest
1253 // visible one in layering.
1254 WindowState highestTarget = null;
1256 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
1257 WindowList curWindows = curTarget.getWindowList();
1258 int pos = curWindows.indexOf(curTarget);
1260 WindowState win = curWindows.get(pos);
1261 if (win.mAppToken != token) {
1264 if (!win.mRemoved) {
1265 if (highestTarget == null || win.mWinAnimator.mAnimLayer >
1266 highestTarget.mWinAnimator.mAnimLayer) {
1267 highestTarget = win;
1275 if (highestTarget != null) {
1276 if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget
1277 + " animating=" + highestTarget.mWinAnimator.isAnimating()
1278 + " layer=" + highestTarget.mWinAnimator.mAnimLayer
1279 + " new layer=" + w.mWinAnimator.mAnimLayer);
1281 if (mAppTransition.isTransitionSet()) {
1282 // If we are currently setting up for an animation,
1283 // hold everything until we can find out what will happen.
1284 mInputMethodTargetWaitingAnim = true;
1285 mInputMethodTarget = highestTarget;
1286 return highestPos + 1;
1287 } else if (highestTarget.mWinAnimator.isAnimating() &&
1288 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
1289 // If the window we are currently targeting is involved
1290 // with an animation, and it is on top of the next target
1291 // we will be over, then hold off on moving until
1293 mInputMethodTargetWaitingAnim = true;
1294 mInputMethodTarget = highestTarget;
1295 return highestPos + 1;
1301 //Slog.i(TAG, "Placing input method @" + (i+1));
1304 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to "
1305 + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
1306 mInputMethodTarget = w;
1307 mInputMethodTargetWaitingAnim = false;
1308 if (w.mAppToken != null) {
1309 setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment);
1311 setInputMethodAnimLayerAdjustment(0);
1317 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null."
1318 + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
1319 mInputMethodTarget = null;
1320 setInputMethodAnimLayerAdjustment(0);
1325 void addInputMethodWindowToListLocked(WindowState win) {
1326 int pos = findDesiredInputMethodWindowIndexLocked(true);
1328 win.mTargetAppToken = mInputMethodTarget.mAppToken;
1329 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
1330 TAG, "Adding input method window " + win + " at " + pos);
1331 // TODO(multidisplay): IMEs are only supported on the default display.
1332 getDefaultWindowListLocked().add(pos, win);
1333 mWindowsChanged = true;
1334 moveInputMethodDialogsLocked(pos+1);
1337 win.mTargetAppToken = null;
1338 addWindowToListInOrderLocked(win, true);
1339 moveInputMethodDialogsLocked(pos);
1342 void setInputMethodAnimLayerAdjustment(int adj) {
1343 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj);
1344 mInputMethodAnimLayerAdjustment = adj;
1345 WindowState imw = mInputMethodWindow;
1347 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
1348 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
1349 + " anim layer: " + imw.mWinAnimator.mAnimLayer);
1350 int wi = imw.mChildWindows.size();
1353 WindowState cw = imw.mChildWindows.get(wi);
1354 cw.mWinAnimator.mAnimLayer = cw.mLayer + adj;
1355 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw
1356 + " anim layer: " + cw.mWinAnimator.mAnimLayer);
1359 int di = mInputMethodDialogs.size();
1362 imw = mInputMethodDialogs.get(di);
1363 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
1364 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
1365 + " anim layer: " + imw.mWinAnimator.mAnimLayer);
1369 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1370 WindowList windows = win.getWindowList();
1371 int wpos = windows.indexOf(win);
1373 if (wpos < interestingPos) interestingPos--;
1374 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
1375 windows.remove(wpos);
1376 mWindowsChanged = true;
1377 int NC = win.mChildWindows.size();
1380 WindowState cw = win.mChildWindows.get(NC);
1381 int cpos = windows.indexOf(cw);
1383 if (cpos < interestingPos) interestingPos--;
1384 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
1385 + cpos + ": " + cw);
1386 windows.remove(cpos);
1390 return interestingPos;
1393 private void reAddWindowToListInOrderLocked(WindowState win) {
1394 addWindowToListInOrderLocked(win, false);
1395 // This is a hack to get all of the child windows added as well
1396 // at the right position. Child windows should be rare and
1397 // this case should be rare, so it shouldn't be that big a deal.
1398 WindowList windows = win.getWindowList();
1399 int wpos = windows.indexOf(win);
1401 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win);
1402 windows.remove(wpos);
1403 mWindowsChanged = true;
1404 reAddWindowLocked(wpos, win);
1408 void logWindowList(final WindowList windows, String prefix) {
1409 int N = windows.size();
1412 Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N));
1416 void moveInputMethodDialogsLocked(int pos) {
1417 ArrayList<WindowState> dialogs = mInputMethodDialogs;
1419 // TODO(multidisplay): IMEs are only supported on the default display.
1420 WindowList windows = getDefaultWindowListLocked();
1421 final int N = dialogs.size();
1422 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
1423 for (int i=0; i<N; i++) {
1424 pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1426 if (DEBUG_INPUT_METHOD) {
1427 Slog.v(TAG, "Window list w/pos=" + pos);
1428 logWindowList(windows, " ");
1432 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1433 if (pos < windows.size()) {
1434 WindowState wp = windows.get(pos);
1435 if (wp == mInputMethodWindow) {
1439 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
1440 for (int i=0; i<N; i++) {
1441 WindowState win = dialogs.get(i);
1442 win.mTargetAppToken = targetAppToken;
1443 pos = reAddWindowLocked(pos, win);
1445 if (DEBUG_INPUT_METHOD) {
1446 Slog.v(TAG, "Final window list:");
1447 logWindowList(windows, " ");
1451 for (int i=0; i<N; i++) {
1452 WindowState win = dialogs.get(i);
1453 win.mTargetAppToken = null;
1454 reAddWindowToListInOrderLocked(win);
1455 if (DEBUG_INPUT_METHOD) {
1456 Slog.v(TAG, "No IM target, final list:");
1457 logWindowList(windows, " ");
1462 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1463 final WindowState imWin = mInputMethodWindow;
1464 final int DN = mInputMethodDialogs.size();
1465 if (imWin == null && DN == 0) {
1469 // TODO(multidisplay): IMEs are only supported on the default display.
1470 WindowList windows = getDefaultWindowListLocked();
1472 int imPos = findDesiredInputMethodWindowIndexLocked(true);
1474 // In this case, the input method windows are to be placed
1475 // immediately above the window they are targeting.
1477 // First check to see if the input method windows are already
1478 // located here, and contiguous.
1479 final int N = windows.size();
1480 WindowState firstImWin = imPos < N
1481 ? windows.get(imPos) : null;
1483 // Figure out the actual input method window that should be
1484 // at the bottom of their stack.
1485 WindowState baseImWin = imWin != null
1486 ? imWin : mInputMethodDialogs.get(0);
1487 if (baseImWin.mChildWindows.size() > 0) {
1488 WindowState cw = baseImWin.mChildWindows.get(0);
1489 if (cw.mSubLayer < 0) baseImWin = cw;
1492 if (firstImWin == baseImWin) {
1493 // The windows haven't moved... but are they still contiguous?
1494 // First find the top IM window.
1497 if (!(windows.get(pos)).mIsImWindow) {
1503 // Now there should be no more input method windows above.
1505 if ((windows.get(pos)).mIsImWindow) {
1512 // The IM target window may be changed, so update the mTargetAppToken.
1513 if (imWin != null) {
1514 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1520 if (imWin != null) {
1521 if (DEBUG_INPUT_METHOD) {
1522 Slog.v(TAG, "Moving IM from " + imPos);
1523 logWindowList(windows, " ");
1525 imPos = tmpRemoveWindowLocked(imPos, imWin);
1526 if (DEBUG_INPUT_METHOD) {
1527 Slog.v(TAG, "List after removing with new pos " + imPos + ":");
1528 logWindowList(windows, " ");
1530 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1531 reAddWindowLocked(imPos, imWin);
1532 if (DEBUG_INPUT_METHOD) {
1533 Slog.v(TAG, "List after moving IM to " + imPos + ":");
1534 logWindowList(windows, " ");
1536 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1538 moveInputMethodDialogsLocked(imPos);
1542 // In this case, the input method windows go in a fixed layer,
1543 // because they aren't currently associated with a focus window.
1545 if (imWin != null) {
1546 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos);
1547 tmpRemoveWindowLocked(0, imWin);
1548 imWin.mTargetAppToken = null;
1549 reAddWindowToListInOrderLocked(imWin);
1550 if (DEBUG_INPUT_METHOD) {
1551 Slog.v(TAG, "List with no IM target:");
1552 logWindowList(windows, " ");
1554 if (DN > 0) moveInputMethodDialogsLocked(-1);
1556 moveInputMethodDialogsLocked(-1);
1561 if (needAssignLayers) {
1562 assignLayersLocked(windows);
1568 final boolean isWallpaperVisible(WindowState wallpaperTarget) {
1569 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
1570 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
1571 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
1572 ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
1573 + " upper=" + mUpperWallpaperTarget
1574 + " lower=" + mLowerWallpaperTarget);
1575 return (wallpaperTarget != null
1576 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
1577 && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
1578 || mUpperWallpaperTarget != null
1579 || mLowerWallpaperTarget != null;
1582 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
1583 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
1585 int adjustWallpaperWindowsLocked() {
1586 mInnerFields.mWallpaperMayChange = false;
1587 boolean targetChanged = false;
1589 // TODO(multidisplay): Wallpapers on main screen only.
1590 final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo();
1591 final int dw = displayInfo.logicalWidth;
1592 final int dh = displayInfo.logicalHeight;
1594 // First find top-most window that has asked to be on top of the
1595 // wallpaper; all wallpapers go behind it.
1596 final WindowList windows = getDefaultWindowListLocked();
1597 int N = windows.size();
1598 WindowState w = null;
1599 WindowState foundW = null;
1601 WindowState topCurW = null;
1603 int windowDetachedI = -1;
1608 if ((w.mAttrs.type == TYPE_WALLPAPER)) {
1609 if (topCurW == null) {
1616 if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
1617 // If this window's app token is hidden and not animating,
1618 // it is of no interest to us.
1619 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
1620 if (DEBUG_WALLPAPER) Slog.v(TAG,
1621 "Skipping hidden and not animating token: " + w);
1625 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
1626 + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
1627 if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isOnScreen()
1628 && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
1629 if (DEBUG_WALLPAPER) Slog.v(TAG,
1630 "Found wallpaper target: #" + i + "=" + w);
1633 if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) {
1634 // The current wallpaper target is animating, so we'll
1635 // look behind it for another possible target and figure
1636 // out what is going on below.
1637 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
1638 + ": token animating, looking behind.");
1642 } else if (w == mAnimator.mWindowDetachedWallpaper) {
1643 windowDetachedI = i;
1647 if (foundW == null && windowDetachedI >= 0) {
1648 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
1649 "Found animating detached wallpaper activity: #" + i + "=" + w);
1651 foundI = windowDetachedI;
1654 if (mWallpaperTarget != foundW
1655 && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) {
1656 if (DEBUG_WALLPAPER_LIGHT) {
1657 Slog.v(TAG, "New wallpaper target: " + foundW
1658 + " oldTarget: " + mWallpaperTarget);
1661 mLowerWallpaperTarget = null;
1662 mUpperWallpaperTarget = null;
1664 WindowState oldW = mWallpaperTarget;
1665 mWallpaperTarget = foundW;
1666 targetChanged = true;
1668 // Now what is happening... if the current and new targets are
1669 // animating, then we are in our super special mode!
1670 if (foundW != null && oldW != null) {
1671 boolean oldAnim = oldW.isAnimatingLw();
1672 boolean foundAnim = foundW.isAnimatingLw();
1673 if (DEBUG_WALLPAPER_LIGHT) {
1674 Slog.v(TAG, "New animation: " + foundAnim
1675 + " old animation: " + oldAnim);
1677 if (foundAnim && oldAnim) {
1678 int oldI = windows.indexOf(oldW);
1679 if (DEBUG_WALLPAPER_LIGHT) {
1680 Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
1683 if (DEBUG_WALLPAPER_LIGHT) {
1684 Slog.v(TAG, "Animating wallpapers: old#" + oldI
1685 + "=" + oldW + "; new#" + foundI
1689 // Set the new target correctly.
1690 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
1691 if (DEBUG_WALLPAPER_LIGHT) {
1692 Slog.v(TAG, "Old wallpaper still the target.");
1694 mWallpaperTarget = oldW;
1698 // Now set the upper and lower wallpaper targets
1699 // correctly, and make sure that we are positioning
1700 // the wallpaper below the lower.
1701 else if (foundI > oldI) {
1702 // The new target is on top of the old one.
1703 if (DEBUG_WALLPAPER_LIGHT) {
1704 Slog.v(TAG, "Found target above old target.");
1706 mUpperWallpaperTarget = foundW;
1707 mLowerWallpaperTarget = oldW;
1711 // The new target is below the old one.
1712 if (DEBUG_WALLPAPER_LIGHT) {
1713 Slog.v(TAG, "Found target below old target.");
1715 mUpperWallpaperTarget = oldW;
1716 mLowerWallpaperTarget = foundW;
1722 } else if (mLowerWallpaperTarget != null) {
1723 // Is it time to stop animating?
1724 if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
1725 if (DEBUG_WALLPAPER_LIGHT) {
1726 Slog.v(TAG, "No longer animating wallpaper targets!");
1728 mLowerWallpaperTarget = null;
1729 mUpperWallpaperTarget = null;
1730 mWallpaperTarget = foundW;
1731 targetChanged = true;
1735 boolean visible = foundW != null;
1737 // The window is visible to the compositor... but is it visible
1738 // to the user? That is what the wallpaper cares about.
1739 visible = isWallpaperVisible(foundW);
1740 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
1742 // If the wallpaper target is animating, we may need to copy
1743 // its layer adjustment. Only do this if we are not transfering
1744 // between two wallpaper targets.
1745 mWallpaperAnimLayerAdjustment =
1746 (mLowerWallpaperTarget == null && foundW.mAppToken != null)
1747 ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0;
1749 final int maxLayer = mPolicy.getMaxWallpaperLayer()
1750 * TYPE_LAYER_MULTIPLIER
1751 + TYPE_LAYER_OFFSET;
1753 // Now w is the window we are supposed to be behind... but we
1754 // need to be sure to also be behind any of its attached windows,
1755 // AND any starting window associated with it, AND below the
1756 // maximum layer the policy allows for wallpapers.
1757 while (foundI > 0) {
1758 WindowState wb = windows.get(foundI-1);
1759 if (wb.mBaseLayer < maxLayer &&
1760 wb.mAttachedWindow != foundW &&
1761 (foundW.mAttachedWindow == null ||
1762 wb.mAttachedWindow != foundW.mAttachedWindow) &&
1763 (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
1764 foundW.mToken == null || wb.mToken != foundW.mToken)) {
1765 // This window is not related to the previous one in any
1766 // interesting way, so stop here.
1773 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
1776 if (foundW == null && topCurW != null) {
1777 // There is no wallpaper target, so it goes at the bottom.
1778 // We will assume it is the same place as last time, if known.
1782 // Okay i is the position immediately above the wallpaper. Look at
1783 // what is below it for later.
1784 foundW = foundI > 0 ? windows.get(foundI-1) : null;
1788 if (mWallpaperTarget.mWallpaperX >= 0) {
1789 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
1790 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
1792 if (mWallpaperTarget.mWallpaperY >= 0) {
1793 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
1794 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
1798 // Start stepping backwards from here, ensuring that our wallpaper windows
1799 // are correctly placed.
1801 int curTokenIndex = mWallpaperTokens.size();
1802 while (curTokenIndex > 0) {
1804 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1805 if (token.hidden == visible) {
1806 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
1807 "Wallpaper token " + token + " hidden=" + !visible);
1808 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
1809 token.hidden = !visible;
1810 // Need to do a layout to ensure the wallpaper now has the
1812 getDefaultDisplayContentLocked().layoutNeeded = true;
1815 int curWallpaperIndex = token.windows.size();
1816 while (curWallpaperIndex > 0) {
1817 curWallpaperIndex--;
1818 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1821 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
1824 // First, make sure the client has the current visibility
1826 dispatchWallpaperVisibility(wallpaper, visible);
1828 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
1829 if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
1830 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
1832 // First, if this window is at the current index, then all
1834 if (wallpaper == foundW) {
1837 ? windows.get(foundI-1) : null;
1841 // The window didn't match... the current wallpaper window,
1842 // wherever it is, is in the wrong place, so make sure it is
1844 int oldIndex = windows.indexOf(wallpaper);
1845 if (oldIndex >= 0) {
1846 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
1847 + oldIndex + ": " + wallpaper);
1848 windows.remove(oldIndex);
1849 mWindowsChanged = true;
1850 if (oldIndex < foundI) {
1856 if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
1857 Slog.v(TAG, "Moving wallpaper " + wallpaper
1858 + " from " + oldIndex + " to " + 0);
1861 windows.add(0, wallpaper);
1862 mWindowsChanged = true;
1863 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
1868 final TaskStack targetStack =
1869 mWallpaperTarget == null ? null : mWallpaperTarget.getStack();
1870 if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 &&
1871 targetStack != null && !targetStack.isHomeStack()) {
1872 // If the wallpaper target is not on the home stack then make sure that all windows
1873 // from other non-home stacks are above the wallpaper.
1874 for (i = foundI - 1; i >= 0; --i) {
1875 WindowState win = windows.get(i);
1876 if (!win.isVisibleLw()) {
1879 final TaskStack winStack = win.getStack();
1880 if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) {
1882 windows.add(foundI + 1, win);
1888 if (targetChanged && DEBUG_WALLPAPER_LIGHT) {
1889 Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget
1890 + " lower=" + mLowerWallpaperTarget + " upper="
1891 + mUpperWallpaperTarget);
1897 void setWallpaperAnimLayerAdjustmentLocked(int adj) {
1898 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
1899 "Setting wallpaper layer adj to " + adj);
1900 mWallpaperAnimLayerAdjustment = adj;
1901 int curTokenIndex = mWallpaperTokens.size();
1902 while (curTokenIndex > 0) {
1904 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1905 int curWallpaperIndex = token.windows.size();
1906 while (curWallpaperIndex > 0) {
1907 curWallpaperIndex--;
1908 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1909 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj;
1910 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win "
1911 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
1916 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
1918 boolean changed = false;
1919 boolean rawChanged = false;
1920 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
1921 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
1922 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
1923 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
1924 changed = wallpaperWin.mXOffset != offset;
1926 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
1927 + wallpaperWin + " x: " + offset);
1928 wallpaperWin.mXOffset = offset;
1930 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
1931 wallpaperWin.mWallpaperX = wpx;
1932 wallpaperWin.mWallpaperXStep = wpxs;
1936 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
1937 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
1938 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
1939 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
1940 if (wallpaperWin.mYOffset != offset) {
1941 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
1942 + wallpaperWin + " y: " + offset);
1944 wallpaperWin.mYOffset = offset;
1946 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
1947 wallpaperWin.mWallpaperY = wpy;
1948 wallpaperWin.mWallpaperYStep = wpys;
1952 if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
1953 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
1955 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
1956 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
1957 + " y=" + wallpaperWin.mWallpaperY);
1959 mWaitingOnWallpaper = wallpaperWin;
1961 wallpaperWin.mClient.dispatchWallpaperOffsets(
1962 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
1963 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
1965 if (mWaitingOnWallpaper != null) {
1966 long start = SystemClock.uptimeMillis();
1967 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
1970 if (DEBUG_WALLPAPER) Slog.v(TAG,
1971 "Waiting for offset complete...");
1972 mWindowMap.wait(WALLPAPER_TIMEOUT);
1973 } catch (InterruptedException e) {
1975 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
1976 if ((start+WALLPAPER_TIMEOUT)
1977 < SystemClock.uptimeMillis()) {
1978 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
1980 mLastWallpaperTimeoutTime = start;
1983 mWaitingOnWallpaper = null;
1986 } catch (RemoteException e) {
1993 void wallpaperOffsetsComplete(IBinder window) {
1994 synchronized (mWindowMap) {
1995 if (mWaitingOnWallpaper != null &&
1996 mWaitingOnWallpaper.mClient.asBinder() == window) {
1997 mWaitingOnWallpaper = null;
1998 mWindowMap.notifyAll();
2003 void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
2004 final DisplayContent displayContent = changingTarget.mDisplayContent;
2005 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2006 final int dw = displayInfo.logicalWidth;
2007 final int dh = displayInfo.logicalHeight;
2009 WindowState target = mWallpaperTarget;
2010 if (target != null) {
2011 if (target.mWallpaperX >= 0) {
2012 mLastWallpaperX = target.mWallpaperX;
2013 } else if (changingTarget.mWallpaperX >= 0) {
2014 mLastWallpaperX = changingTarget.mWallpaperX;
2016 if (target.mWallpaperY >= 0) {
2017 mLastWallpaperY = target.mWallpaperY;
2018 } else if (changingTarget.mWallpaperY >= 0) {
2019 mLastWallpaperY = changingTarget.mWallpaperY;
2023 int curTokenIndex = mWallpaperTokens.size();
2024 while (curTokenIndex > 0) {
2026 WindowToken token = mWallpaperTokens.get(curTokenIndex);
2027 int curWallpaperIndex = token.windows.size();
2028 while (curWallpaperIndex > 0) {
2029 curWallpaperIndex--;
2030 WindowState wallpaper = token.windows.get(curWallpaperIndex);
2031 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
2032 WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
2033 winAnimator.computeShownFrameLocked();
2034 // No need to lay out the windows - we can just set the wallpaper position
2036 winAnimator.setWallpaperOffset(wallpaper.mShownFrame);
2037 // We only want to be synchronous with one wallpaper.
2045 * Check wallpaper for visiblity change and notify window if so.
2046 * @param wallpaper The wallpaper to test and notify.
2047 * @param visible Current visibility.
2049 void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) {
2050 if (wallpaper.mWallpaperVisible != visible) {
2051 wallpaper.mWallpaperVisible = visible;
2053 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
2054 "Updating vis of wallpaper " + wallpaper
2055 + ": " + visible + " from:\n" + Debug.getCallers(4, " "));
2056 wallpaper.mClient.dispatchAppVisibility(visible);
2057 } catch (RemoteException e) {
2062 void updateWallpaperVisibilityLocked() {
2063 final boolean visible = isWallpaperVisible(mWallpaperTarget);
2064 final DisplayContent displayContent = mWallpaperTarget.mDisplayContent;
2065 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2066 final int dw = displayInfo.logicalWidth;
2067 final int dh = displayInfo.logicalHeight;
2069 int curTokenIndex = mWallpaperTokens.size();
2070 while (curTokenIndex > 0) {
2072 WindowToken token = mWallpaperTokens.get(curTokenIndex);
2073 if (token.hidden == visible) {
2074 token.hidden = !visible;
2075 // Need to do a layout to ensure the wallpaper now has the
2077 getDefaultDisplayContentLocked().layoutNeeded = true;
2080 int curWallpaperIndex = token.windows.size();
2081 while (curWallpaperIndex > 0) {
2082 curWallpaperIndex--;
2083 WindowState wallpaper = token.windows.get(curWallpaperIndex);
2085 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
2088 dispatchWallpaperVisibility(wallpaper, visible);
2093 public int addWindow(Session session, IWindow client, int seq,
2094 WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
2095 Rect outContentInsets, InputChannel outInputChannel) {
2096 int[] appOp = new int[1];
2097 int res = mPolicy.checkAddPermission(attrs, appOp);
2098 if (res != WindowManagerGlobal.ADD_OKAY) {
2102 boolean reportNewConfig = false;
2103 WindowState attachedWindow = null;
2104 WindowState win = null;
2106 final int type = attrs.type;
2108 synchronized(mWindowMap) {
2109 if (!mDisplayReady) {
2110 throw new IllegalStateException("Display has not been initialialized");
2113 final DisplayContent displayContent = getDisplayContentLocked(displayId);
2114 if (displayContent == null) {
2115 Slog.w(TAG, "Attempted to add window to a display that does not exist: "
2116 + displayId + ". Aborting.");
2117 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2119 if (!displayContent.hasAccess(session.mUid)) {
2120 Slog.w(TAG, "Attempted to add window to a display for which the application "
2121 + "does not have access: " + displayId + ". Aborting.");
2122 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2125 if (mWindowMap.containsKey(client.asBinder())) {
2126 Slog.w(TAG, "Window " + client + " is already added");
2127 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
2130 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
2131 attachedWindow = windowForClientLocked(null, attrs.token, false);
2132 if (attachedWindow == null) {
2133 Slog.w(TAG, "Attempted to add window with token that is not a window: "
2134 + attrs.token + ". Aborting.");
2135 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
2137 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
2138 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
2139 Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
2140 + attrs.token + ". Aborting.");
2141 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
2145 if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
2146 Slog.w(TAG, "Attempted to add private presentation window to a non-private display. Aborting.");
2147 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2150 boolean addToken = false;
2151 WindowToken token = mTokenMap.get(attrs.token);
2152 if (token == null) {
2153 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2154 Slog.w(TAG, "Attempted to add application window with unknown token "
2155 + attrs.token + ". Aborting.");
2156 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2158 if (type == TYPE_INPUT_METHOD) {
2159 Slog.w(TAG, "Attempted to add input method window with unknown token "
2160 + attrs.token + ". Aborting.");
2161 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2163 if (type == TYPE_WALLPAPER) {
2164 Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
2165 + attrs.token + ". Aborting.");
2166 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2168 if (type == TYPE_DREAM) {
2169 Slog.w(TAG, "Attempted to add Dream window with unknown token "
2170 + attrs.token + ". Aborting.");
2171 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2173 token = new WindowToken(this, attrs.token, -1, false);
2175 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2176 AppWindowToken atoken = token.appWindowToken;
2177 if (atoken == null) {
2178 Slog.w(TAG, "Attempted to add window with non-application token "
2179 + token + ". Aborting.");
2180 return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
2181 } else if (atoken.removed) {
2182 Slog.w(TAG, "Attempted to add window with exiting application token "
2183 + token + ". Aborting.");
2184 return WindowManagerGlobal.ADD_APP_EXITING;
2186 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
2187 // No need for this guy!
2188 if (localLOGV) Slog.v(
2189 TAG, "**** NO NEED TO START: " + attrs.getTitle());
2190 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
2192 } else if (type == TYPE_INPUT_METHOD) {
2193 if (token.windowType != TYPE_INPUT_METHOD) {
2194 Slog.w(TAG, "Attempted to add input method window with bad token "
2195 + attrs.token + ". Aborting.");
2196 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2198 } else if (type == TYPE_WALLPAPER) {
2199 if (token.windowType != TYPE_WALLPAPER) {
2200 Slog.w(TAG, "Attempted to add wallpaper window with bad token "
2201 + attrs.token + ". Aborting.");
2202 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2204 } else if (type == TYPE_DREAM) {
2205 if (token.windowType != TYPE_DREAM) {
2206 Slog.w(TAG, "Attempted to add Dream window with bad token "
2207 + attrs.token + ". Aborting.");
2208 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2212 win = new WindowState(this, session, client, token,
2213 attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
2214 if (win.mDeathRecipient == null) {
2215 // Client has apparently died, so there is no reason to
2217 Slog.w(TAG, "Adding window client " + client.asBinder()
2218 + " that is dead, aborting.");
2219 return WindowManagerGlobal.ADD_APP_EXITING;
2222 mPolicy.adjustWindowParamsLw(win.mAttrs);
2223 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
2225 res = mPolicy.prepareAddWindowLw(win, attrs);
2226 if (res != WindowManagerGlobal.ADD_OKAY) {
2230 if (outInputChannel != null && (attrs.inputFeatures
2231 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
2232 String name = win.makeInputChannelName();
2233 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
2234 win.setInputChannel(inputChannels[0]);
2235 inputChannels[1].transferTo(outInputChannel);
2237 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
2240 // From now on, no exceptions or errors allowed!
2242 res = WindowManagerGlobal.ADD_OKAY;
2244 origId = Binder.clearCallingIdentity();
2247 mTokenMap.put(attrs.token, token);
2250 mWindowMap.put(client.asBinder(), win);
2251 if (win.mAppOp != AppOpsManager.OP_NONE) {
2252 if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage())
2253 != AppOpsManager.MODE_ALLOWED) {
2254 win.setAppOpVisibilityLw(false);
2258 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
2259 token.appWindowToken.startingWindow = win;
2260 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken
2261 + " startingWindow=" + win);
2262 Message m = mH.obtainMessage(H.REMOVE_STARTING_TIMEOUT, token.appWindowToken);
2263 mH.sendMessageDelayed(m, STARTING_WINDOW_TIMEOUT_DURATION);
2266 boolean imMayMove = true;
2268 if (type == TYPE_INPUT_METHOD) {
2269 win.mGivenInsetsPending = true;
2270 mInputMethodWindow = win;
2271 addInputMethodWindowToListLocked(win);
2273 } else if (type == TYPE_INPUT_METHOD_DIALOG) {
2274 mInputMethodDialogs.add(win);
2275 addWindowToListInOrderLocked(win, true);
2276 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
2279 addWindowToListInOrderLocked(win, true);
2280 if (type == TYPE_WALLPAPER) {
2281 mLastWallpaperTimeoutTime = 0;
2282 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2283 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2284 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2285 } else if (mWallpaperTarget != null
2286 && mWallpaperTarget.mLayer >= win.mBaseLayer) {
2287 // If there is currently a wallpaper being shown, and
2288 // the base layer of the new window is below the current
2289 // layer of the target window, then adjust the wallpaper.
2290 // This is to avoid a new window being placed between the
2291 // wallpaper and its target.
2292 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2296 win.mWinAnimator.mEnterAnimationPending = true;
2298 if (displayContent.isDefaultDisplay) {
2299 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
2301 outContentInsets.setEmpty();
2305 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
2307 if (win.mAppToken == null || !win.mAppToken.clientHidden) {
2308 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
2311 mInputMonitor.setUpdateInputWindowsNeededLw();
2313 boolean focusChanged = false;
2314 if (win.canReceiveKeys()) {
2315 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
2316 false /*updateInputWindows*/);
2323 moveInputMethodWindowsIfNeededLocked(false);
2326 assignLayersLocked(displayContent.getWindowList());
2327 // Don't do layout here, the window must call
2328 // relayout to be displayed, so we'll do it there.
2331 finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/);
2333 mInputMonitor.updateInputWindowsLw(false /*force*/);
2335 if (localLOGV) Slog.v(
2336 TAG, "New client " + client.asBinder()
2337 + ": window=" + win);
2339 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
2340 reportNewConfig = true;
2344 if (reportNewConfig) {
2345 sendNewConfiguration();
2348 Binder.restoreCallingIdentity(origId);
2353 public void removeWindow(Session session, IWindow client) {
2354 synchronized(mWindowMap) {
2355 WindowState win = windowForClientLocked(session, client, false);
2359 removeWindowLocked(session, win);
2363 public void removeWindowLocked(Session session, WindowState win) {
2364 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2365 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win);
2366 removeStartingWindowTimeout(win.mAppToken);
2369 if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v(
2370 TAG, "Remove " + win + " client="
2371 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder()))
2372 + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers="
2373 + Debug.getCallers(4));
2375 final long origId = Binder.clearCallingIdentity();
2377 win.disposeInputChannel();
2379 if (DEBUG_APP_TRANSITIONS) Slog.v(
2380 TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl
2381 + " mExiting=" + win.mExiting
2382 + " isAnimating=" + win.mWinAnimator.isAnimating()
2384 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
2385 + " inPendingTransaction="
2386 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
2387 + " mDisplayFrozen=" + mDisplayFrozen);
2388 // Visibility of the removed window. Will be used later to update orientation later on.
2389 boolean wasVisible = false;
2390 // First, see if we need to run an animation. If we do, we have
2391 // to hold off on removing the window until the animation is done.
2392 // If the display is frozen, just remove immediately, since the
2393 // animation wouldn't be seen.
2394 if (win.mHasSurface && okToDisplay()) {
2395 // If we are not currently running the exit animation, we
2396 // need to see about starting one.
2397 wasVisible = win.isWinVisibleLw();
2400 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2401 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2402 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2404 // Try starting an animation.
2405 if (win.mWinAnimator.applyAnimationLocked(transit, false)) {
2406 win.mExiting = true;
2408 //TODO (multidisplay): Magnification is supported only for the default display.
2409 if (mDisplayMagnifier != null
2410 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
2411 mDisplayMagnifier.onWindowTransitionLocked(win, transit);
2414 if (win.mExiting || win.mWinAnimator.isAnimating()) {
2415 // The exit animation is running... wait for it!
2416 //Slog.i(TAG, "*** Running exit animation...");
2417 win.mExiting = true;
2418 win.mRemoveOnExit = true;
2419 win.mDisplayContent.layoutNeeded = true;
2420 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
2421 false /*updateInputWindows*/);
2422 performLayoutAndPlaceSurfacesLocked();
2423 if (win.mAppToken != null) {
2424 win.mAppToken.updateReportedVisibilityLocked();
2427 Binder.restoreCallingIdentity(origId);
2432 removeWindowInnerLocked(session, win);
2433 // Removing a visible window will effect the computed orientation
2434 // So just update orientation if needed.
2435 if (wasVisible && updateOrientationFromAppTokensLocked(false)) {
2436 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
2438 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
2439 Binder.restoreCallingIdentity(origId);
2442 private void removeWindowInnerLocked(Session session, WindowState win) {
2448 for (int i=win.mChildWindows.size()-1; i>=0; i--) {
2449 WindowState cwin = win.mChildWindows.get(i);
2450 Slog.w(TAG, "Force-removing child win " + cwin + " from container "
2452 removeWindowInnerLocked(cwin.mSession, cwin);
2455 win.mRemoved = true;
2457 if (mInputMethodTarget == win) {
2458 moveInputMethodWindowsIfNeededLocked(false);
2462 RuntimeException e = new RuntimeException("here");
2463 e.fillInStackTrace();
2464 Slog.w(TAG, "Removing window " + win, e);
2467 mPolicy.removeWindowLw(win);
2470 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win);
2471 mWindowMap.remove(win.mClient.asBinder());
2472 if (win.mAppOp != AppOpsManager.OP_NONE) {
2473 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
2476 final WindowList windows = win.getWindowList();
2477 windows.remove(win);
2478 mPendingRemove.remove(win);
2479 mResizingWindows.remove(win);
2480 mWindowsChanged = true;
2481 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
2483 if (mInputMethodWindow == win) {
2484 mInputMethodWindow = null;
2485 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2486 mInputMethodDialogs.remove(win);
2489 final WindowToken token = win.mToken;
2490 final AppWindowToken atoken = win.mAppToken;
2491 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token);
2492 token.windows.remove(win);
2493 if (atoken != null) {
2494 atoken.allAppWindows.remove(win);
2496 if (localLOGV) Slog.v(
2497 TAG, "**** Removing window " + win + ": count="
2498 + token.windows.size());
2499 if (token.windows.size() == 0) {
2500 if (!token.explicit) {
2501 mTokenMap.remove(token.token);
2502 } else if (atoken != null) {
2503 atoken.firstWindowDrawn = false;
2507 if (atoken != null) {
2508 if (atoken.startingWindow == win) {
2509 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling startingWindow " + win);
2510 removeStartingWindowTimeout(atoken);
2511 atoken.startingWindow = null;
2512 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2513 // If this is the last window and we had requested a starting
2514 // transition window, well there is no point now.
2515 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling last startingWindow");
2516 atoken.startingData = null;
2517 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2518 // If this is the last window except for a starting transition
2519 // window, we need to get rid of the starting transition.
2520 scheduleRemoveStartingWindow(atoken);
2524 if (win.mAttrs.type == TYPE_WALLPAPER) {
2525 mLastWallpaperTimeoutTime = 0;
2526 getDefaultDisplayContentLocked().pendingLayoutChanges |=
2527 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2528 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2529 getDefaultDisplayContentLocked().pendingLayoutChanges |=
2530 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2534 assignLayersLocked(windows);
2535 win.mDisplayContent.layoutNeeded = true;
2536 performLayoutAndPlaceSurfacesLocked();
2537 if (win.mAppToken != null) {
2538 win.mAppToken.updateReportedVisibilityLocked();
2542 mInputMonitor.updateInputWindowsLw(true /*force*/);
2545 public void updateAppOpsState() {
2546 synchronized(mWindowMap) {
2547 final int numDisplays = mDisplayContents.size();
2548 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
2549 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
2550 final int numWindows = windows.size();
2551 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
2552 final WindowState win = windows.get(winNdx);
2553 if (win.mAppOp != AppOpsManager.OP_NONE) {
2554 final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
2555 win.getOwningPackage());
2556 win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED);
2563 static void logSurface(WindowState w, String msg, RuntimeException where) {
2564 String str = " SURFACE " + msg + ": " + w;
2565 if (where != null) {
2566 Slog.i(TAG, str, where);
2572 static void logSurface(SurfaceControl s, String title, String msg, RuntimeException where) {
2573 String str = " SURFACE " + s + ": " + msg + " / " + title;
2574 if (where != null) {
2575 Slog.i(TAG, str, where);
2581 void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2582 long origId = Binder.clearCallingIdentity();
2584 synchronized (mWindowMap) {
2585 WindowState w = windowForClientLocked(session, client, false);
2586 if ((w != null) && w.mHasSurface) {
2587 w.mWinAnimator.setTransparentRegionHintLocked(region);
2591 Binder.restoreCallingIdentity(origId);
2595 void setInsetsWindow(Session session, IWindow client,
2596 int touchableInsets, Rect contentInsets,
2597 Rect visibleInsets, Region touchableRegion) {
2598 long origId = Binder.clearCallingIdentity();
2600 synchronized (mWindowMap) {
2601 WindowState w = windowForClientLocked(session, client, false);
2603 w.mGivenInsetsPending = false;
2604 w.mGivenContentInsets.set(contentInsets);
2605 w.mGivenVisibleInsets.set(visibleInsets);
2606 w.mGivenTouchableRegion.set(touchableRegion);
2607 w.mTouchableInsets = touchableInsets;
2608 if (w.mGlobalScale != 1) {
2609 w.mGivenContentInsets.scale(w.mGlobalScale);
2610 w.mGivenVisibleInsets.scale(w.mGlobalScale);
2611 w.mGivenTouchableRegion.scale(w.mGlobalScale);
2613 w.mDisplayContent.layoutNeeded = true;
2614 performLayoutAndPlaceSurfacesLocked();
2618 Binder.restoreCallingIdentity(origId);
2622 public void getWindowDisplayFrame(Session session, IWindow client,
2623 Rect outDisplayFrame) {
2624 synchronized(mWindowMap) {
2625 WindowState win = windowForClientLocked(session, client, false);
2627 outDisplayFrame.setEmpty();
2630 outDisplayFrame.set(win.mDisplayFrame);
2634 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
2635 float xStep, float yStep) {
2636 if (window.mWallpaperX != x || window.mWallpaperY != y) {
2637 window.mWallpaperX = x;
2638 window.mWallpaperY = y;
2639 window.mWallpaperXStep = xStep;
2640 window.mWallpaperYStep = yStep;
2641 updateWallpaperOffsetLocked(window, true);
2645 void wallpaperCommandComplete(IBinder window, Bundle result) {
2646 synchronized (mWindowMap) {
2647 if (mWaitingOnWallpaper != null &&
2648 mWaitingOnWallpaper.mClient.asBinder() == window) {
2649 mWaitingOnWallpaper = null;
2650 mWindowMap.notifyAll();
2655 public Bundle sendWindowWallpaperCommandLocked(WindowState window,
2656 String action, int x, int y, int z, Bundle extras, boolean sync) {
2657 if (window == mWallpaperTarget || window == mLowerWallpaperTarget
2658 || window == mUpperWallpaperTarget) {
2659 boolean doWait = sync;
2660 int curTokenIndex = mWallpaperTokens.size();
2661 while (curTokenIndex > 0) {
2663 WindowToken token = mWallpaperTokens.get(curTokenIndex);
2664 int curWallpaperIndex = token.windows.size();
2665 while (curWallpaperIndex > 0) {
2666 curWallpaperIndex--;
2667 WindowState wallpaper = token.windows.get(curWallpaperIndex);
2669 wallpaper.mClient.dispatchWallpaperCommand(action,
2670 x, y, z, extras, sync);
2671 // We only want to be synchronous with one wallpaper.
2673 } catch (RemoteException e) {
2679 // XXX Need to wait for result.
2686 public void setUniverseTransformLocked(WindowState window, float alpha,
2687 float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) {
2688 Transformation transform = window.mWinAnimator.mUniverseTransform;
2689 transform.setAlpha(alpha);
2690 Matrix matrix = transform.getMatrix();
2691 matrix.getValues(mTmpFloats);
2692 mTmpFloats[Matrix.MTRANS_X] = offx;
2693 mTmpFloats[Matrix.MTRANS_Y] = offy;
2694 mTmpFloats[Matrix.MSCALE_X] = dsdx;
2695 mTmpFloats[Matrix.MSKEW_Y] = dtdx;
2696 mTmpFloats[Matrix.MSKEW_X] = dsdy;
2697 mTmpFloats[Matrix.MSCALE_Y] = dtdy;
2698 matrix.setValues(mTmpFloats);
2699 final DisplayInfo displayInfo = window.mDisplayContent.getDisplayInfo();
2700 final RectF dispRect = new RectF(0, 0,
2701 displayInfo.logicalWidth, displayInfo.logicalHeight);
2702 matrix.mapRect(dispRect);
2703 window.mGivenTouchableRegion.set(0, 0,
2704 displayInfo.logicalWidth, displayInfo.logicalHeight);
2705 window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top,
2706 (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE);
2707 window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
2708 window.mDisplayContent.layoutNeeded = true;
2709 performLayoutAndPlaceSurfacesLocked();
2712 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle, boolean immediate) {
2713 synchronized (mWindowMap) {
2714 if (mDisplayMagnifier != null) {
2715 WindowState window = mWindowMap.get(token);
2716 //TODO (multidisplay): Magnification is supported only for the default display.
2717 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
2718 mDisplayMagnifier.onRectangleOnScreenRequestedLocked(rectangle, immediate);
2724 public IWindowId getWindowId(IBinder token) {
2725 synchronized (mWindowMap) {
2726 WindowState window = mWindowMap.get(token);
2727 return window != null ? window.mWindowId : null;
2731 public int relayoutWindow(Session session, IWindow client, int seq,
2732 WindowManager.LayoutParams attrs, int requestedWidth,
2733 int requestedHeight, int viewVisibility, int flags,
2734 Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
2735 Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
2736 boolean toBeDisplayed = false;
2737 boolean inTouchMode;
2738 boolean configChanged;
2739 boolean surfaceChanged = false;
2742 // if they don't have this permission, mask out the status bar bits
2743 int systemUiVisibility = 0;
2744 if (attrs != null) {
2745 systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility);
2746 if ((systemUiVisibility & StatusBarManager.DISABLE_MASK) != 0) {
2747 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
2748 != PackageManager.PERMISSION_GRANTED) {
2749 systemUiVisibility &= ~StatusBarManager.DISABLE_MASK;
2753 long origId = Binder.clearCallingIdentity();
2755 synchronized(mWindowMap) {
2756 WindowState win = windowForClientLocked(session, client, false);
2760 WindowStateAnimator winAnimator = win.mWinAnimator;
2761 if (win.mRequestedWidth != requestedWidth
2762 || win.mRequestedHeight != requestedHeight) {
2763 win.mLayoutNeeded = true;
2764 win.mRequestedWidth = requestedWidth;
2765 win.mRequestedHeight = requestedHeight;
2767 if (attrs != null && seq == win.mSeq) {
2768 win.mSystemUiVisibility = systemUiVisibility;
2771 if (attrs != null) {
2772 mPolicy.adjustWindowParamsLw(attrs);
2775 winAnimator.mSurfaceDestroyDeferred =
2776 (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
2778 int attrChanges = 0;
2779 int flagChanges = 0;
2780 if (attrs != null) {
2781 if (win.mAttrs.type != attrs.type) {
2782 throw new IllegalArgumentException(
2783 "Window type can not be changed after the window is added.");
2785 flagChanges = win.mAttrs.flags ^= attrs.flags;
2786 attrChanges = win.mAttrs.copyFrom(attrs);
2787 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
2788 | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
2789 win.mLayoutNeeded = true;
2793 if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
2794 + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
2796 win.mEnforceSizeCompat =
2797 (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
2799 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2800 winAnimator.mAlpha = attrs.alpha;
2803 final boolean scaledWindow =
2804 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
2807 // requested{Width|Height} Surface's physical size
2808 // attrs.{width|height} Size on screen
2809 win.mHScale = (attrs.width != requestedWidth) ?
2810 (attrs.width / (float)requestedWidth) : 1.0f;
2811 win.mVScale = (attrs.height != requestedHeight) ?
2812 (attrs.height / (float)requestedHeight) : 1.0f;
2814 win.mHScale = win.mVScale = 1;
2817 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
2819 final boolean isDefaultDisplay = win.isDefaultDisplay();
2820 boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
2821 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
2822 || (!win.mRelayoutCalled));
2824 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2825 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
2826 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
2828 win.mRelayoutCalled = true;
2829 final int oldVisibility = win.mViewVisibility;
2830 win.mViewVisibility = viewVisibility;
2831 if (DEBUG_SCREEN_ON) {
2832 RuntimeException stack = new RuntimeException();
2833 stack.fillInStackTrace();
2834 Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility
2835 + " newVis=" + viewVisibility, stack);
2837 if (viewVisibility == View.VISIBLE &&
2838 (win.mAppToken == null || !win.mAppToken.clientHidden)) {
2839 toBeDisplayed = !win.isVisibleLw();
2841 winAnimator.cancelExitAnimationForNextAnimationLocked();
2842 win.mExiting = false;
2844 if (win.mDestroying) {
2845 win.mDestroying = false;
2846 mDestroySurface.remove(win);
2848 if (oldVisibility == View.GONE) {
2849 winAnimator.mEnterAnimationPending = true;
2851 if (toBeDisplayed) {
2852 if (win.isDrawnLw() && okToDisplay()) {
2853 winAnimator.applyEnterAnimationLocked();
2855 if ((win.mAttrs.flags
2856 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
2857 if (DEBUG_VISIBILITY) Slog.v(TAG,
2858 "Relayout window turning screen on: " + win);
2859 win.mTurnOnScreen = true;
2861 if (win.isConfigChanged()) {
2862 if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win
2863 + " visible with new config: " + mCurConfiguration);
2864 outConfig.setTo(mCurConfiguration);
2867 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
2868 // To change the format, we need to re-build the surface.
2869 winAnimator.destroySurfaceLocked();
2870 toBeDisplayed = true;
2871 surfaceChanged = true;
2874 if (!win.mHasSurface) {
2875 surfaceChanged = true;
2877 SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
2878 if (surfaceControl != null) {
2879 outSurface.copyFrom(surfaceControl);
2880 if (SHOW_TRANSACTIONS) Slog.i(TAG,
2881 " OUT SURFACE " + outSurface + ": copied");
2883 // For some reason there isn't a surface. Clear the
2884 // caller's object so they see the same state.
2885 outSurface.release();
2887 } catch (Exception e) {
2888 mInputMonitor.updateInputWindowsLw(true /*force*/);
2890 Slog.w(TAG, "Exception thrown when creating surface for client "
2891 + client + " (" + win.mAttrs.getTitle() + ")",
2893 Binder.restoreCallingIdentity(origId);
2896 if (toBeDisplayed) {
2897 focusMayChange = isDefaultDisplay;
2899 if (win.mAttrs.type == TYPE_INPUT_METHOD
2900 && mInputMethodWindow == null) {
2901 mInputMethodWindow = win;
2904 if (win.mAttrs.type == TYPE_BASE_APPLICATION
2905 && win.mAppToken != null
2906 && win.mAppToken.startingWindow != null) {
2907 // Special handling of starting window over the base
2908 // window of the app: propagate lock screen flags to it,
2909 // to provide the correct semantics while starting.
2911 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
2912 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
2913 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
2914 WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
2915 sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
2918 winAnimator.mEnterAnimationPending = false;
2919 if (winAnimator.mSurfaceControl != null) {
2920 if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
2921 + ": mExiting=" + win.mExiting);
2922 // If we are not currently running the exit animation, we
2923 // need to see about starting one.
2924 if (!win.mExiting) {
2925 surfaceChanged = true;
2926 // Try starting an animation; if there isn't one, we
2927 // can destroy the surface right away.
2928 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2929 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2930 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2932 if (win.isWinVisibleLw() &&
2933 winAnimator.applyAnimationLocked(transit, false)) {
2934 focusMayChange = isDefaultDisplay;
2935 win.mExiting = true;
2936 } else if (win.mWinAnimator.isAnimating()) {
2937 // Currently in a hide animation... turn this into
2939 win.mExiting = true;
2940 } else if (win == mWallpaperTarget) {
2941 // If the wallpaper is currently behind this
2942 // window, we need to change both of them inside
2943 // of a transaction to avoid artifacts.
2944 win.mExiting = true;
2945 win.mWinAnimator.mAnimating = true;
2947 if (mInputMethodWindow == win) {
2948 mInputMethodWindow = null;
2950 winAnimator.destroySurfaceLocked();
2952 //TODO (multidisplay): Magnification is supported only for the default
2953 if (mDisplayMagnifier != null
2954 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
2955 mDisplayMagnifier.onWindowTransitionLocked(win, transit);
2960 outSurface.release();
2961 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
2964 if (focusMayChange) {
2965 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2966 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
2967 false /*updateInputWindows*/)) {
2970 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2973 // updateFocusedWindowLocked() already assigned layers so we only need to
2974 // reassign them at this point if the IM window state gets shuffled
2975 if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) {
2976 // Little hack here -- we -should- be able to rely on the
2977 // function to return true if the IME has moved and needs
2978 // its layer recomputed. However, if the IME was hidden
2979 // and isn't actually moved in the list, its layer may be
2980 // out of data so we make sure to recompute it.
2981 assignLayersLocked(win.getWindowList());
2984 if (wallpaperMayMove) {
2985 getDefaultDisplayContentLocked().pendingLayoutChanges |=
2986 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2989 win.mDisplayContent.layoutNeeded = true;
2990 win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
2991 configChanged = updateOrientationFromAppTokensLocked(false);
2992 performLayoutAndPlaceSurfacesLocked();
2993 if (toBeDisplayed && win.mIsWallpaper) {
2994 DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
2995 updateWallpaperOffsetLocked(win,
2996 displayInfo.logicalWidth, displayInfo.logicalHeight, false);
2998 if (win.mAppToken != null) {
2999 win.mAppToken.updateReportedVisibilityLocked();
3001 outFrame.set(win.mCompatFrame);
3002 outOverscanInsets.set(win.mOverscanInsets);
3003 outContentInsets.set(win.mContentInsets);
3004 outVisibleInsets.set(win.mVisibleInsets);
3005 if (localLOGV) Slog.v(
3006 TAG, "Relayout given client " + client.asBinder()
3007 + ", requestedWidth=" + requestedWidth
3008 + ", requestedHeight=" + requestedHeight
3009 + ", viewVisibility=" + viewVisibility
3010 + "\nRelayout returning frame=" + outFrame
3011 + ", surface=" + outSurface);
3013 if (localLOGV || DEBUG_FOCUS) Slog.v(
3014 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
3016 inTouchMode = mInTouchMode;
3017 animating = mAnimator.mAnimating;
3018 if (animating && !mRelayoutWhileAnimating.contains(win)) {
3019 mRelayoutWhileAnimating.add(win);
3022 mInputMonitor.updateInputWindowsLw(true /*force*/);
3025 Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
3029 if (configChanged) {
3030 sendNewConfiguration();
3033 Binder.restoreCallingIdentity(origId);
3035 return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0)
3036 | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0)
3037 | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0)
3038 | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0);
3041 public void performDeferredDestroyWindow(Session session, IWindow client) {
3042 long origId = Binder.clearCallingIdentity();
3045 synchronized (mWindowMap) {
3046 WindowState win = windowForClientLocked(session, client, false);
3050 win.mWinAnimator.destroyDeferredSurfaceLocked();
3053 Binder.restoreCallingIdentity(origId);
3057 public boolean outOfMemoryWindow(Session session, IWindow client) {
3058 long origId = Binder.clearCallingIdentity();
3061 synchronized (mWindowMap) {
3062 WindowState win = windowForClientLocked(session, client, false);
3066 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false);
3069 Binder.restoreCallingIdentity(origId);
3073 public void finishDrawingWindow(Session session, IWindow client) {
3074 final long origId = Binder.clearCallingIdentity();
3076 synchronized (mWindowMap) {
3077 WindowState win = windowForClientLocked(session, client, false);
3078 if (win != null && win.mWinAnimator.finishDrawingLocked()) {
3079 if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
3080 getDefaultDisplayContentLocked().pendingLayoutChanges |=
3081 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
3083 win.mDisplayContent.layoutNeeded = true;
3084 requestTraversalLocked();
3088 Binder.restoreCallingIdentity(origId);
3093 public void getWindowFrame(IBinder token, Rect outBounds) {
3094 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
3095 "getWindowInfo()")) {
3096 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
3098 synchronized (mWindowMap) {
3099 WindowState windowState = mWindowMap.get(token);
3100 if (windowState != null) {
3101 outBounds.set(windowState.mFrame);
3103 outBounds.setEmpty();
3109 public void setMagnificationSpec(MagnificationSpec spec) {
3110 if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
3111 "setMagnificationSpec()")) {
3112 throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
3114 synchronized (mWindowMap) {
3115 if (mDisplayMagnifier != null) {
3116 mDisplayMagnifier.setMagnificationSpecLocked(spec);
3118 throw new IllegalStateException("Magnification callbacks not set!");
3121 if (Binder.getCallingPid() != android.os.Process.myPid()) {
3127 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
3128 if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
3129 "getCompatibleMagnificationSpecForWindow()")) {
3130 throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
3132 synchronized (mWindowMap) {
3133 WindowState windowState = mWindowMap.get(windowToken);
3134 if (windowState == null) {
3137 MagnificationSpec spec = null;
3138 if (mDisplayMagnifier != null) {
3139 spec = mDisplayMagnifier.getMagnificationSpecForWindowLocked(windowState);
3141 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
3144 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
3145 spec.scale *= windowState.mGlobalScale;
3151 public void setMagnificationCallbacks(IMagnificationCallbacks callbacks) {
3152 if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
3153 "setMagnificationCallbacks()")) {
3154 throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
3156 synchronized (mWindowMap) {
3157 if (mDisplayMagnifier == null) {
3158 mDisplayMagnifier = new DisplayMagnifier(this, callbacks);
3160 if (callbacks == null) {
3161 if (mDisplayMagnifier != null) {
3162 mDisplayMagnifier.destroyLocked();
3163 mDisplayMagnifier = null;
3166 throw new IllegalStateException("Magnification callbacks already set!");
3172 private boolean applyAnimationLocked(AppWindowToken atoken,
3173 WindowManager.LayoutParams lp, int transit, boolean enter) {
3174 // Only apply an animation if the display isn't frozen. If it is
3175 // frozen, there is no reason to animate and it can cause strange
3176 // artifacts when we unfreeze the display if some different animation
3178 if (okToDisplay()) {
3179 DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
3180 final int width = displayInfo.appWidth;
3181 final int height = displayInfo.appHeight;
3182 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken="
3184 Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height);
3187 RuntimeException e = null;
3188 if (!HIDE_STACK_CRAWLS) {
3189 e = new RuntimeException();
3190 e.fillInStackTrace();
3192 Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e);
3194 atoken.mAppAnimator.setAnimation(a, width, height);
3197 atoken.mAppAnimator.clearAnimation();
3200 return atoken.mAppAnimator.animation != null;
3203 // -------------------------------------------------------------
3204 // Application Window Tokens
3205 // -------------------------------------------------------------
3207 public void validateAppTokens(int stackId, List<TaskGroup> tasks) {
3208 synchronized (mWindowMap) {
3209 int t = tasks.size() - 1;
3211 Slog.w(TAG, "validateAppTokens: empty task list");
3215 TaskGroup task = tasks.get(0);
3216 int taskId = task.taskId;
3217 Task targetTask = mTaskIdToTask.get(taskId);
3218 DisplayContent displayContent = targetTask.getDisplayContent();
3219 if (displayContent == null) {
3220 Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId);
3224 final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks();
3226 for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) {
3227 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens;
3228 task = tasks.get(t);
3229 List<IApplicationToken> tokens = task.tokens;
3231 DisplayContent lastDisplayContent = displayContent;
3232 displayContent = mTaskIdToTask.get(taskId).getDisplayContent();
3233 if (displayContent != lastDisplayContent) {
3234 Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!");
3240 for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1;
3241 tokenNdx >= 0 && v >= 0; ) {
3242 final AppWindowToken atoken = localTokens.get(tokenNdx);
3243 if (atoken.removed) {
3247 if (tokens.get(v) != atoken.token) {
3254 if (tokenNdx >= 0 || v >= 0) {
3259 if (taskNdx >= 0 || t >= 0) {
3260 Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks);
3261 Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + localTasks);
3262 Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4));
3267 public void validateStackOrder(Integer[] remoteStackIds) {
3271 boolean checkCallingPermission(String permission, String func) {
3272 // Quick check: if the calling permission is me, it's all okay.
3273 if (Binder.getCallingPid() == Process.myPid()) {
3277 if (mContext.checkCallingPermission(permission)
3278 == PackageManager.PERMISSION_GRANTED) {
3281 String msg = "Permission Denial: " + func + " from pid="
3282 + Binder.getCallingPid()
3283 + ", uid=" + Binder.getCallingUid()
3284 + " requires " + permission;
3289 boolean okToDisplay() {
3290 return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully();
3293 AppWindowToken findAppWindowToken(IBinder token) {
3294 WindowToken wtoken = mTokenMap.get(token);
3295 if (wtoken == null) {
3298 return wtoken.appWindowToken;
3302 public void addWindowToken(IBinder token, int type) {
3303 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3304 "addWindowToken()")) {
3305 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3308 synchronized(mWindowMap) {
3309 WindowToken wtoken = mTokenMap.get(token);
3310 if (wtoken != null) {
3311 Slog.w(TAG, "Attempted to add existing input method token: " + token);
3314 wtoken = new WindowToken(this, token, type, true);
3315 mTokenMap.put(token, wtoken);
3316 if (type == TYPE_WALLPAPER) {
3317 mWallpaperTokens.add(wtoken);
3323 public void removeWindowToken(IBinder token) {
3324 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3325 "removeWindowToken()")) {
3326 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3329 final long origId = Binder.clearCallingIdentity();
3330 synchronized(mWindowMap) {
3331 DisplayContent displayContent = null;
3332 WindowToken wtoken = mTokenMap.remove(token);
3333 if (wtoken != null) {
3334 boolean delayed = false;
3335 if (!wtoken.hidden) {
3336 final int N = wtoken.windows.size();
3337 boolean changed = false;
3339 for (int i=0; i<N; i++) {
3340 WindowState win = wtoken.windows.get(i);
3341 displayContent = win.mDisplayContent;
3343 if (win.mWinAnimator.isAnimating()) {
3347 if (win.isVisibleNow()) {
3348 win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
3350 //TODO (multidisplay): Magnification is supported only for the default
3351 if (mDisplayMagnifier != null && win.isDefaultDisplay()) {
3352 mDisplayMagnifier.onWindowTransitionLocked(win,
3353 WindowManagerPolicy.TRANSIT_EXIT);
3356 displayContent.layoutNeeded = true;
3360 wtoken.hidden = true;
3363 performLayoutAndPlaceSurfacesLocked();
3364 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
3365 false /*updateInputWindows*/);
3369 displayContent.mExitingTokens.add(wtoken);
3370 } else if (wtoken.windowType == TYPE_WALLPAPER) {
3371 mWallpaperTokens.remove(wtoken);
3375 mInputMonitor.updateInputWindowsLw(true /*force*/);
3377 Slog.w(TAG, "Attempted to remove non-existing token: " + token);
3380 Binder.restoreCallingIdentity(origId);
3383 private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) {
3384 final TaskStack stack = mStackIdToStack.get(stackId);
3385 if (stack == null) {
3386 throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
3388 Task task = new Task(atoken, stack, userId);
3389 mTaskIdToTask.put(taskId, task);
3390 stack.addTask(task, true);
3391 stack.getDisplayContent().moveStack(stack, true);
3396 public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
3397 int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId) {
3398 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3400 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3403 // Get the dispatching timeout here while we are not holding any locks so that it
3404 // can be cached by the AppWindowToken. The timeout value is used later by the
3405 // input dispatcher in code that does hold locks. If we did not cache the value
3406 // here we would run the chance of introducing a deadlock between the window manager
3407 // (which holds locks while updating the input dispatcher state) and the activity manager
3408 // (which holds locks while querying the application token).
3409 long inputDispatchingTimeoutNanos;
3411 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
3412 } catch (RemoteException ex) {
3413 Slog.w(TAG, "Could not get dispatching timeout.", ex);
3414 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
3417 synchronized(mWindowMap) {
3418 AppWindowToken atoken = findAppWindowToken(token.asBinder());
3419 if (atoken != null) {
3420 Slog.w(TAG, "Attempted to add existing app token: " + token);
3423 atoken = new AppWindowToken(this, token);
3424 atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
3425 atoken.groupId = taskId;
3426 atoken.appFullscreen = fullscreen;
3427 atoken.showWhenLocked = showWhenLocked;
3428 atoken.requestedOrientation = requestedOrientation;
3429 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
3430 + " to stack=" + stackId + " task=" + taskId + " at " + addPos);
3432 Task task = mTaskIdToTask.get(taskId);
3434 task = createTask(taskId, stackId, userId, atoken);
3436 task.addAppToken(addPos, atoken);
3439 mTokenMap.put(token.asBinder(), atoken);
3441 // Application tokens start out hidden.
3442 atoken.hidden = true;
3443 atoken.hiddenRequested = true;
3450 public void setAppGroupId(IBinder token, int groupId) {
3451 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3452 "setAppGroupId()")) {
3453 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3456 synchronized(mWindowMap) {
3457 final AppWindowToken atoken = findAppWindowToken(token);
3458 if (atoken == null) {
3459 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
3462 Task oldTask = mTaskIdToTask.get(atoken.groupId);
3463 oldTask.removeAppToken(atoken);
3465 atoken.groupId = groupId;
3466 Task newTask = mTaskIdToTask.get(groupId);
3467 if (newTask == null) {
3468 newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken);
3470 newTask.mAppTokens.add(atoken);
3474 public int getOrientationFromWindowsLocked() {
3475 if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
3476 // If the display is frozen, some activities may be in the middle
3477 // of restarting, and thus have removed their old window. If the
3478 // window has the flag to hide the lock screen, then the lock screen
3479 // can re-appear and inflict its own orientation on us. Keep the
3480 // orientation stable until this all settles down.
3481 return mLastWindowForcedOrientation;
3484 // TODO(multidisplay): Change to the correct display.
3485 final WindowList windows = getDefaultWindowListLocked();
3486 int pos = windows.size() - 1;
3488 WindowState win = windows.get(pos);
3490 if (win.mAppToken != null) {
3491 // We hit an application window. so the orientation will be determined by the
3492 // app window. No point in continuing further.
3493 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3495 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
3498 int req = win.mAttrs.screenOrientation;
3499 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
3500 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
3504 if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req);
3505 return (mLastWindowForcedOrientation=req);
3507 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3510 public int getOrientationFromAppTokensLocked() {
3511 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3512 boolean findingBehind = false;
3513 boolean lastFullscreen = false;
3514 // TODO: Multi window.
3515 DisplayContent displayContent = getDefaultDisplayContentLocked();
3516 final ArrayList<Task> tasks = displayContent.getTasks();
3517 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
3518 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
3519 final int firstToken = tokens.size() - 1;
3520 for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) {
3521 final AppWindowToken atoken = tokens.get(tokenNdx);
3523 if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
3525 // if we're about to tear down this window and not seek for
3526 // the behind activity, don't use it for orientation
3528 && (!atoken.hidden && atoken.hiddenRequested)) {
3529 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
3530 + " -- going to hide");
3534 if (tokenNdx == firstToken) {
3535 // If we have hit a new Task, and the bottom
3536 // of the previous group didn't explicitly say to use
3537 // the orientation behind it, and the last app was
3538 // full screen, then we'll stick with the
3539 // user's orientation.
3540 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
3541 && lastFullscreen) {
3542 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3543 + " -- end of group, return " + lastOrientation);
3544 return lastOrientation;
3548 // We ignore any hidden applications on the top.
3549 if (atoken.hiddenRequested || atoken.willBeHidden) {
3550 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
3551 + " -- hidden on top");
3555 if (tokenNdx == 0) {
3556 // Last token in this task.
3557 lastOrientation = atoken.requestedOrientation;
3560 int or = atoken.requestedOrientation;
3561 // If this application is fullscreen, and didn't explicitly say
3562 // to use the orientation behind it, then just take whatever
3563 // orientation it has and ignores whatever is under it.
3564 lastFullscreen = atoken.appFullscreen;
3566 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3567 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3568 + " -- full screen, return " + or);
3571 // If this application has requested an explicit orientation,
3573 if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
3574 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3575 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3576 + " -- explicitly set, return " + or);
3579 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
3582 if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation");
3583 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3587 public Configuration updateOrientationFromAppTokens(
3588 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3589 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3590 "updateOrientationFromAppTokens()")) {
3591 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3594 Configuration config = null;
3595 long ident = Binder.clearCallingIdentity();
3597 synchronized(mWindowMap) {
3598 config = updateOrientationFromAppTokensLocked(currentConfig,
3599 freezeThisOneIfNeeded);
3602 Binder.restoreCallingIdentity(ident);
3606 private Configuration updateOrientationFromAppTokensLocked(
3607 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3608 Configuration config = null;
3610 if (updateOrientationFromAppTokensLocked(false)) {
3611 if (freezeThisOneIfNeeded != null) {
3612 AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
3613 if (atoken != null) {
3614 startAppFreezingScreenLocked(atoken, ActivityInfo.CONFIG_ORIENTATION);
3617 config = computeNewConfigurationLocked();
3619 } else if (currentConfig != null) {
3620 // No obvious action we need to take, but if our current
3621 // state mismatches the activity manager's, update it,
3622 // disregarding font scale, which should remain set to
3623 // the value of the previous configuration.
3624 mTempConfiguration.setToDefaults();
3625 mTempConfiguration.fontScale = currentConfig.fontScale;
3626 if (computeScreenConfigurationLocked(mTempConfiguration)) {
3627 if (currentConfig.diff(mTempConfiguration) != 0) {
3628 mWaitingForConfig = true;
3629 final DisplayContent displayContent = getDefaultDisplayContentLocked();
3630 displayContent.layoutNeeded = true;
3631 int anim[] = new int[2];
3632 if (displayContent.isDimming()) {
3633 anim[0] = anim[1] = 0;
3635 mPolicy.selectRotationAnimationLw(anim);
3637 startFreezingDisplayLocked(false, anim[0], anim[1]);
3638 config = new Configuration(mTempConfiguration);
3647 * Determine the new desired orientation of the display, returning
3648 * a non-null new Configuration if it has changed from the current
3649 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL
3650 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3651 * SCREEN. This will typically be done for you if you call
3652 * sendNewConfiguration().
3654 * The orientation is computed from non-application windows first. If none of
3655 * the non-application windows specify orientation, the orientation is computed from
3656 * application tokens.
3657 * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3658 * android.os.IBinder)
3660 boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
3661 long ident = Binder.clearCallingIdentity();
3663 int req = getOrientationFromWindowsLocked();
3664 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
3665 req = getOrientationFromAppTokensLocked();
3668 if (req != mForcedAppOrientation) {
3669 mForcedAppOrientation = req;
3670 //send a message to Policy indicating orientation change to take
3671 //action like disabling/enabling sensors etc.,
3672 mPolicy.setCurrentOrientationLw(req);
3673 if (updateRotationUncheckedLocked(inTransaction)) {
3681 Binder.restoreCallingIdentity(ident);
3686 public void setNewConfiguration(Configuration config) {
3687 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3688 "setNewConfiguration()")) {
3689 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3692 synchronized(mWindowMap) {
3693 mCurConfiguration = new Configuration(config);
3694 if (mWaitingForConfig) {
3695 mWaitingForConfig = false;
3696 mLastFinishedFreezeSource = "new-config";
3698 performLayoutAndPlaceSurfacesLocked();
3703 public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3704 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3705 "setAppOrientation()")) {
3706 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3709 synchronized(mWindowMap) {
3710 AppWindowToken atoken = findAppWindowToken(token.asBinder());
3711 if (atoken == null) {
3712 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
3716 atoken.requestedOrientation = requestedOrientation;
3721 public int getAppOrientation(IApplicationToken token) {
3722 synchronized(mWindowMap) {
3723 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3724 if (wtoken == null) {
3725 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3728 return wtoken.requestedOrientation;
3732 /** Call while in a Surface transaction. */
3733 void setFocusedStackLayer() {
3734 mFocusedStackLayer = 0;
3735 if (mFocusedApp != null) {
3736 final WindowList windows = mFocusedApp.allAppWindows;
3737 for (int i = windows.size() - 1; i >= 0; --i) {
3738 final WindowState win = windows.get(i);
3739 final int animLayer = win.mWinAnimator.mAnimLayer;
3740 if (win.mAttachedWindow == null && win.isVisibleLw() &&
3741 animLayer > mFocusedStackLayer) {
3742 mFocusedStackLayer = animLayer + LAYER_OFFSET_FOCUSED_STACK;
3746 if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedStackFrame to layer=" +
3747 mFocusedStackLayer);
3748 mFocusedStackFrame.setLayer(mFocusedStackLayer);
3751 void setFocusedStackFrame() {
3752 final TaskStack stack;
3753 if (mFocusedApp != null) {
3754 Task task = mTaskIdToTask.get(mFocusedApp.groupId);
3755 stack = task.mStack;
3756 task.getDisplayContent().setTouchExcludeRegion(stack);
3760 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame");
3761 SurfaceControl.openTransaction();
3763 if (stack == null) {
3764 mFocusedStackFrame.setVisibility(false);
3766 final StackBox box = stack.mStackBox;
3767 final Rect bounds = box.mBounds;
3768 final boolean multipleStacks = box.mParent != null;
3769 mFocusedStackFrame.setBounds(bounds);
3770 mFocusedStackFrame.setVisibility(multipleStacks);
3773 SurfaceControl.closeTransaction();
3774 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame");
3779 public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3780 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3781 "setFocusedApp()")) {
3782 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3785 synchronized(mWindowMap) {
3786 boolean changed = false;
3787 if (token == null) {
3788 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
3789 changed = mFocusedApp != null;
3792 mInputMonitor.setFocusedAppLw(null);
3795 AppWindowToken newFocus = findAppWindowToken(token);
3796 if (newFocus == null) {
3797 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
3800 changed = mFocusedApp != newFocus;
3801 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus
3802 + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
3803 mFocusedApp = newFocus;
3805 mInputMonitor.setFocusedAppLw(newFocus);
3809 if (moveFocusNow && changed) {
3810 final long origId = Binder.clearCallingIdentity();
3811 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
3812 Binder.restoreCallingIdentity(origId);
3818 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
3819 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3820 "prepareAppTransition()")) {
3821 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3824 synchronized(mWindowMap) {
3825 if (DEBUG_APP_TRANSITIONS) Slog.v(
3826 TAG, "Prepare app transition: transit=" + transit
3827 + " " + mAppTransition
3828 + " alwaysKeepCurrent=" + alwaysKeepCurrent
3829 + " Callers=" + Debug.getCallers(3));
3830 if (okToDisplay()) {
3831 if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) {
3832 mAppTransition.setAppTransition(transit);
3833 } else if (!alwaysKeepCurrent) {
3834 if (transit == AppTransition.TRANSIT_TASK_OPEN
3835 && mAppTransition.isTransitionEqual(
3836 AppTransition.TRANSIT_TASK_CLOSE)) {
3837 // Opening a new task always supersedes a close for the anim.
3838 mAppTransition.setAppTransition(transit);
3839 } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN
3840 && mAppTransition.isTransitionEqual(
3841 AppTransition.TRANSIT_ACTIVITY_CLOSE)) {
3842 // Opening a new activity always supersedes a close for the anim.
3843 mAppTransition.setAppTransition(transit);
3846 mAppTransition.prepare();
3847 mStartingIconInTransition = false;
3848 mSkipAppTransitionAnimation = false;
3849 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
3850 mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000);
3856 public int getPendingAppTransition() {
3857 return mAppTransition.getAppTransition();
3861 public void overridePendingAppTransition(String packageName,
3862 int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
3863 synchronized(mWindowMap) {
3864 mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,
3870 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
3872 synchronized(mWindowMap) {
3873 mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth,
3879 public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
3880 int startY, IRemoteCallback startedCallback, boolean scaleUp) {
3881 synchronized(mWindowMap) {
3882 mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
3883 startedCallback, scaleUp);
3888 public void executeAppTransition() {
3889 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3890 "executeAppTransition()")) {
3891 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3894 synchronized(mWindowMap) {
3895 if (DEBUG_APP_TRANSITIONS) {
3896 RuntimeException e = new RuntimeException("here");
3897 e.fillInStackTrace();
3898 Slog.w(TAG, "Execute app transition: " + mAppTransition, e);
3900 if (mAppTransition.isTransitionSet()) {
3901 mAppTransition.setReady();
3902 final long origId = Binder.clearCallingIdentity();
3903 performLayoutAndPlaceSurfacesLocked();
3904 Binder.restoreCallingIdentity(origId);
3910 public void setAppStartingWindow(IBinder token, String pkg,
3911 int theme, CompatibilityInfo compatInfo,
3912 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
3913 int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
3914 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3915 "setAppStartingWindow()")) {
3916 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3919 synchronized(mWindowMap) {
3920 if (DEBUG_STARTING_WINDOW) Slog.v(
3921 TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg
3922 + " transferFrom=" + transferFrom);
3924 AppWindowToken wtoken = findAppWindowToken(token);
3925 if (wtoken == null) {
3926 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
3930 // If the display is frozen, we won't do anything until the
3931 // actual window is displayed so there is no reason to put in
3932 // the starting window.
3933 if (!okToDisplay()) {
3937 if (wtoken.startingData != null) {
3941 if (transferFrom != null) {
3942 AppWindowToken ttoken = findAppWindowToken(transferFrom);
3943 if (ttoken != null) {
3944 WindowState startingWindow = ttoken.startingWindow;
3945 if (startingWindow != null) {
3946 if (mStartingIconInTransition) {
3947 // In this case, the starting icon has already
3948 // been displayed, so start letting windows get
3949 // shown immediately without any more transitions.
3950 mSkipAppTransitionAnimation = true;
3952 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
3953 "Moving existing starting " + startingWindow + " from " + ttoken
3955 final long origId = Binder.clearCallingIdentity();
3957 // Transfer the starting window over to the new
3959 wtoken.startingData = ttoken.startingData;
3960 wtoken.startingView = ttoken.startingView;
3961 wtoken.startingDisplayed = ttoken.startingDisplayed;
3962 ttoken.startingDisplayed = false;
3963 wtoken.startingWindow = startingWindow;
3964 wtoken.reportedVisible = ttoken.reportedVisible;
3965 ttoken.startingData = null;
3966 ttoken.startingView = null;
3967 ttoken.startingWindow = null;
3968 ttoken.startingMoved = true;
3969 startingWindow.mToken = wtoken;
3970 startingWindow.mRootToken = wtoken;
3971 startingWindow.mAppToken = wtoken;
3972 startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator;
3974 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
3975 Slog.v(TAG, "Removing starting window: " + startingWindow);
3977 removeStartingWindowTimeout(ttoken);
3978 startingWindow.getWindowList().remove(startingWindow);
3979 mWindowsChanged = true;
3980 if (DEBUG_ADD_REMOVE) Slog.v(TAG,
3981 "Removing starting " + startingWindow + " from " + ttoken);
3982 ttoken.windows.remove(startingWindow);
3983 ttoken.allAppWindows.remove(startingWindow);
3984 addWindowToListInOrderLocked(startingWindow, true);
3986 // Propagate other interesting state between the
3987 // tokens. If the old token is displayed, we should
3988 // immediately force the new one to be displayed. If
3989 // it is animating, we need to move that animation to
3991 if (ttoken.allDrawn) {
3992 wtoken.allDrawn = true;
3993 wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn;
3995 if (ttoken.firstWindowDrawn) {
3996 wtoken.firstWindowDrawn = true;
3998 if (!ttoken.hidden) {
3999 wtoken.hidden = false;
4000 wtoken.hiddenRequested = false;
4001 wtoken.willBeHidden = false;
4003 if (wtoken.clientHidden != ttoken.clientHidden) {
4004 wtoken.clientHidden = ttoken.clientHidden;
4005 wtoken.sendAppVisibilityToClients();
4007 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4008 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4009 if (tAppAnimator.animation != null) {
4010 wAppAnimator.animation = tAppAnimator.animation;
4011 wAppAnimator.animating = tAppAnimator.animating;
4012 wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment;
4013 tAppAnimator.animation = null;
4014 tAppAnimator.animLayerAdjustment = 0;
4015 wAppAnimator.updateLayers();
4016 tAppAnimator.updateLayers();
4019 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4020 true /*updateInputWindows*/);
4021 getDefaultDisplayContentLocked().layoutNeeded = true;
4022 performLayoutAndPlaceSurfacesLocked();
4023 Binder.restoreCallingIdentity(origId);
4025 } else if (ttoken.startingData != null) {
4026 // The previous app was getting ready to show a
4027 // starting window, but hasn't yet done so. Steal it!
4028 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
4029 "Moving pending starting from " + ttoken
4031 wtoken.startingData = ttoken.startingData;
4032 ttoken.startingData = null;
4033 ttoken.startingMoved = true;
4034 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4035 // Note: we really want to do sendMessageAtFrontOfQueue() because we
4036 // want to process the message ASAP, before any other queued
4038 mH.sendMessageAtFrontOfQueue(m);
4041 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4042 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4043 if (tAppAnimator.thumbnail != null) {
4044 // The old token is animating with a thumbnail, transfer
4045 // that to the new token.
4046 if (wAppAnimator.thumbnail != null) {
4047 wAppAnimator.thumbnail.destroy();
4049 wAppAnimator.thumbnail = tAppAnimator.thumbnail;
4050 wAppAnimator.thumbnailX = tAppAnimator.thumbnailX;
4051 wAppAnimator.thumbnailY = tAppAnimator.thumbnailY;
4052 wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
4053 wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
4054 tAppAnimator.thumbnail = null;
4059 // There is no existing starting window, and the caller doesn't
4060 // want us to create one, so that's it!
4061 if (!createIfNeeded) {
4065 // If this is a translucent window, then don't
4066 // show a starting window -- the current effect (a full-screen
4067 // opaque starting window that fades away to the real contents
4068 // when it is ready) does not work for this.
4069 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x"
4070 + Integer.toHexString(theme));
4072 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
4073 com.android.internal.R.styleable.Window, mCurrentUserId);
4075 // Whoops! App doesn't exist. Um. Okay. We'll just
4076 // pretend like we didn't see that.
4079 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent="
4080 + ent.array.getBoolean(
4081 com.android.internal.R.styleable.Window_windowIsTranslucent, false)
4083 + ent.array.getBoolean(
4084 com.android.internal.R.styleable.Window_windowIsFloating, false)
4086 + ent.array.getBoolean(
4087 com.android.internal.R.styleable.Window_windowShowWallpaper, false));
4088 if (ent.array.getBoolean(
4089 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
4092 if (ent.array.getBoolean(
4093 com.android.internal.R.styleable.Window_windowIsFloating, false)) {
4096 if (ent.array.getBoolean(
4097 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
4098 if (mWallpaperTarget == null) {
4099 // If this theme is requesting a wallpaper, and the wallpaper
4100 // is not curently visible, then this effectively serves as
4101 // an opaque window and our starting window transition animation
4102 // can still work. We just need to make sure the starting window
4103 // is also showing the wallpaper.
4104 windowFlags |= FLAG_SHOW_WALLPAPER;
4111 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData");
4112 mStartingIconInTransition = true;
4113 wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
4114 labelRes, icon, logo, windowFlags);
4115 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4116 // Note: we really want to do sendMessageAtFrontOfQueue() because we
4117 // want to process the message ASAP, before any other queued
4119 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
4120 mH.sendMessageAtFrontOfQueue(m);
4125 public void setAppWillBeHidden(IBinder token) {
4126 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4127 "setAppWillBeHidden()")) {
4128 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4131 AppWindowToken wtoken;
4133 synchronized(mWindowMap) {
4134 wtoken = findAppWindowToken(token);
4135 if (wtoken == null) {
4136 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
4139 wtoken.willBeHidden = true;
4143 public void setAppFullscreen(IBinder token, boolean toOpaque) {
4144 AppWindowToken atoken = findAppWindowToken(token);
4145 if (atoken != null) {
4146 atoken.appFullscreen = toOpaque;
4151 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
4152 boolean visible, int transit, boolean performLayout) {
4153 boolean delayed = false;
4155 if (wtoken.clientHidden == visible) {
4156 wtoken.clientHidden = !visible;
4157 wtoken.sendAppVisibilityToClients();
4160 wtoken.willBeHidden = false;
4161 if (wtoken.hidden == visible) {
4162 boolean changed = false;
4163 if (DEBUG_APP_TRANSITIONS) Slog.v(
4164 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
4165 + " performLayout=" + performLayout);
4167 boolean runningAppAnimation = false;
4169 if (transit != AppTransition.TRANSIT_UNSET) {
4170 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
4171 wtoken.mAppAnimator.animation = null;
4173 if (applyAnimationLocked(wtoken, lp, transit, visible)) {
4174 delayed = runningAppAnimation = true;
4176 WindowState window = wtoken.findMainWindow();
4177 //TODO (multidisplay): Magnification is supported only for the default display.
4178 if (window != null && mDisplayMagnifier != null
4179 && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
4180 mDisplayMagnifier.onAppWindowTransitionLocked(window, transit);
4185 final int N = wtoken.allAppWindows.size();
4186 for (int i=0; i<N; i++) {
4187 WindowState win = wtoken.allAppWindows.get(i);
4188 if (win == wtoken.startingWindow) {
4192 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
4195 if (!win.isVisibleNow()) {
4196 if (!runningAppAnimation) {
4197 win.mWinAnimator.applyAnimationLocked(
4198 WindowManagerPolicy.TRANSIT_ENTER, true);
4199 //TODO (multidisplay): Magnification is supported only for the default
4200 if (mDisplayMagnifier != null
4201 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4202 mDisplayMagnifier.onWindowTransitionLocked(win,
4203 WindowManagerPolicy.TRANSIT_ENTER);
4207 win.mDisplayContent.layoutNeeded = true;
4209 } else if (win.isVisibleNow()) {
4210 if (!runningAppAnimation) {
4211 win.mWinAnimator.applyAnimationLocked(
4212 WindowManagerPolicy.TRANSIT_EXIT, false);
4213 //TODO (multidisplay): Magnification is supported only for the default
4214 if (mDisplayMagnifier != null
4215 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4216 mDisplayMagnifier.onWindowTransitionLocked(win,
4217 WindowManagerPolicy.TRANSIT_EXIT);
4221 win.mDisplayContent.layoutNeeded = true;
4225 wtoken.hidden = wtoken.hiddenRequested = !visible;
4227 unsetAppFreezingScreenLocked(wtoken, true, true);
4229 // If we are being set visible, and the starting window is
4230 // not yet displayed, then make sure it doesn't get displayed.
4231 WindowState swin = wtoken.startingWindow;
4232 if (swin != null && !swin.isDrawnLw()) {
4233 swin.mPolicyVisibility = false;
4234 swin.mPolicyVisibilityAfterAnim = false;
4238 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
4239 + ": hidden=" + wtoken.hidden + " hiddenRequested="
4240 + wtoken.hiddenRequested);
4243 mInputMonitor.setUpdateInputWindowsNeededLw();
4244 if (performLayout) {
4245 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4246 false /*updateInputWindows*/);
4247 performLayoutAndPlaceSurfacesLocked();
4249 mInputMonitor.updateInputWindowsLw(false /*force*/);
4253 if (wtoken.mAppAnimator.animation != null) {
4257 for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
4258 if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) {
4267 public void setAppVisibility(IBinder token, boolean visible) {
4268 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4269 "setAppVisibility()")) {
4270 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4273 AppWindowToken wtoken;
4275 synchronized(mWindowMap) {
4276 wtoken = findAppWindowToken(token);
4277 if (wtoken == null) {
4278 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
4282 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
4283 RuntimeException e = null;
4284 if (!HIDE_STACK_CRAWLS) {
4285 e = new RuntimeException();
4286 e.fillInStackTrace();
4288 Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible
4289 + "): " + mAppTransition
4290 + " hidden=" + wtoken.hidden
4291 + " hiddenRequested=" + wtoken.hiddenRequested, e);
4294 // If we are preparing an app transition, then delay changing
4295 // the visibility of this token until we execute that transition.
4296 if (okToDisplay() && mAppTransition.isTransitionSet()) {
4297 // Already in requested state, don't do anything more.
4298 if (wtoken.hiddenRequested != visible) {
4301 wtoken.hiddenRequested = !visible;
4303 if (!wtoken.startingDisplayed) {
4304 if (DEBUG_APP_TRANSITIONS) Slog.v(
4305 TAG, "Setting dummy animation on: " + wtoken);
4306 wtoken.mAppAnimator.setDummyAnimation();
4308 mOpeningApps.remove(wtoken);
4309 mClosingApps.remove(wtoken);
4310 wtoken.waitingToShow = wtoken.waitingToHide = false;
4311 wtoken.inPendingTransaction = true;
4313 mOpeningApps.add(wtoken);
4314 wtoken.startingMoved = false;
4316 // If the token is currently hidden (should be the
4317 // common case), then we need to set up to wait for
4318 // its windows to be ready.
4319 if (wtoken.hidden) {
4320 wtoken.allDrawn = false;
4321 wtoken.deferClearAllDrawn = false;
4322 wtoken.waitingToShow = true;
4324 if (wtoken.clientHidden) {
4325 // In the case where we are making an app visible
4326 // but holding off for a transition, we still need
4327 // to tell the client to make its windows visible so
4328 // they get drawn. Otherwise, we will wait on
4329 // performing the transition until all windows have
4330 // been drawn, they never will be, and we are sad.
4331 wtoken.clientHidden = false;
4332 wtoken.sendAppVisibilityToClients();
4336 mClosingApps.add(wtoken);
4338 // If the token is currently visible (should be the
4339 // common case), then set up to wait for it to be hidden.
4340 if (!wtoken.hidden) {
4341 wtoken.waitingToHide = true;
4347 final long origId = Binder.clearCallingIdentity();
4348 setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
4350 wtoken.updateReportedVisibilityLocked();
4351 Binder.restoreCallingIdentity(origId);
4355 void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
4356 boolean unfreezeSurfaceNow, boolean force) {
4357 if (wtoken.mAppAnimator.freezingScreen) {
4358 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
4359 + " force=" + force);
4360 final int N = wtoken.allAppWindows.size();
4361 boolean unfrozeWindows = false;
4362 for (int i=0; i<N; i++) {
4363 WindowState w = wtoken.allAppWindows.get(i);
4364 if (w.mAppFreezing) {
4365 w.mAppFreezing = false;
4366 if (w.mHasSurface && !w.mOrientationChanging) {
4367 if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w);
4368 w.mOrientationChanging = true;
4369 mInnerFields.mOrientationChangeComplete = false;
4371 w.mLastFreezeDuration = 0;
4372 unfrozeWindows = true;
4373 w.mDisplayContent.layoutNeeded = true;
4376 if (force || unfrozeWindows) {
4377 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
4378 wtoken.mAppAnimator.freezingScreen = false;
4379 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime()
4380 - mDisplayFreezeTime);
4381 mAppsFreezingScreen--;
4382 mLastFinishedFreezeSource = wtoken;
4384 if (unfreezeSurfaceNow) {
4385 if (unfrozeWindows) {
4386 performLayoutAndPlaceSurfacesLocked();
4388 stopFreezingDisplayLocked();
4393 public void startAppFreezingScreenLocked(AppWindowToken wtoken,
4394 int configChanges) {
4395 if (DEBUG_ORIENTATION) {
4396 RuntimeException e = null;
4397 if (!HIDE_STACK_CRAWLS) {
4398 e = new RuntimeException();
4399 e.fillInStackTrace();
4401 Slog.i(TAG, "Set freezing of " + wtoken.appToken
4402 + ": hidden=" + wtoken.hidden + " freezing="
4403 + wtoken.mAppAnimator.freezingScreen, e);
4405 if (!wtoken.hiddenRequested) {
4406 if (!wtoken.mAppAnimator.freezingScreen) {
4407 wtoken.mAppAnimator.freezingScreen = true;
4408 wtoken.mAppAnimator.lastFreezeDuration = 0;
4409 mAppsFreezingScreen++;
4410 if (mAppsFreezingScreen == 1) {
4411 startFreezingDisplayLocked(false, 0, 0);
4412 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
4413 mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000);
4416 final int N = wtoken.allAppWindows.size();
4417 for (int i=0; i<N; i++) {
4418 WindowState w = wtoken.allAppWindows.get(i);
4419 w.mAppFreezing = true;
4425 public void startAppFreezingScreen(IBinder token, int configChanges) {
4426 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4427 "setAppFreezingScreen()")) {
4428 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4431 synchronized(mWindowMap) {
4432 if (configChanges == 0 && okToDisplay()) {
4433 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
4437 AppWindowToken wtoken = findAppWindowToken(token);
4438 if (wtoken == null || wtoken.appToken == null) {
4439 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
4442 final long origId = Binder.clearCallingIdentity();
4443 startAppFreezingScreenLocked(wtoken, configChanges);
4444 Binder.restoreCallingIdentity(origId);
4449 public void stopAppFreezingScreen(IBinder token, boolean force) {
4450 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4451 "setAppFreezingScreen()")) {
4452 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4455 synchronized(mWindowMap) {
4456 AppWindowToken wtoken = findAppWindowToken(token);
4457 if (wtoken == null || wtoken.appToken == null) {
4460 final long origId = Binder.clearCallingIdentity();
4461 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
4462 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
4463 unsetAppFreezingScreenLocked(wtoken, true, force);
4464 Binder.restoreCallingIdentity(origId);
4469 public void removeAppToken(IBinder token) {
4470 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4471 "removeAppToken()")) {
4472 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4475 AppWindowToken wtoken = null;
4476 AppWindowToken startingToken = null;
4477 boolean delayed = false;
4479 final long origId = Binder.clearCallingIdentity();
4480 synchronized(mWindowMap) {
4481 WindowToken basewtoken = mTokenMap.remove(token);
4482 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
4483 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
4484 delayed = setTokenVisibilityLocked(wtoken, null, false,
4485 AppTransition.TRANSIT_UNSET, true);
4486 wtoken.inPendingTransaction = false;
4487 mOpeningApps.remove(wtoken);
4488 wtoken.waitingToShow = false;
4489 if (mClosingApps.contains(wtoken)) {
4491 } else if (mAppTransition.isTransitionSet()) {
4492 mClosingApps.add(wtoken);
4493 wtoken.waitingToHide = true;
4496 if (DEBUG_APP_TRANSITIONS) Slog.v(
4497 TAG, "Removing app " + wtoken + " delayed=" + delayed
4498 + " animation=" + wtoken.mAppAnimator.animation
4499 + " animating=" + wtoken.mAppAnimator.animating);
4500 final Task task = mTaskIdToTask.get(wtoken.groupId);
4501 DisplayContent displayContent = task.getDisplayContent();
4503 // set the token aside because it has an active animation to be finished
4504 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
4505 "removeAppToken make exiting: " + wtoken);
4506 displayContent.mExitingAppTokens.add(wtoken);
4508 // Make sure there is no animation running on this token,
4509 // so any windows associated with it will be removed as
4510 // soon as their animations are complete
4511 wtoken.mAppAnimator.clearAnimation();
4512 wtoken.mAppAnimator.animating = false;
4514 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
4515 "removeAppToken: " + wtoken);
4517 if (task.removeAppToken(wtoken)) {
4518 mTaskIdToTask.delete(wtoken.groupId);
4520 wtoken.removed = true;
4521 if (wtoken.startingData != null) {
4522 startingToken = wtoken;
4524 unsetAppFreezingScreenLocked(wtoken, true, true);
4525 if (mFocusedApp == wtoken) {
4526 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken);
4528 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
4529 mInputMonitor.setFocusedAppLw(null);
4532 Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
4535 if (!delayed && wtoken != null) {
4536 wtoken.updateReportedVisibilityLocked();
4539 Binder.restoreCallingIdentity(origId);
4541 // Will only remove if startingToken non null.
4542 scheduleRemoveStartingWindow(startingToken);
4545 void removeStartingWindowTimeout(AppWindowToken wtoken) {
4546 if (wtoken != null) {
4547 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
4548 ": Remove starting window timeout " + wtoken + (wtoken != null ?
4549 " startingWindow=" + wtoken.startingWindow : ""));
4550 mH.removeMessages(H.REMOVE_STARTING_TIMEOUT, wtoken);
4554 void scheduleRemoveStartingWindow(AppWindowToken wtoken) {
4555 if (wtoken != null && wtoken.startingWindow != null) {
4556 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
4557 ": Schedule remove starting " + wtoken + (wtoken != null ?
4558 " startingWindow=" + wtoken.startingWindow : ""));
4559 removeStartingWindowTimeout(wtoken);
4560 Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
4564 private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
4565 final int NW = token.windows.size();
4567 mWindowsChanged = true;
4569 for (int i=0; i<NW; i++) {
4570 WindowState win = token.windows.get(i);
4571 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
4572 win.getWindowList().remove(win);
4573 int j = win.mChildWindows.size();
4576 WindowState cwin = win.mChildWindows.get(j);
4577 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
4578 "Tmp removing child window " + cwin);
4579 cwin.getWindowList().remove(cwin);
4585 void dumpAppTokensLocked() {
4586 final int numDisplays = mDisplayContents.size();
4587 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4588 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
4589 Slog.v(TAG, " Display " + displayContent.getDisplayId());
4590 final ArrayList<Task> tasks = displayContent.getTasks();
4591 int i = displayContent.numTokens();
4592 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
4593 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
4594 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
4595 final AppWindowToken wtoken = tokens.get(tokenNdx);
4596 Slog.v(TAG, " #" + --i + ": " + wtoken.token);
4602 void dumpWindowsLocked() {
4604 final int numDisplays = mDisplayContents.size();
4605 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4606 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
4607 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
4608 Slog.v(TAG, " #" + i++ + ": " + windows.get(winNdx));
4613 private int findAppWindowInsertionPointLocked(AppWindowToken target) {
4614 final int taskId = target.groupId;
4615 Task targetTask = mTaskIdToTask.get(taskId);
4616 if (targetTask == null) {
4617 Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId="
4621 DisplayContent displayContent = targetTask.getDisplayContent();
4622 if (displayContent == null) {
4623 Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target);
4626 final WindowList windows = displayContent.getWindowList();
4627 final int NW = windows.size();
4629 boolean found = false;
4630 final ArrayList<Task> tasks = displayContent.getTasks();
4631 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
4632 final Task task = tasks.get(taskNdx);
4633 if (!found && task.taskId != taskId) {
4636 AppTokenList tokens = task.mAppTokens;
4637 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
4638 final AppWindowToken wtoken = tokens.get(tokenNdx);
4639 if (!found && wtoken == target) {
4643 // Find the first app token below the new position that has
4644 // a window displayed.
4645 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token);
4646 if (wtoken.sendingToBottom) {
4647 if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom");
4650 for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
4651 WindowState win = wtoken.windows.get(i);
4652 for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
4653 WindowState cwin = win.mChildWindows.get(j);
4654 if (cwin.mSubLayer >= 0) {
4655 for (int pos = NW - 1; pos >= 0; pos--) {
4656 if (windows.get(pos) == cwin) {
4657 if (DEBUG_REORDER) Slog.v(TAG,
4658 "Found child win @" + (pos + 1));
4664 for (int pos = NW - 1; pos >= 0; pos--) {
4665 if (windows.get(pos) == win) {
4666 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1));
4674 // Never put an app window underneath wallpaper.
4675 for (int pos = NW - 1; pos >= 0; pos--) {
4676 if (windows.get(pos).mIsWallpaper) {
4677 if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos);
4684 private final int reAddWindowLocked(int index, WindowState win) {
4685 final WindowList windows = win.getWindowList();
4686 final int NCW = win.mChildWindows.size();
4687 boolean added = false;
4688 for (int j=0; j<NCW; j++) {
4689 WindowState cwin = win.mChildWindows.get(j);
4690 if (!added && cwin.mSubLayer >= 0) {
4691 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
4692 + index + ": " + cwin);
4693 win.mRebuilding = false;
4694 windows.add(index, win);
4698 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4699 + index + ": " + cwin);
4700 cwin.mRebuilding = false;
4701 windows.add(index, cwin);
4705 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4706 + index + ": " + win);
4707 win.mRebuilding = false;
4708 windows.add(index, win);
4711 mWindowsChanged = true;
4715 private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index,
4716 WindowToken token) {
4717 final int NW = token.windows.size();
4718 for (int i=0; i<NW; i++) {
4719 final WindowState win = token.windows.get(i);
4720 if (win.mDisplayContent == displayContent) {
4721 index = reAddWindowLocked(index, win);
4727 void moveStackWindowsLocked(TaskStack stack) {
4728 DisplayContent displayContent = stack.getDisplayContent();
4730 // First remove all of the windows from the list.
4731 final ArrayList<Task> tasks = stack.getTasks();
4732 final int numTasks = tasks.size();
4733 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4734 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
4735 final int numTokens = tokens.size();
4736 for (int tokenNdx = numTokens - 1; tokenNdx >= 0; --tokenNdx) {
4737 tmpRemoveAppWindowsLocked(tokens.get(tokenNdx));
4741 // And now add them back at the correct place.
4742 // Where to start adding?
4743 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4744 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
4745 int pos = findAppWindowInsertionPointLocked(tokens.get(0));
4746 final int numTokens = tokens.size();
4747 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4748 final AppWindowToken wtoken = tokens.get(tokenNdx);
4749 if (wtoken != null) {
4750 final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
4751 if (newPos != pos) {
4752 displayContent.layoutNeeded = true;
4759 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4760 false /*updateInputWindows*/)) {
4761 assignLayersLocked(displayContent.getWindowList());
4764 mInputMonitor.setUpdateInputWindowsNeededLw();
4765 performLayoutAndPlaceSurfacesLocked();
4766 mInputMonitor.updateInputWindowsLw(false /*force*/);
4771 public void moveTaskToTop(int taskId) {
4772 final long origId = Binder.clearCallingIdentity();
4774 synchronized(mWindowMap) {
4775 Task task = mTaskIdToTask.get(taskId);
4777 // Normal behavior, addAppToken will be called next and task will be created.
4780 final TaskStack stack = task.mStack;
4781 final DisplayContent displayContent = task.getDisplayContent();
4782 final boolean isHomeStackTask = stack.isHomeStack();
4783 if (isHomeStackTask != displayContent.homeOnTop()) {
4784 // First move the stack itself.
4785 displayContent.moveHomeStackBox(isHomeStackTask);
4787 stack.moveTaskToTop(task);
4788 displayContent.moveStack(stack, true);
4791 Binder.restoreCallingIdentity(origId);
4795 public void moveTaskToBottom(int taskId) {
4796 final long origId = Binder.clearCallingIdentity();
4798 synchronized(mWindowMap) {
4799 Task task = mTaskIdToTask.get(taskId);
4801 Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId
4802 + " not found in mTaskIdToTask");
4805 final TaskStack stack = task.mStack;
4806 stack.moveTaskToBottom(task);
4807 moveStackWindowsLocked(stack);
4810 Binder.restoreCallingIdentity(origId);
4815 * Create a new TaskStack and place it next to an existing stack.
4816 * @param stackId The unique identifier of the new stack.
4817 * @param relativeStackBoxId The existing stack that this stack goes before or after.
4818 * @param position One of:
4819 * {@link StackBox#TASK_STACK_GOES_BEFORE}
4820 * {@link StackBox#TASK_STACK_GOES_AFTER}
4821 * {@link StackBox#TASK_STACK_GOES_ABOVE}
4822 * {@link StackBox#TASK_STACK_GOES_BELOW}
4823 * {@link StackBox#TASK_STACK_GOES_UNDER}
4824 * {@link StackBox#TASK_STACK_GOES_OVER}
4825 * @param weight Relative weight for determining how big to make the new TaskStack.
4827 public void createStack(int stackId, int relativeStackBoxId, int position, float weight) {
4828 synchronized (mWindowMap) {
4829 if (position <= StackBox.TASK_STACK_GOES_BELOW &&
4830 (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX)) {
4831 throw new IllegalArgumentException(
4832 "createStack: weight must be between " + STACK_WEIGHT_MIN + " and " +
4833 STACK_WEIGHT_MAX + ", weight=" + weight);
4835 final int numDisplays = mDisplayContents.size();
4836 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4837 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
4838 TaskStack stack = displayContent.createStack(stackId, relativeStackBoxId, position,
4840 if (stack != null) {
4841 mStackIdToStack.put(stackId, stack);
4842 displayContent.moveStack(stack, true);
4843 performLayoutAndPlaceSurfacesLocked();
4847 Slog.e(TAG, "createStack: Unable to find relativeStackBoxId=" + relativeStackBoxId);
4851 public int removeStack(int stackId) {
4852 synchronized (mWindowMap) {
4853 final TaskStack stack = mStackIdToStack.get(stackId);
4854 if (stack != null) {
4855 mStackIdToStack.delete(stackId);
4856 int nextStackId = stack.remove();
4857 stack.getDisplayContent().layoutNeeded = true;
4858 requestTraversalLocked();
4861 if (DEBUG_STACK) Slog.i(TAG, "removeStack: could not find stackId=" + stackId);
4863 return HOME_STACK_ID;
4866 public void removeTask(int taskId) {
4867 synchronized (mWindowMap) {
4868 Task task = mTaskIdToTask.get(taskId);
4870 if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId);
4873 final TaskStack stack = task.mStack;
4874 stack.removeTask(task);
4875 stack.getDisplayContent().layoutNeeded = true;
4879 public void addTask(int taskId, int stackId, boolean toTop) {
4880 synchronized (mWindowMap) {
4881 Task task = mTaskIdToTask.get(taskId);
4885 TaskStack stack = mStackIdToStack.get(stackId);
4886 stack.addTask(task, toTop);
4887 final DisplayContent displayContent = stack.getDisplayContent();
4888 displayContent.layoutNeeded = true;
4889 performLayoutAndPlaceSurfacesLocked();
4893 public void resizeStackBox(int stackBoxId, float weight) {
4894 if (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX) {
4895 throw new IllegalArgumentException(
4896 "resizeStack: weight must be between " + STACK_WEIGHT_MIN + " and " +
4897 STACK_WEIGHT_MAX + ", weight=" + weight);
4899 synchronized (mWindowMap) {
4900 final int numDisplays = mDisplayContents.size();
4901 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4902 if (mDisplayContents.valueAt(displayNdx).resizeStack(stackBoxId, weight)) {
4903 performLayoutAndPlaceSurfacesLocked();
4908 throw new IllegalArgumentException("resizeStack: stackBoxId " + stackBoxId
4912 public ArrayList<StackBoxInfo> getStackBoxInfos() {
4913 synchronized(mWindowMap) {
4914 return getDefaultDisplayContentLocked().getStackBoxInfos();
4918 public Rect getStackBounds(int stackId) {
4919 final int numDisplays = mDisplayContents.size();
4920 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4921 Rect bounds = mDisplayContents.valueAt(displayNdx).getStackBounds(stackId);
4922 if (bounds != null) {
4929 // -------------------------------------------------------------
4930 // Misc IWindowSession methods
4931 // -------------------------------------------------------------
4934 public void startFreezingScreen(int exitAnim, int enterAnim) {
4935 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
4936 "startFreezingScreen()")) {
4937 throw new SecurityException("Requires FREEZE_SCREEN permission");
4940 synchronized(mWindowMap) {
4941 if (!mClientFreezingScreen) {
4942 mClientFreezingScreen = true;
4943 final long origId = Binder.clearCallingIdentity();
4945 startFreezingDisplayLocked(false, exitAnim, enterAnim);
4946 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
4947 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
4949 Binder.restoreCallingIdentity(origId);
4956 public void stopFreezingScreen() {
4957 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
4958 "stopFreezingScreen()")) {
4959 throw new SecurityException("Requires FREEZE_SCREEN permission");
4962 synchronized(mWindowMap) {
4963 if (mClientFreezingScreen) {
4964 mClientFreezingScreen = false;
4965 mLastFinishedFreezeSource = "client";
4966 final long origId = Binder.clearCallingIdentity();
4968 stopFreezingDisplayLocked();
4970 Binder.restoreCallingIdentity(origId);
4977 public void disableKeyguard(IBinder token, String tag) {
4978 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
4979 != PackageManager.PERMISSION_GRANTED) {
4980 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4983 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
4984 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
4988 public void reenableKeyguard(IBinder token) {
4989 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
4990 != PackageManager.PERMISSION_GRANTED) {
4991 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4994 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
4995 KeyguardDisableHandler.KEYGUARD_REENABLE, token));
4999 * @see android.app.KeyguardManager#exitKeyguardSecurely
5002 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
5003 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5004 != PackageManager.PERMISSION_GRANTED) {
5005 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5007 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
5009 public void onKeyguardExitResult(boolean success) {
5011 callback.onKeyguardExitResult(success);
5012 } catch (RemoteException e) {
5013 // Client has died, we don't care.
5020 public boolean inKeyguardRestrictedInputMode() {
5021 return mPolicy.inKeyguardRestrictedKeyInputMode();
5025 public boolean isKeyguardLocked() {
5026 return mPolicy.isKeyguardLocked();
5030 public boolean isKeyguardSecure() {
5031 return mPolicy.isKeyguardSecure();
5035 public void dismissKeyguard() {
5036 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5037 != PackageManager.PERMISSION_GRANTED) {
5038 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5040 synchronized(mWindowMap) {
5041 mPolicy.dismissKeyguardLw();
5046 public void closeSystemDialogs(String reason) {
5047 synchronized(mWindowMap) {
5048 final int numDisplays = mDisplayContents.size();
5049 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5050 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5051 final int numWindows = windows.size();
5052 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5053 final WindowState w = windows.get(winNdx);
5054 if (w.mHasSurface) {
5056 w.mClient.closeSystemDialogs(reason);
5057 } catch (RemoteException e) {
5065 static float fixScale(float scale) {
5066 if (scale < 0) scale = 0;
5067 else if (scale > 20) scale = 20;
5068 return Math.abs(scale);
5072 public void setAnimationScale(int which, float scale) {
5073 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5074 "setAnimationScale()")) {
5075 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5078 scale = fixScale(scale);
5080 case 0: mWindowAnimationScale = scale; break;
5081 case 1: mTransitionAnimationScale = scale; break;
5082 case 2: mAnimatorDurationScale = scale; break;
5086 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5090 public void setAnimationScales(float[] scales) {
5091 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5092 "setAnimationScale()")) {
5093 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5096 if (scales != null) {
5097 if (scales.length >= 1) {
5098 mWindowAnimationScale = fixScale(scales[0]);
5100 if (scales.length >= 2) {
5101 mTransitionAnimationScale = fixScale(scales[1]);
5103 if (scales.length >= 3) {
5104 setAnimatorDurationScale(fixScale(scales[2]));
5109 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5112 private void setAnimatorDurationScale(float scale) {
5113 mAnimatorDurationScale = scale;
5114 ValueAnimator.setDurationScale(scale);
5118 public float getAnimationScale(int which) {
5120 case 0: return mWindowAnimationScale;
5121 case 1: return mTransitionAnimationScale;
5122 case 2: return mAnimatorDurationScale;
5128 public float[] getAnimationScales() {
5129 return new float[] { mWindowAnimationScale, mTransitionAnimationScale,
5130 mAnimatorDurationScale };
5134 public void registerPointerEventListener(PointerEventListener listener) {
5135 mPointerEventDispatcher.registerInputEventListener(listener);
5139 public void unregisterPointerEventListener(PointerEventListener listener) {
5140 mPointerEventDispatcher.unregisterInputEventListener(listener);
5143 // Called by window manager policy. Not exposed externally.
5145 public int getLidState() {
5146 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5147 InputManagerService.SW_LID);
5149 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5151 } else if (sw == 0) {
5152 // Switch state: AKEY_STATE_UP.
5155 // Switch state: AKEY_STATE_UNKNOWN.
5160 // Called by window manager policy. Not exposed externally.
5162 public void switchKeyboardLayout(int deviceId, int direction) {
5163 mInputManager.switchKeyboardLayout(deviceId, direction);
5166 // Called by window manager policy. Not exposed externally.
5168 public void shutdown(boolean confirm) {
5169 ShutdownThread.shutdown(mContext, confirm);
5172 // Called by window manager policy. Not exposed externally.
5174 public void rebootSafeMode(boolean confirm) {
5175 ShutdownThread.rebootSafeMode(mContext, confirm);
5179 public void setInputFilter(IInputFilter filter) {
5180 if (!checkCallingPermission(android.Manifest.permission.FILTER_EVENTS, "setInputFilter()")) {
5181 throw new SecurityException("Requires FILTER_EVENTS permission");
5183 mInputManager.setInputFilter(filter);
5187 public void setTouchExplorationEnabled(boolean enabled) {
5188 mPolicy.setTouchExplorationEnabled(enabled);
5191 public void setCurrentUser(final int newUserId) {
5192 synchronized (mWindowMap) {
5193 int oldUserId = mCurrentUserId;
5194 mCurrentUserId = newUserId;
5195 mAppTransition.setCurrentUser(newUserId);
5196 mPolicy.setCurrentUserLw(newUserId);
5198 // Hide windows that should not be seen by the new user.
5199 final int numDisplays = mDisplayContents.size();
5200 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5201 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
5202 displayContent.switchUserStacks(oldUserId, newUserId);
5203 rebuildAppWindowListLocked(displayContent);
5205 performLayoutAndPlaceSurfacesLocked();
5209 public void enableScreenAfterBoot() {
5210 synchronized(mWindowMap) {
5212 RuntimeException here = new RuntimeException("here");
5213 here.fillInStackTrace();
5214 Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
5215 + " mForceDisplayEnabled=" + mForceDisplayEnabled
5216 + " mShowingBootMessages=" + mShowingBootMessages
5217 + " mSystemBooted=" + mSystemBooted, here);
5219 if (mSystemBooted) {
5222 mSystemBooted = true;
5223 hideBootMessagesLocked();
5224 // If the screen still doesn't come up after 30 seconds, give
5225 // up and turn it on.
5226 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
5229 mPolicy.systemBooted();
5231 performEnableScreen();
5234 void enableScreenIfNeededLocked() {
5236 RuntimeException here = new RuntimeException("here");
5237 here.fillInStackTrace();
5238 Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
5239 + " mForceDisplayEnabled=" + mForceDisplayEnabled
5240 + " mShowingBootMessages=" + mShowingBootMessages
5241 + " mSystemBooted=" + mSystemBooted, here);
5243 if (mDisplayEnabled) {
5246 if (!mSystemBooted && !mShowingBootMessages) {
5249 mH.sendEmptyMessage(H.ENABLE_SCREEN);
5252 public void performBootTimeout() {
5253 synchronized(mWindowMap) {
5254 if (mDisplayEnabled || mHeadless) {
5257 Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled");
5258 mForceDisplayEnabled = true;
5260 performEnableScreen();
5263 public void performEnableScreen() {
5264 synchronized(mWindowMap) {
5266 RuntimeException here = new RuntimeException("here");
5267 here.fillInStackTrace();
5268 Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
5269 + " mForceDisplayEnabled=" + mForceDisplayEnabled
5270 + " mShowingBootMessages=" + mShowingBootMessages
5271 + " mSystemBooted=" + mSystemBooted
5272 + " mOnlyCore=" + mOnlyCore, here);
5274 if (mDisplayEnabled) {
5277 if (!mSystemBooted && !mShowingBootMessages) {
5281 if (!mForceDisplayEnabled) {
5282 // Don't enable the screen until all existing windows
5284 boolean haveBootMsg = false;
5285 boolean haveApp = false;
5286 // if the wallpaper service is disabled on the device, we're never going to have
5287 // wallpaper, don't bother waiting for it
5288 boolean haveWallpaper = false;
5289 boolean wallpaperEnabled = mContext.getResources().getBoolean(
5290 com.android.internal.R.bool.config_enableWallpaperService)
5292 boolean haveKeyguard = true;
5293 // TODO(multidisplay): Expand to all displays?
5294 final WindowList windows = getDefaultWindowListLocked();
5295 final int N = windows.size();
5296 for (int i=0; i<N; i++) {
5297 WindowState w = windows.get(i);
5298 if (w.mAttrs.type == TYPE_KEYGUARD) {
5299 // Only if there is a keyguard attached to the window manager
5300 // will we consider ourselves as having a keyguard. If it
5301 // isn't attached, we don't know if it wants to be shown or
5302 // hidden. If it is attached, we will say we have a keyguard
5303 // if the window doesn't want to be visible, because in that
5304 // case it explicitly doesn't want to be shown so we should
5305 // not delay turning the screen on for it.
5306 boolean vis = w.mViewVisibility == View.VISIBLE
5307 && w.mPolicyVisibility;
5308 haveKeyguard = !vis;
5310 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
5313 if (w.isDrawnLw()) {
5314 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
5316 } else if (w.mAttrs.type == TYPE_APPLICATION) {
5318 } else if (w.mAttrs.type == TYPE_WALLPAPER) {
5319 haveWallpaper = true;
5320 } else if (w.mAttrs.type == TYPE_KEYGUARD) {
5321 haveKeyguard = true;
5326 if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
5327 Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
5328 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
5329 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
5330 + " haveKeyguard=" + haveKeyguard);
5333 // If we are turning on the screen to show the boot message,
5334 // don't do it until the boot message is actually displayed.
5335 if (!mSystemBooted && !haveBootMsg) {
5339 // If we are turning on the screen after the boot is completed
5340 // normally, don't do so until we have the application and
5342 if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
5343 (wallpaperEnabled && !haveWallpaper))) {
5348 mDisplayEnabled = true;
5349 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
5351 StringWriter sw = new StringWriter();
5352 PrintWriter pw = new FastPrintWriter(sw, false, 1024);
5353 this.dump(null, pw, null);
5355 Slog.i(TAG, sw.toString());
5358 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5359 if (surfaceFlinger != null) {
5360 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5361 Parcel data = Parcel.obtain();
5362 data.writeInterfaceToken("android.ui.ISurfaceComposer");
5363 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5367 } catch (RemoteException ex) {
5368 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
5371 // Enable input dispatch.
5372 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5375 mPolicy.enableScreenAfterBoot();
5377 // Make sure the last requested orientation has been applied.
5378 updateRotationUnchecked(false, false);
5381 public void showBootMessage(final CharSequence msg, final boolean always) {
5382 boolean first = false;
5383 synchronized(mWindowMap) {
5385 RuntimeException here = new RuntimeException("here");
5386 here.fillInStackTrace();
5387 Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always
5388 + " mAllowBootMessages=" + mAllowBootMessages
5389 + " mShowingBootMessages=" + mShowingBootMessages
5390 + " mSystemBooted=" + mSystemBooted, here);
5392 if (!mAllowBootMessages) {
5395 if (!mShowingBootMessages) {
5401 if (mSystemBooted) {
5404 mShowingBootMessages = true;
5405 mPolicy.showBootMessage(msg, always);
5408 performEnableScreen();
5412 public void hideBootMessagesLocked() {
5414 RuntimeException here = new RuntimeException("here");
5415 here.fillInStackTrace();
5416 Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
5417 + " mForceDisplayEnabled=" + mForceDisplayEnabled
5418 + " mShowingBootMessages=" + mShowingBootMessages
5419 + " mSystemBooted=" + mSystemBooted, here);
5421 if (mShowingBootMessages) {
5422 mShowingBootMessages = false;
5423 mPolicy.hideBootMessages();
5428 public void setInTouchMode(boolean mode) {
5429 synchronized(mWindowMap) {
5430 mInTouchMode = mode;
5434 // TODO: more accounting of which pid(s) turned it on, keep count,
5435 // only allow disables from pids which have count on, etc.
5437 public void showStrictModeViolation(boolean on) {
5438 if (mHeadless) return;
5439 int pid = Binder.getCallingPid();
5440 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
5443 private void showStrictModeViolation(int arg, int pid) {
5444 final boolean on = arg != 0;
5445 synchronized(mWindowMap) {
5446 // Ignoring requests to enable the red border from clients
5447 // which aren't on screen. (e.g. Broadcast Receivers in
5448 // the background..)
5450 boolean isVisible = false;
5451 final int numDisplays = mDisplayContents.size();
5452 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5453 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5454 final int numWindows = windows.size();
5455 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5456 final WindowState ws = windows.get(winNdx);
5457 if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
5468 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5469 ">>> OPEN TRANSACTION showStrictModeViolation");
5470 SurfaceControl.openTransaction();
5472 // TODO(multi-display): support multiple displays
5473 if (mStrictModeFlash == null) {
5474 mStrictModeFlash = new StrictModeFlash(
5475 getDefaultDisplayContentLocked().getDisplay(), mFxSession);
5477 mStrictModeFlash.setVisibility(on);
5479 SurfaceControl.closeTransaction();
5480 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5481 "<<< CLOSE TRANSACTION showStrictModeViolation");
5487 public void setStrictModeVisualIndicatorPreference(String value) {
5488 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
5492 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
5493 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
5494 * of the target image.
5496 * @param displayId the Display to take a screenshot of.
5497 * @param width the width of the target bitmap
5498 * @param height the height of the target bitmap
5499 * @param force565 if true the returned bitmap will be RGB_565, otherwise it
5500 * will be the same config as the surface
5503 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
5504 int height, boolean force565) {
5505 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5506 "screenshotApplications()")) {
5507 throw new SecurityException("Requires READ_FRAME_BUFFER permission");
5510 Bitmap rawss = null;
5513 final Rect frame = new Rect();
5517 int rot = Surface.ROTATION_0;
5519 boolean screenshotReady;
5521 if (appToken == null) {
5522 screenshotReady = true;
5525 screenshotReady = false;
5526 minLayer = Integer.MAX_VALUE;
5530 WindowState appWin = null;
5533 if (retryCount++ > 0) {
5536 } catch (InterruptedException e) {
5539 synchronized(mWindowMap) {
5540 final DisplayContent displayContent = getDisplayContentLocked(displayId);
5541 if (displayContent == null) {
5544 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5545 dw = displayInfo.logicalWidth;
5546 dh = displayInfo.logicalHeight;
5548 int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION)
5549 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
5550 aboveAppLayer += TYPE_LAYER_MULTIPLIER;
5552 boolean isImeTarget = mInputMethodTarget != null
5553 && mInputMethodTarget.mAppToken != null
5554 && mInputMethodTarget.mAppToken.appToken != null
5555 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
5557 // Figure out the part of the screen that is actually the app.
5558 boolean including = false;
5560 final WindowList windows = displayContent.getWindowList();
5561 final Rect stackBounds = new Rect();
5562 for (int i = windows.size() - 1; i >= 0; i--) {
5563 WindowState ws = windows.get(i);
5564 if (!ws.mHasSurface) {
5567 if (ws.mLayer >= aboveAppLayer) {
5570 // When we will skip windows: when we are not including
5571 // ones behind a window we didn't skip, and we are actually
5572 // taking a screenshot of a specific app.
5573 if (!including && appToken != null) {
5574 // Also, we can possibly skip this window if it is not
5575 // an IME target or the application for the screenshot
5576 // is not the current IME target.
5577 if (!ws.mIsImWindow || !isImeTarget) {
5578 // And finally, this window is of no interest if it
5579 // is not associated with the screenshot app.
5580 if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
5584 stackBounds.set(ws.getStackBounds());
5588 // We keep on including windows until we go past a full-screen
5590 boolean fullscreen = ws.isFullscreen(dw, dh);
5591 including = !ws.mIsImWindow && !fullscreen;
5593 final WindowStateAnimator winAnim = ws.mWinAnimator;
5594 if (maxLayer < winAnim.mSurfaceLayer) {
5595 maxLayer = winAnim.mSurfaceLayer;
5597 if (minLayer > winAnim.mSurfaceLayer) {
5598 minLayer = winAnim.mSurfaceLayer;
5601 // Don't include wallpaper in bounds calculation
5602 if (!ws.mIsWallpaper) {
5603 final Rect wf = ws.mFrame;
5604 final Rect cr = ws.mContentInsets;
5605 int left = wf.left + cr.left;
5606 int top = wf.top + cr.top;
5607 int right = wf.right - cr.right;
5608 int bottom = wf.bottom - cr.bottom;
5609 frame.union(left, top, right, bottom);
5610 frame.intersect(stackBounds);
5613 if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
5614 ws.isDisplayedLw()) {
5615 screenshotReady = true;
5619 // No point in continuing down through windows.
5624 if (appToken != null && appWin == null) {
5625 // Can't find a window to snapshot.
5626 if (DEBUG_SCREENSHOT) Slog.i(TAG,
5627 "Screenshot: Couldn't find a surface matching " + appToken);
5630 if (!screenshotReady) {
5631 // Delay and hope that window gets drawn.
5632 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken
5633 + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState);
5637 // Constrain frame to the screen size.
5638 frame.intersect(0, 0, dw, dh);
5640 if (frame.isEmpty() || maxLayer == 0) {
5641 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
5642 + ": returning null frame=" + frame.toShortString() + " maxLayer="
5647 // The screenshot API does not apply the current screen rotation.
5648 rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
5649 int fw = frame.width();
5650 int fh = frame.height();
5652 // Constrain thumbnail to smaller of screen width or height. Assumes aspect
5653 // of thumbnail is the same as the screen (in landscape) or square.
5654 scale = Math.max(width / (float) fw, height / (float) fh);
5656 float targetWidthScale = width / (float) fw;
5657 float targetHeightScale = height / (float) fh;
5659 scale = targetWidthScale;
5660 // If aspect of thumbnail is the same as the screen (in landscape),
5661 // select the slightly larger value so we fill the entire bitmap
5662 if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) {
5663 scale = targetHeightScale;
5666 scale = targetHeightScale;
5667 // If aspect of thumbnail is the same as the screen (in landscape),
5668 // select the slightly larger value so we fill the entire bitmap
5669 if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) {
5670 scale = targetWidthScale;
5675 // The screen shot will contain the entire screen.
5676 dw = (int)(dw*scale);
5677 dh = (int)(dh*scale);
5678 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
5682 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
5684 if (DEBUG_SCREENSHOT) {
5685 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
5686 + maxLayer + " appToken=" + appToken);
5687 for (int i = 0; i < windows.size(); i++) {
5688 WindowState win = windows.get(i);
5689 Slog.i(TAG, win + ": " + win.mLayer
5690 + " animLayer=" + win.mWinAnimator.mAnimLayer
5691 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
5694 rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer);
5696 } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES);
5697 if (retryCount > MAX_SCREENSHOT_RETRIES) Slog.i(TAG, "Screenshot max retries " +
5698 retryCount + " of " + appToken + " appWin=" + (appWin == null ?
5699 "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState)));
5701 if (rawss == null) {
5702 Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
5703 + ") to layer " + maxLayer);
5707 Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig());
5709 Matrix matrix = new Matrix();
5710 ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
5711 // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left
5712 matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top));
5713 Canvas canvas = new Canvas(bm);
5714 canvas.drawColor(0xFF000000);
5715 canvas.drawBitmap(rawss, matrix, null);
5716 canvas.setBitmap(null);
5718 if (true || DEBUG_SCREENSHOT) {
5719 // TEST IF IT's ALL BLACK
5720 int[] buffer = new int[bm.getWidth() * bm.getHeight()];
5721 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
5722 boolean allBlack = true;
5723 final int firstColor = buffer[0];
5724 for (int i = 0; i < buffer.length; i++) {
5725 if (buffer[i] != firstColor) {
5731 Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" +
5732 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
5733 (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") +
5734 " minLayer=" + minLayer + " maxLayer=" + maxLayer);
5743 * Freeze rotation changes. (Enable "rotation lock".)
5744 * Persists across reboots.
5745 * @param rotation The desired rotation to freeze to, or -1 to use the
5749 public void freezeRotation(int rotation) {
5750 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5751 "freezeRotation()")) {
5752 throw new SecurityException("Requires SET_ORIENTATION permission");
5754 if (rotation < -1 || rotation > Surface.ROTATION_270) {
5755 throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
5756 + "rotation constant.");
5759 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
5761 long origId = Binder.clearCallingIdentity();
5763 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
5764 rotation == -1 ? mRotation : rotation);
5766 Binder.restoreCallingIdentity(origId);
5769 updateRotationUnchecked(false, false);
5773 * Thaw rotation changes. (Disable "rotation lock".)
5774 * Persists across reboots.
5777 public void thawRotation() {
5778 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5779 "thawRotation()")) {
5780 throw new SecurityException("Requires SET_ORIENTATION permission");
5783 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
5785 long origId = Binder.clearCallingIdentity();
5787 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
5788 777); // rot not used
5790 Binder.restoreCallingIdentity(origId);
5793 updateRotationUnchecked(false, false);
5797 * Recalculate the current rotation.
5799 * Called by the window manager policy whenever the state of the system changes
5800 * such that the current rotation might need to be updated, such as when the
5801 * device is docked or rotated into a new posture.
5804 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
5805 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
5809 * Temporarily pauses rotation changes until resumed.
5811 * This can be used to prevent rotation changes from occurring while the user is
5812 * performing certain operations, such as drag and drop.
5814 * This call nests and must be matched by an equal number of calls to
5815 * {@link #resumeRotationLocked}.
5817 void pauseRotationLocked() {
5818 mDeferredRotationPauseCount += 1;
5822 * Resumes normal rotation changes after being paused.
5824 void resumeRotationLocked() {
5825 if (mDeferredRotationPauseCount > 0) {
5826 mDeferredRotationPauseCount -= 1;
5827 if (mDeferredRotationPauseCount == 0) {
5828 boolean changed = updateRotationUncheckedLocked(false);
5830 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
5836 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
5837 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
5838 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
5840 long origId = Binder.clearCallingIdentity();
5842 synchronized(mWindowMap) {
5843 changed = updateRotationUncheckedLocked(false);
5844 if (!changed || forceRelayout) {
5845 getDefaultDisplayContentLocked().layoutNeeded = true;
5846 performLayoutAndPlaceSurfacesLocked();
5850 if (changed || alwaysSendConfiguration) {
5851 sendNewConfiguration();
5854 Binder.restoreCallingIdentity(origId);
5857 // TODO(multidisplay): Rotate any display?
5859 * Updates the current rotation.
5861 * Returns true if the rotation has been changed. In this case YOU
5862 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
5864 public boolean updateRotationUncheckedLocked(boolean inTransaction) {
5865 if (mDeferredRotationPauseCount > 0) {
5866 // Rotation updates have been paused temporarily. Defer the update until
5867 // updates have been resumed.
5868 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");
5872 ScreenRotationAnimation screenRotationAnimation =
5873 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
5874 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
5875 // Rotation updates cannot be performed while the previous rotation change
5876 // animation is still in progress. Skip this update. We will try updating
5877 // again after the animation is finished and the display is unfrozen.
5878 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");
5882 if (!mDisplayEnabled) {
5883 // No point choosing a rotation if the display is not enabled.
5884 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");
5888 // TODO: Implement forced rotation changes.
5889 // Set mAltOrientation to indicate that the application is receiving
5890 // an orientation that has different metrics than it expected.
5891 // eg. Portrait instead of Landscape.
5893 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
5894 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
5895 mForcedAppOrientation, rotation);
5897 if (DEBUG_ORIENTATION) {
5898 Slog.v(TAG, "Application requested orientation "
5899 + mForcedAppOrientation + ", got rotation " + rotation
5900 + " which has " + (altOrientation ? "incompatible" : "compatible")
5904 if (mRotation == rotation && mAltOrientation == altOrientation) {
5909 if (DEBUG_ORIENTATION) {
5911 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
5912 + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
5913 + ", forceApp=" + mForcedAppOrientation);
5916 mRotation = rotation;
5917 mAltOrientation = altOrientation;
5918 mPolicy.setRotationLw(mRotation);
5920 mWindowsFreezingScreen = true;
5921 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
5922 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
5923 mWaitingForConfig = true;
5924 final DisplayContent displayContent = getDefaultDisplayContentLocked();
5925 displayContent.layoutNeeded = true;
5926 final int[] anim = new int[2];
5927 if (displayContent.isDimming()) {
5928 anim[0] = anim[1] = 0;
5930 mPolicy.selectRotationAnimationLw(anim);
5932 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
5933 // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
5934 screenRotationAnimation =
5935 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
5937 // We need to update our screen size information to match the new
5938 // rotation. Note that this is redundant with the later call to
5939 // sendNewConfiguration() that must be called after this function
5940 // returns... however we need to do the screen size part of that
5941 // before then so we have the correct size to use when initializing
5942 // the rotation animation for the new rotation.
5943 computeScreenConfigurationLocked(null);
5945 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5946 if (!inTransaction) {
5947 if (SHOW_TRANSACTIONS) {
5948 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
5950 SurfaceControl.openTransaction();
5953 // NOTE: We disable the rotation in the emulator because
5954 // it doesn't support hardware OpenGL emulation yet.
5955 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
5956 && screenRotationAnimation.hasScreenshot()) {
5957 if (screenRotationAnimation.setRotationInTransaction(
5958 rotation, mFxSession,
5959 MAX_ANIMATION_DURATION, mTransitionAnimationScale,
5960 displayInfo.logicalWidth, displayInfo.logicalHeight)) {
5961 scheduleAnimationLocked();
5965 mDisplayManagerService.performTraversalInTransactionFromWindowManager();
5967 if (!inTransaction) {
5968 SurfaceControl.closeTransaction();
5969 if (SHOW_LIGHT_TRANSACTIONS) {
5970 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
5975 final WindowList windows = displayContent.getWindowList();
5976 for (int i = windows.size() - 1; i >= 0; i--) {
5977 WindowState w = windows.get(i);
5978 if (w.mHasSurface) {
5979 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
5980 w.mOrientationChanging = true;
5981 mInnerFields.mOrientationChangeComplete = false;
5983 w.mLastFreezeDuration = 0;
5986 for (int i=mRotationWatchers.size()-1; i>=0; i--) {
5988 mRotationWatchers.get(i).onRotationChanged(rotation);
5989 } catch (RemoteException e) {
5993 //TODO (multidisplay): Magnification is supported only for the default display.
5994 if (mDisplayMagnifier != null
5995 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
5996 mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation);
6003 public int getRotation() {
6008 public boolean isRotationFrozen() {
6009 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6013 public int watchRotation(IRotationWatcher watcher) {
6014 final IBinder watcherBinder = watcher.asBinder();
6015 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6017 public void binderDied() {
6018 synchronized (mWindowMap) {
6019 for (int i=0; i<mRotationWatchers.size(); i++) {
6020 if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
6021 IRotationWatcher removed = mRotationWatchers.remove(i);
6022 if (removed != null) {
6023 removed.asBinder().unlinkToDeath(this, 0);
6032 synchronized (mWindowMap) {
6034 watcher.asBinder().linkToDeath(dr, 0);
6035 mRotationWatchers.add(watcher);
6036 } catch (RemoteException e) {
6037 // Client died, no cleanup needed.
6045 public void removeRotationWatcher(IRotationWatcher watcher) {
6046 final IBinder watcherBinder = watcher.asBinder();
6047 synchronized (mWindowMap) {
6048 for (int i=0; i<mRotationWatchers.size(); i++) {
6049 if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
6050 mRotationWatchers.remove(i);
6058 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6059 * theme attribute) on devices that feature a physical options menu key attempt to position
6060 * their menu panel window along the edge of the screen nearest the physical menu key.
6061 * This lowers the travel distance between invoking the menu panel and selecting
6064 * This method helps control where that menu is placed. Its current implementation makes
6065 * assumptions about the menu key and its relationship to the screen based on whether
6066 * the device's natural orientation is portrait (width < height) or landscape.
6068 * The menu key is assumed to be located along the bottom edge of natural-portrait
6069 * devices and along the right edge of natural-landscape devices. If these assumptions
6070 * do not hold for the target device, this method should be changed to reflect that.
6072 * @return A {@link Gravity} value for placing the options menu window
6075 public int getPreferredOptionsPanelGravity() {
6076 synchronized (mWindowMap) {
6077 final int rotation = getRotation();
6079 // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6080 final DisplayContent displayContent = getDefaultDisplayContentLocked();
6081 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6082 // On devices with a natural orientation of portrait
6085 case Surface.ROTATION_0:
6086 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6087 case Surface.ROTATION_90:
6088 return Gravity.RIGHT | Gravity.BOTTOM;
6089 case Surface.ROTATION_180:
6090 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6091 case Surface.ROTATION_270:
6092 return Gravity.START | Gravity.BOTTOM;
6096 // On devices with a natural orientation of landscape
6099 case Surface.ROTATION_0:
6100 return Gravity.RIGHT | Gravity.BOTTOM;
6101 case Surface.ROTATION_90:
6102 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6103 case Surface.ROTATION_180:
6104 return Gravity.START | Gravity.BOTTOM;
6105 case Surface.ROTATION_270:
6106 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6112 * Starts the view server on the specified port.
6114 * @param port The port to listener to.
6116 * @return True if the server was successfully started, false otherwise.
6118 * @see com.android.server.wm.ViewServer
6119 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
6122 public boolean startViewServer(int port) {
6123 if (isSystemSecure()) {
6127 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
6135 if (mViewServer != null) {
6136 if (!mViewServer.isRunning()) {
6138 return mViewServer.start();
6139 } catch (IOException e) {
6140 Slog.w(TAG, "View server did not start");
6147 mViewServer = new ViewServer(this, port);
6148 return mViewServer.start();
6149 } catch (IOException e) {
6150 Slog.w(TAG, "View server did not start");
6155 private boolean isSystemSecure() {
6156 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
6157 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6161 * Stops the view server if it exists.
6163 * @return True if the server stopped, false if it wasn't started or
6164 * couldn't be stopped.
6166 * @see com.android.server.wm.ViewServer
6169 public boolean stopViewServer() {
6170 if (isSystemSecure()) {
6174 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
6178 if (mViewServer != null) {
6179 return mViewServer.stop();
6185 * Indicates whether the view server is running.
6187 * @return True if the server is running, false otherwise.
6189 * @see com.android.server.wm.ViewServer
6192 public boolean isViewServerRunning() {
6193 if (isSystemSecure()) {
6197 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
6201 return mViewServer != null && mViewServer.isRunning();
6205 * Lists all availble windows in the system. The listing is written in the
6206 * specified Socket's output stream with the following syntax:
6207 * windowHashCodeInHexadecimal windowName
6208 * Each line of the ouput represents a different window.
6210 * @param client The remote client to send the listing to.
6211 * @return False if an error occured, true otherwise.
6213 boolean viewServerListWindows(Socket client) {
6214 if (isSystemSecure()) {
6218 boolean result = true;
6220 WindowList windows = new WindowList();
6221 synchronized (mWindowMap) {
6222 //noinspection unchecked
6223 final int numDisplays = mDisplayContents.size();
6224 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6225 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
6226 windows.addAll(displayContent.getWindowList());
6230 BufferedWriter out = null;
6232 // Any uncaught exception will crash the system process
6234 OutputStream clientStream = client.getOutputStream();
6235 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6237 final int count = windows.size();
6238 for (int i = 0; i < count; i++) {
6239 final WindowState w = windows.get(i);
6240 out.write(Integer.toHexString(System.identityHashCode(w)));
6242 out.append(w.mAttrs.getTitle());
6246 out.write("DONE.\n");
6248 } catch (Exception e) {
6254 } catch (IOException e) {
6263 // TODO(multidisplay): Extend to multiple displays.
6265 * Returns the focused window in the following format:
6266 * windowHashCodeInHexadecimal windowName
6268 * @param client The remote client to send the listing to.
6269 * @return False if an error occurred, true otherwise.
6271 boolean viewServerGetFocusedWindow(Socket client) {
6272 if (isSystemSecure()) {
6276 boolean result = true;
6278 WindowState focusedWindow = getFocusedWindow();
6280 BufferedWriter out = null;
6282 // Any uncaught exception will crash the system process
6284 OutputStream clientStream = client.getOutputStream();
6285 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6287 if(focusedWindow != null) {
6288 out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
6290 out.append(focusedWindow.mAttrs.getTitle());
6294 } catch (Exception e) {
6300 } catch (IOException e) {
6310 * Sends a command to a target window. The result of the command, if any, will be
6311 * written in the output stream of the specified socket.
6313 * The parameters must follow this syntax:
6314 * windowHashcode extra
6316 * Where XX is the length in characeters of the windowTitle.
6318 * The first parameter is the target window. The window with the specified hashcode
6319 * will be the target. If no target can be found, nothing happens. The extra parameters
6320 * will be delivered to the target window and as parameters to the command itself.
6322 * @param client The remote client to sent the result, if any, to.
6323 * @param command The command to execute.
6324 * @param parameters The command parameters.
6326 * @return True if the command was successfully delivered, false otherwise. This does
6327 * not indicate whether the command itself was successful.
6329 boolean viewServerWindowCommand(Socket client, String command, String parameters) {
6330 if (isSystemSecure()) {
6334 boolean success = true;
6336 Parcel reply = null;
6338 BufferedWriter out = null;
6340 // Any uncaught exception will crash the system process
6342 // Find the hashcode of the window
6343 int index = parameters.indexOf(' ');
6345 index = parameters.length();
6347 final String code = parameters.substring(0, index);
6348 int hashCode = (int) Long.parseLong(code, 16);
6350 // Extract the command's parameter after the window description
6351 if (index < parameters.length()) {
6352 parameters = parameters.substring(index + 1);
6357 final WindowState window = findWindow(hashCode);
6358 if (window == null) {
6362 data = Parcel.obtain();
6363 data.writeInterfaceToken("android.view.IWindow");
6364 data.writeString(command);
6365 data.writeString(parameters);
6367 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
6369 reply = Parcel.obtain();
6371 final IBinder binder = window.mClient.asBinder();
6372 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
6373 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
6375 reply.readException();
6377 if (!client.isOutputShutdown()) {
6378 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
6379 out.write("DONE\n");
6383 } catch (Exception e) {
6384 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
6390 if (reply != null) {
6396 } catch (IOException e) {
6405 public void addWindowChangeListener(WindowChangeListener listener) {
6406 synchronized(mWindowMap) {
6407 mWindowChangeListeners.add(listener);
6411 public void removeWindowChangeListener(WindowChangeListener listener) {
6412 synchronized(mWindowMap) {
6413 mWindowChangeListeners.remove(listener);
6417 private void notifyWindowsChanged() {
6418 WindowChangeListener[] windowChangeListeners;
6419 synchronized(mWindowMap) {
6420 if(mWindowChangeListeners.isEmpty()) {
6423 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6424 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6426 int N = windowChangeListeners.length;
6427 for(int i = 0; i < N; i++) {
6428 windowChangeListeners[i].windowsChanged();
6432 private void notifyFocusChanged() {
6433 WindowChangeListener[] windowChangeListeners;
6434 synchronized(mWindowMap) {
6435 if(mWindowChangeListeners.isEmpty()) {
6438 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6439 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6441 int N = windowChangeListeners.length;
6442 for(int i = 0; i < N; i++) {
6443 windowChangeListeners[i].focusChanged();
6447 private WindowState findWindow(int hashCode) {
6448 if (hashCode == -1) {
6449 // TODO(multidisplay): Extend to multiple displays.
6450 return getFocusedWindow();
6453 synchronized (mWindowMap) {
6454 final int numDisplays = mDisplayContents.size();
6455 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6456 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
6457 final int numWindows = windows.size();
6458 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
6459 final WindowState w = windows.get(winNdx);
6460 if (System.identityHashCode(w) == hashCode) {
6471 * Instruct the Activity Manager to fetch the current configuration and broadcast
6472 * that to config-changed listeners if appropriate.
6474 void sendNewConfiguration() {
6476 mActivityManager.updateConfiguration(null);
6477 } catch (RemoteException e) {
6481 public Configuration computeNewConfiguration() {
6482 synchronized (mWindowMap) {
6483 Configuration config = computeNewConfigurationLocked();
6484 if (config == null && mWaitingForConfig) {
6485 // Nothing changed but we are waiting for something... stop that!
6486 mWaitingForConfig = false;
6487 mLastFinishedFreezeSource = "new-config";
6488 performLayoutAndPlaceSurfacesLocked();
6494 Configuration computeNewConfigurationLocked() {
6495 Configuration config = new Configuration();
6496 config.fontScale = 0;
6497 if (!computeScreenConfigurationLocked(config)) {
6503 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
6504 // TODO: Multidisplay: for now only use with default display.
6505 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
6506 if (width < displayInfo.smallestNominalAppWidth) {
6507 displayInfo.smallestNominalAppWidth = width;
6509 if (width > displayInfo.largestNominalAppWidth) {
6510 displayInfo.largestNominalAppWidth = width;
6512 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
6513 if (height < displayInfo.smallestNominalAppHeight) {
6514 displayInfo.smallestNominalAppHeight = height;
6516 if (height > displayInfo.largestNominalAppHeight) {
6517 displayInfo.largestNominalAppHeight = height;
6521 private int reduceConfigLayout(int curLayout, int rotation, float density,
6523 // TODO: Multidisplay: for now only use with default display.
6524 // Get the app screen size at this rotation.
6525 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6526 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6528 // Compute the screen layout size class for this rotation.
6531 if (longSize < shortSize) {
6533 longSize = shortSize;
6536 longSize = (int)(longSize/density);
6537 shortSize = (int)(shortSize/density);
6538 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
6541 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
6542 int dw, int dh, float density, Configuration outConfig) {
6543 // TODO: Multidisplay: for now only use with default display.
6545 // We need to determine the smallest width that will occur under normal
6546 // operation. To this, start with the base screen size and compute the
6547 // width under the different possible rotations. We need to un-rotate
6548 // the current screen dimensions before doing this.
6549 int unrotDw, unrotDh;
6557 displayInfo.smallestNominalAppWidth = 1<<30;
6558 displayInfo.smallestNominalAppHeight = 1<<30;
6559 displayInfo.largestNominalAppWidth = 0;
6560 displayInfo.largestNominalAppHeight = 0;
6561 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
6562 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
6563 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
6564 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
6565 int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
6566 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
6567 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
6568 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
6569 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
6570 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
6571 outConfig.screenLayout = sl;
6574 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
6576 // TODO: Multidisplay: for now only use with default display.
6577 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6578 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6579 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
6580 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
6581 if (curSize == 0 || size < curSize) {
6587 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) {
6588 // TODO: Multidisplay: for now only use with default display.
6589 mTmpDisplayMetrics.setTo(dm);
6590 final DisplayMetrics tmpDm = mTmpDisplayMetrics;
6591 final int unrotDw, unrotDh;
6599 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
6600 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
6601 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
6602 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
6606 boolean computeScreenConfigurationLocked(Configuration config) {
6607 if (!mDisplayReady) {
6611 // TODO(multidisplay): For now, apply Configuration to main screen only.
6612 final DisplayContent displayContent = getDefaultDisplayContentLocked();
6614 // Use the effective "visual" dimensions based on current rotation
6615 final boolean rotated = (mRotation == Surface.ROTATION_90
6616 || mRotation == Surface.ROTATION_270);
6617 final int realdw = rotated ?
6618 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
6619 final int realdh = rotated ?
6620 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
6624 if (mAltOrientation) {
6625 if (realdw > realdh) {
6626 // Turn landscape into portrait.
6627 int maxw = (int)(realdh/1.3f);
6628 if (maxw < realdw) {
6632 // Turn portrait into landscape.
6633 int maxh = (int)(realdw/1.3f);
6634 if (maxh < realdh) {
6640 if (config != null) {
6641 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
6642 Configuration.ORIENTATION_LANDSCAPE;
6645 // Update application display metrics.
6646 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
6647 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
6648 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6649 synchronized(displayContent.mDisplaySizeLock) {
6650 displayInfo.rotation = mRotation;
6651 displayInfo.logicalWidth = dw;
6652 displayInfo.logicalHeight = dh;
6653 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
6654 displayInfo.appWidth = appWidth;
6655 displayInfo.appHeight = appHeight;
6656 displayInfo.getLogicalMetrics(mRealDisplayMetrics,
6657 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
6658 displayInfo.getAppMetrics(mDisplayMetrics);
6659 mDisplayManagerService.setDisplayInfoOverrideFromWindowManager(
6660 displayContent.getDisplayId(), displayInfo);
6663 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
6666 final DisplayMetrics dm = mDisplayMetrics;
6667 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
6668 mCompatDisplayMetrics);
6670 if (config != null) {
6671 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
6673 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
6675 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
6677 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
6678 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
6679 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
6680 config.densityDpi = displayContent.mBaseDisplayDensity;
6682 // Update the configuration based on available input devices, lid switch,
6683 // and platform configuration.
6684 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6685 config.keyboard = Configuration.KEYBOARD_NOKEYS;
6686 config.navigation = Configuration.NAVIGATION_NONAV;
6688 int keyboardPresence = 0;
6689 int navigationPresence = 0;
6690 final InputDevice[] devices = mInputManager.getInputDevices();
6691 final int len = devices.length;
6692 for (int i = 0; i < len; i++) {
6693 InputDevice device = devices[i];
6694 if (!device.isVirtual()) {
6695 final int sources = device.getSources();
6696 final int presenceFlag = device.isExternal() ?
6697 WindowManagerPolicy.PRESENCE_EXTERNAL :
6698 WindowManagerPolicy.PRESENCE_INTERNAL;
6700 if (mIsTouchDevice) {
6701 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
6702 InputDevice.SOURCE_TOUCHSCREEN) {
6703 config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
6706 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6709 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
6710 config.navigation = Configuration.NAVIGATION_TRACKBALL;
6711 navigationPresence |= presenceFlag;
6712 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
6713 && config.navigation == Configuration.NAVIGATION_NONAV) {
6714 config.navigation = Configuration.NAVIGATION_DPAD;
6715 navigationPresence |= presenceFlag;
6718 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
6719 config.keyboard = Configuration.KEYBOARD_QWERTY;
6720 keyboardPresence |= presenceFlag;
6725 // Determine whether a hard keyboard is available and enabled.
6726 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
6727 if (hardKeyboardAvailable != mHardKeyboardAvailable) {
6728 mHardKeyboardAvailable = hardKeyboardAvailable;
6729 mHardKeyboardEnabled = hardKeyboardAvailable;
6730 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6731 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6733 if (!mHardKeyboardEnabled) {
6734 config.keyboard = Configuration.KEYBOARD_NOKEYS;
6737 // Let the policy update hidden states.
6738 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
6739 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
6740 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
6741 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
6747 public boolean isHardKeyboardAvailable() {
6748 synchronized (mWindowMap) {
6749 return mHardKeyboardAvailable;
6753 public boolean isHardKeyboardEnabled() {
6754 synchronized (mWindowMap) {
6755 return mHardKeyboardEnabled;
6759 public void setHardKeyboardEnabled(boolean enabled) {
6760 synchronized (mWindowMap) {
6761 if (mHardKeyboardEnabled != enabled) {
6762 mHardKeyboardEnabled = enabled;
6763 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6768 public void setOnHardKeyboardStatusChangeListener(
6769 OnHardKeyboardStatusChangeListener listener) {
6770 synchronized (mWindowMap) {
6771 mHardKeyboardStatusChangeListener = listener;
6775 void notifyHardKeyboardStatusChange() {
6776 final boolean available, enabled;
6777 final OnHardKeyboardStatusChangeListener listener;
6778 synchronized (mWindowMap) {
6779 listener = mHardKeyboardStatusChangeListener;
6780 available = mHardKeyboardAvailable;
6781 enabled = mHardKeyboardEnabled;
6783 if (listener != null) {
6784 listener.onHardKeyboardStatusChange(available, enabled);
6788 // -------------------------------------------------------------
6790 // -------------------------------------------------------------
6792 IBinder prepareDragSurface(IWindow window, SurfaceSession session,
6793 int flags, int width, int height, Surface outSurface) {
6795 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height
6796 + " flags=" + Integer.toHexString(flags) + " win=" + window
6797 + " asbinder=" + window.asBinder());
6800 final int callerPid = Binder.getCallingPid();
6801 final long origId = Binder.clearCallingIdentity();
6802 IBinder token = null;
6805 synchronized (mWindowMap) {
6807 if (mDragState == null) {
6808 // TODO(multi-display): support other displays
6809 final DisplayContent displayContent = getDefaultDisplayContentLocked();
6810 final Display display = displayContent.getDisplay();
6811 SurfaceControl surface = new SurfaceControl(session, "drag surface",
6812 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
6813 surface.setLayerStack(display.getLayerStack());
6814 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG "
6815 + surface + ": CREATE");
6816 outSurface.copyFrom(surface);
6817 final IBinder winBinder = window.asBinder();
6818 token = new Binder();
6819 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
6820 token = mDragState.mToken = new Binder();
6822 // 5 second timeout for this window to actually begin the drag
6823 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
6824 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
6825 mH.sendMessageDelayed(msg, 5000);
6827 Slog.w(TAG, "Drag already in progress");
6829 } catch (OutOfResourcesException e) {
6830 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
6831 if (mDragState != null) {
6838 Binder.restoreCallingIdentity(origId);
6844 // -------------------------------------------------------------
6845 // Input Events and Focus Management
6846 // -------------------------------------------------------------
6848 final InputMonitor mInputMonitor = new InputMonitor(this);
6849 private boolean mEventDispatchingEnabled;
6852 public void pauseKeyDispatching(IBinder _token) {
6853 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6854 "pauseKeyDispatching()")) {
6855 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6858 synchronized (mWindowMap) {
6859 WindowToken token = mTokenMap.get(_token);
6860 if (token != null) {
6861 mInputMonitor.pauseDispatchingLw(token);
6867 public void resumeKeyDispatching(IBinder _token) {
6868 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6869 "resumeKeyDispatching()")) {
6870 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6873 synchronized (mWindowMap) {
6874 WindowToken token = mTokenMap.get(_token);
6875 if (token != null) {
6876 mInputMonitor.resumeDispatchingLw(token);
6882 public void setEventDispatching(boolean enabled) {
6883 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6884 "setEventDispatching()")) {
6885 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6888 synchronized (mWindowMap) {
6889 mEventDispatchingEnabled = enabled;
6890 if (mDisplayEnabled) {
6891 mInputMonitor.setEventDispatchingLw(enabled);
6893 sendScreenStatusToClientsLocked();
6898 public IBinder getFocusedWindowToken() {
6899 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
6900 "getFocusedWindowToken()")) {
6901 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
6903 synchronized (mWindowMap) {
6904 WindowState windowState = getFocusedWindowLocked();
6905 if (windowState != null) {
6906 return windowState.mClient.asBinder();
6912 private WindowState getFocusedWindow() {
6913 synchronized (mWindowMap) {
6914 return getFocusedWindowLocked();
6918 private WindowState getFocusedWindowLocked() {
6919 return mCurrentFocus;
6922 public boolean detectSafeMode() {
6923 if (!mInputMonitor.waitForInputDevicesReady(
6924 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
6925 Slog.w(TAG, "Devices still not ready after waiting "
6926 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
6927 + " milliseconds before attempting to detect safe mode.");
6930 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
6931 KeyEvent.KEYCODE_MENU);
6932 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
6933 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
6934 KeyEvent.KEYCODE_DPAD_CENTER);
6935 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
6936 InputManagerService.BTN_MOUSE);
6937 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
6938 KeyEvent.KEYCODE_VOLUME_DOWN);
6939 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
6940 || volumeDownState > 0;
6942 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
6944 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
6946 } catch (IllegalArgumentException e) {
6949 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
6950 + " dpad=" + dpadState + " trackball=" + trackballState + ")");
6952 Log.i(TAG, "SAFE MODE not enabled");
6954 mPolicy.setSafeMode(mSafeMode);
6958 public void displayReady() {
6959 displayReady(Display.DEFAULT_DISPLAY);
6961 synchronized(mWindowMap) {
6962 final DisplayContent displayContent = getDefaultDisplayContentLocked();
6963 readForcedDisplaySizeAndDensityLocked(displayContent);
6964 mDisplayReady = true;
6968 mActivityManager.updateConfiguration(null);
6969 } catch (RemoteException e) {
6972 synchronized(mWindowMap) {
6973 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
6974 PackageManager.FEATURE_TOUCHSCREEN);
6975 configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
6979 mActivityManager.updateConfiguration(null);
6980 } catch (RemoteException e) {
6984 private void displayReady(int displayId) {
6985 synchronized(mWindowMap) {
6986 final DisplayContent displayContent = getDisplayContentLocked(displayId);
6987 if (displayContent != null) {
6988 mAnimator.addDisplayLocked(displayId);
6989 synchronized(displayContent.mDisplaySizeLock) {
6990 // Bootstrap the default logical display from the display manager.
6991 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6992 DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId);
6993 if (newDisplayInfo != null) {
6994 displayInfo.copyFrom(newDisplayInfo);
6996 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
6997 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
6998 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
6999 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
7000 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
7001 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
7002 displayContent.mBaseDisplayRect.set(0, 0,
7003 displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight);
7009 public void systemReady() {
7010 mPolicy.systemReady();
7013 // TODO(multidisplay): Call isScreenOn for each display.
7014 private void sendScreenStatusToClientsLocked() {
7015 final boolean on = mPowerManager.isScreenOn();
7016 final int numDisplays = mDisplayContents.size();
7017 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
7018 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
7019 final int numWindows = windows.size();
7020 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
7022 windows.get(winNdx).mClient.dispatchScreenState(on);
7023 } catch (RemoteException e) {
7030 // -------------------------------------------------------------
7032 // -------------------------------------------------------------
7034 final class H extends Handler {
7035 public static final int REPORT_FOCUS_CHANGE = 2;
7036 public static final int REPORT_LOSING_FOCUS = 3;
7037 public static final int DO_TRAVERSAL = 4;
7038 public static final int ADD_STARTING = 5;
7039 public static final int REMOVE_STARTING = 6;
7040 public static final int FINISHED_STARTING = 7;
7041 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
7042 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
7043 public static final int WINDOW_FREEZE_TIMEOUT = 11;
7045 public static final int APP_TRANSITION_TIMEOUT = 13;
7046 public static final int PERSIST_ANIMATION_SCALE = 14;
7047 public static final int FORCE_GC = 15;
7048 public static final int ENABLE_SCREEN = 16;
7049 public static final int APP_FREEZE_TIMEOUT = 17;
7050 public static final int SEND_NEW_CONFIGURATION = 18;
7051 public static final int REPORT_WINDOWS_CHANGE = 19;
7052 public static final int DRAG_START_TIMEOUT = 20;
7053 public static final int DRAG_END_TIMEOUT = 21;
7054 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
7055 public static final int BOOT_TIMEOUT = 23;
7056 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
7057 public static final int SHOW_STRICT_MODE_VIOLATION = 25;
7058 public static final int DO_ANIMATION_CALLBACK = 26;
7060 public static final int DO_DISPLAY_ADDED = 27;
7061 public static final int DO_DISPLAY_REMOVED = 28;
7062 public static final int DO_DISPLAY_CHANGED = 29;
7064 public static final int CLIENT_FREEZE_TIMEOUT = 30;
7065 public static final int TAP_OUTSIDE_STACK = 31;
7066 public static final int NOTIFY_ACTIVITY_DRAWN = 32;
7068 public static final int REMOVE_STARTING_TIMEOUT = 33;
7071 public void handleMessage(Message msg) {
7072 if (DEBUG_WINDOW_TRACE) {
7073 Slog.v(TAG, "handleMessage: entry what=" + msg.what);
7076 case REPORT_FOCUS_CHANGE: {
7077 WindowState lastFocus;
7078 WindowState newFocus;
7080 synchronized(mWindowMap) {
7081 lastFocus = mLastFocus;
7082 newFocus = mCurrentFocus;
7083 if (lastFocus == newFocus) {
7084 // Focus is not changing, so nothing to do.
7087 mLastFocus = newFocus;
7088 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus +
7090 if (newFocus != null && lastFocus != null
7091 && !newFocus.isDisplayedLw()) {
7092 //Slog.i(TAG, "Delaying loss of focus...");
7093 mLosingFocus.add(lastFocus);
7098 //System.out.println("Changing focus from " + lastFocus
7099 // + " to " + newFocus);
7100 if (newFocus != null) {
7101 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus);
7102 newFocus.reportFocusChangedSerialized(true, mInTouchMode);
7103 notifyFocusChanged();
7106 if (lastFocus != null) {
7107 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus);
7108 lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
7112 case REPORT_LOSING_FOCUS: {
7113 ArrayList<WindowState> losers;
7115 synchronized(mWindowMap) {
7116 losers = mLosingFocus;
7117 mLosingFocus = new ArrayList<WindowState>();
7120 final int N = losers.size();
7121 for (int i=0; i<N; i++) {
7122 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " +
7124 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
7128 case DO_TRAVERSAL: {
7129 synchronized(mWindowMap) {
7130 mTraversalScheduled = false;
7131 performLayoutAndPlaceSurfacesLocked();
7135 case ADD_STARTING: {
7136 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7137 final StartingData sd = wtoken.startingData;
7140 // Animation has been canceled... do nothing.
7144 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
7145 + wtoken + ": pkg=" + sd.pkg);
7149 view = mPolicy.addStartingWindow(
7150 wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
7151 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags);
7152 } catch (Exception e) {
7153 Slog.w(TAG, "Exception when adding starting window", e);
7157 boolean abort = false;
7159 synchronized(mWindowMap) {
7160 if (wtoken.removed || wtoken.startingData == null) {
7161 // If the window was successfully added, then
7162 // we need to remove it.
7163 if (wtoken.startingWindow != null) {
7164 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7165 "Aborted starting " + wtoken
7166 + ": removed=" + wtoken.removed
7167 + " startingData=" + wtoken.startingData);
7168 removeStartingWindowTimeout(wtoken);
7169 wtoken.startingWindow = null;
7170 wtoken.startingData = null;
7174 wtoken.startingView = view;
7176 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
7177 "Added starting " + wtoken
7178 + ": startingWindow="
7179 + wtoken.startingWindow + " startingView="
7180 + wtoken.startingView);
7185 mPolicy.removeStartingWindow(wtoken.token, view);
7186 } catch (Exception e) {
7187 Slog.w(TAG, "Exception when removing starting window", e);
7193 case REMOVE_STARTING_TIMEOUT: {
7194 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7195 Slog.e(TAG, "Starting window " + wtoken + " timed out");
7198 case REMOVE_STARTING: {
7199 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7200 IBinder token = null;
7202 synchronized (mWindowMap) {
7203 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
7204 + wtoken + ": startingWindow="
7205 + wtoken.startingWindow + " startingView="
7206 + wtoken.startingView);
7207 if (wtoken.startingWindow != null) {
7208 view = wtoken.startingView;
7209 token = wtoken.token;
7210 wtoken.startingData = null;
7211 wtoken.startingView = null;
7212 wtoken.startingWindow = null;
7213 wtoken.startingDisplayed = false;
7218 mPolicy.removeStartingWindow(token, view);
7219 } catch (Exception e) {
7220 Slog.w(TAG, "Exception when removing starting window", e);
7225 case FINISHED_STARTING: {
7226 IBinder token = null;
7229 synchronized (mWindowMap) {
7230 final int N = mFinishedStarting.size();
7234 AppWindowToken wtoken = mFinishedStarting.remove(N-1);
7236 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7237 "Finished starting " + wtoken
7238 + ": startingWindow=" + wtoken.startingWindow
7239 + " startingView=" + wtoken.startingView);
7241 if (wtoken.startingWindow == null) {
7245 view = wtoken.startingView;
7246 token = wtoken.token;
7247 wtoken.startingData = null;
7248 wtoken.startingView = null;
7249 wtoken.startingWindow = null;
7250 wtoken.startingDisplayed = false;
7254 mPolicy.removeStartingWindow(token, view);
7255 } catch (Exception e) {
7256 Slog.w(TAG, "Exception when removing starting window", e);
7261 case REPORT_APPLICATION_TOKEN_DRAWN: {
7262 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7265 if (DEBUG_VISIBILITY) Slog.v(
7266 TAG, "Reporting drawn in " + wtoken);
7267 wtoken.appToken.windowsDrawn();
7268 } catch (RemoteException ex) {
7272 case REPORT_APPLICATION_TOKEN_WINDOWS: {
7273 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7275 boolean nowVisible = msg.arg1 != 0;
7276 boolean nowGone = msg.arg2 != 0;
7279 if (DEBUG_VISIBILITY) Slog.v(
7280 TAG, "Reporting visible in " + wtoken
7281 + " visible=" + nowVisible
7282 + " gone=" + nowGone);
7284 wtoken.appToken.windowsVisible();
7286 wtoken.appToken.windowsGone();
7288 } catch (RemoteException ex) {
7292 case WINDOW_FREEZE_TIMEOUT: {
7293 // TODO(multidisplay): Can non-default displays rotate?
7294 synchronized (mWindowMap) {
7295 Slog.w(TAG, "Window freeze timeout expired.");
7296 final WindowList windows = getDefaultWindowListLocked();
7297 int i = windows.size();
7300 WindowState w = windows.get(i);
7301 if (w.mOrientationChanging) {
7302 w.mOrientationChanging = false;
7303 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
7304 - mDisplayFreezeTime);
7305 Slog.w(TAG, "Force clearing orientation change: " + w);
7308 performLayoutAndPlaceSurfacesLocked();
7313 case APP_TRANSITION_TIMEOUT: {
7314 synchronized (mWindowMap) {
7315 if (mAppTransition.isTransitionSet()) {
7316 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
7317 mAppTransition.setTimeout();
7318 performLayoutAndPlaceSurfacesLocked();
7324 case PERSIST_ANIMATION_SCALE: {
7325 Settings.Global.putFloat(mContext.getContentResolver(),
7326 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
7327 Settings.Global.putFloat(mContext.getContentResolver(),
7328 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
7329 Settings.Global.putFloat(mContext.getContentResolver(),
7330 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale);
7335 synchronized (mWindowMap) {
7336 // Since we're holding both mWindowMap and mAnimator we don't need to
7337 // hold mAnimator.mLayoutToAnim.
7338 if (mAnimator.mAnimating || mAnimationScheduled) {
7339 // If we are animating, don't do the gc now but
7340 // delay a bit so we don't interrupt the animation.
7341 sendEmptyMessageDelayed(H.FORCE_GC, 2000);
7344 // If we are currently rotating the display, it will
7345 // schedule a new message when done.
7346 if (mDisplayFrozen) {
7350 Runtime.getRuntime().gc();
7354 case ENABLE_SCREEN: {
7355 performEnableScreen();
7359 case APP_FREEZE_TIMEOUT: {
7360 synchronized (mWindowMap) {
7361 Slog.w(TAG, "App freeze timeout expired.");
7362 DisplayContent displayContent = getDefaultDisplayContentLocked();
7363 final ArrayList<Task> tasks = displayContent.getTasks();
7364 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
7365 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
7366 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
7367 AppWindowToken tok = tokens.get(tokenNdx);
7368 if (tok.mAppAnimator.freezingScreen) {
7369 Slog.w(TAG, "Force clearing freeze: " + tok);
7370 unsetAppFreezingScreenLocked(tok, true, true);
7378 case CLIENT_FREEZE_TIMEOUT: {
7379 synchronized (mWindowMap) {
7380 if (mClientFreezingScreen) {
7381 mClientFreezingScreen = false;
7382 mLastFinishedFreezeSource = "client-timeout";
7383 stopFreezingDisplayLocked();
7389 case SEND_NEW_CONFIGURATION: {
7390 removeMessages(SEND_NEW_CONFIGURATION);
7391 sendNewConfiguration();
7395 case REPORT_WINDOWS_CHANGE: {
7396 if (mWindowsChanged) {
7397 synchronized (mWindowMap) {
7398 mWindowsChanged = false;
7400 notifyWindowsChanged();
7405 case DRAG_START_TIMEOUT: {
7406 IBinder win = (IBinder)msg.obj;
7408 Slog.w(TAG, "Timeout starting drag by win " + win);
7410 synchronized (mWindowMap) {
7411 // !!! TODO: ANR the app that has failed to start the drag in time
7412 if (mDragState != null) {
7413 mDragState.unregister();
7414 mInputMonitor.updateInputWindowsLw(true /*force*/);
7422 case DRAG_END_TIMEOUT: {
7423 IBinder win = (IBinder)msg.obj;
7425 Slog.w(TAG, "Timeout ending drag to win " + win);
7427 synchronized (mWindowMap) {
7428 // !!! TODO: ANR the drag-receiving app
7429 if (mDragState != null) {
7430 mDragState.mDragResult = false;
7431 mDragState.endDragLw();
7437 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
7438 notifyHardKeyboardStatusChange();
7442 case BOOT_TIMEOUT: {
7443 performBootTimeout();
7447 case WAITING_FOR_DRAWN_TIMEOUT: {
7448 Pair<WindowState, IRemoteCallback> pair;
7449 synchronized (mWindowMap) {
7450 pair = (Pair<WindowState, IRemoteCallback>)msg.obj;
7451 Slog.w(TAG, "Timeout waiting for drawn: " + pair.first);
7452 if (!mWaitingForDrawn.remove(pair)) {
7457 pair.second.sendResult(null);
7458 } catch (RemoteException e) {
7463 case SHOW_STRICT_MODE_VIOLATION: {
7464 showStrictModeViolation(msg.arg1, msg.arg2);
7468 case DO_ANIMATION_CALLBACK: {
7470 ((IRemoteCallback)msg.obj).sendResult(null);
7471 } catch (RemoteException e) {
7476 case DO_DISPLAY_ADDED:
7477 synchronized (mWindowMap) {
7478 handleDisplayAddedLocked(msg.arg1);
7482 case DO_DISPLAY_REMOVED:
7483 synchronized (mWindowMap) {
7484 handleDisplayRemovedLocked(msg.arg1);
7488 case DO_DISPLAY_CHANGED:
7489 synchronized (mWindowMap) {
7490 handleDisplayChangedLocked(msg.arg1);
7494 case TAP_OUTSIDE_STACK: {
7496 synchronized (mWindowMap) {
7497 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
7501 mActivityManager.setFocusedStack(stackId);
7502 } catch (RemoteException e) {
7507 case NOTIFY_ACTIVITY_DRAWN:
7509 mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
7510 } catch (RemoteException e) {
7514 if (DEBUG_WINDOW_TRACE) {
7515 Slog.v(TAG, "handleMessage: exit");
7520 // -------------------------------------------------------------
7521 // IWindowManager API
7522 // -------------------------------------------------------------
7525 public IWindowSession openSession(IInputMethodClient client,
7526 IInputContext inputContext) {
7527 if (client == null) throw new IllegalArgumentException("null client");
7528 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
7529 Session session = new Session(this, client, inputContext);
7534 public boolean inputMethodClientHasFocus(IInputMethodClient client) {
7535 synchronized (mWindowMap) {
7536 // The focus for the client is the window immediately below
7537 // where we would place the input method window.
7538 int idx = findDesiredInputMethodWindowIndexLocked(false);
7540 // TODO(multidisplay): IMEs are only supported on the default display.
7541 WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
7542 if (DEBUG_INPUT_METHOD) {
7543 Slog.i(TAG, "Desired input method target: " + imFocus);
7544 Slog.i(TAG, "Current focus: " + mCurrentFocus);
7545 Slog.i(TAG, "Last focus: " + mLastFocus);
7547 if (imFocus != null) {
7548 // This may be a starting window, in which case we still want
7549 // to count it as okay.
7550 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
7551 && imFocus.mAppToken != null) {
7552 // The client has definitely started, so it really should
7553 // have a window in this app token. Let's look for it.
7554 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
7555 WindowState w = imFocus.mAppToken.windows.get(i);
7557 Log.i(TAG, "Switching to real app window: " + w);
7563 if (DEBUG_INPUT_METHOD) {
7564 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient);
7565 if (imFocus.mSession.mClient != null) {
7566 Slog.i(TAG, "IM target client binder: "
7567 + imFocus.mSession.mClient.asBinder());
7568 Slog.i(TAG, "Requesting client binder: " + client.asBinder());
7571 if (imFocus.mSession.mClient != null &&
7572 imFocus.mSession.mClient.asBinder() == client.asBinder()) {
7578 // Okay, how about this... what is the current focus?
7579 // It seems in some cases we may not have moved the IM
7580 // target window, such as when it was in a pop-up window,
7581 // so let's also look at the current focus. (An example:
7582 // go to Gmail, start searching so the keyboard goes up,
7583 // press home. Sometimes the IME won't go down.)
7584 // Would be nice to fix this more correctly, but it's
7585 // way at the end of a release, and this should be good enough.
7586 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
7587 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
7595 public void getInitialDisplaySize(int displayId, Point size) {
7596 synchronized (mWindowMap) {
7597 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7598 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7599 synchronized(displayContent.mDisplaySizeLock) {
7600 size.x = displayContent.mInitialDisplayWidth;
7601 size.y = displayContent.mInitialDisplayHeight;
7608 public void getBaseDisplaySize(int displayId, Point size) {
7609 synchronized (mWindowMap) {
7610 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7611 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7612 synchronized(displayContent.mDisplaySizeLock) {
7613 size.x = displayContent.mBaseDisplayWidth;
7614 size.y = displayContent.mBaseDisplayHeight;
7621 public void setForcedDisplaySize(int displayId, int width, int height) {
7622 if (mContext.checkCallingOrSelfPermission(
7623 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7624 PackageManager.PERMISSION_GRANTED) {
7625 throw new SecurityException("Must hold permission " +
7626 android.Manifest.permission.WRITE_SECURE_SETTINGS);
7628 if (displayId != Display.DEFAULT_DISPLAY) {
7629 throw new IllegalArgumentException("Can only set the default display");
7631 synchronized(mWindowMap) {
7632 // Set some sort of reasonable bounds on the size of the display that we
7633 // will try to emulate.
7634 final int MIN_WIDTH = 200;
7635 final int MIN_HEIGHT = 200;
7636 final int MAX_SCALE = 2;
7637 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7638 if (displayContent != null) {
7639 width = Math.min(Math.max(width, MIN_WIDTH),
7640 displayContent.mInitialDisplayWidth * MAX_SCALE);
7641 height = Math.min(Math.max(height, MIN_HEIGHT),
7642 displayContent.mInitialDisplayHeight * MAX_SCALE);
7643 setForcedDisplaySizeLocked(displayContent, width, height);
7644 Settings.Global.putString(mContext.getContentResolver(),
7645 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
7650 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
7651 String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
7652 Settings.Global.DISPLAY_SIZE_FORCED);
7653 if (sizeStr == null || sizeStr.length() == 0) {
7654 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
7656 if (sizeStr != null && sizeStr.length() > 0) {
7657 final int pos = sizeStr.indexOf(',');
7658 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
7661 width = Integer.parseInt(sizeStr.substring(0, pos));
7662 height = Integer.parseInt(sizeStr.substring(pos+1));
7663 synchronized(displayContent.mDisplaySizeLock) {
7664 if (displayContent.mBaseDisplayWidth != width
7665 || displayContent.mBaseDisplayHeight != height) {
7666 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
7667 displayContent.mBaseDisplayWidth = width;
7668 displayContent.mBaseDisplayHeight = height;
7671 } catch (NumberFormatException ex) {
7675 String densityStr = Settings.Global.getString(mContext.getContentResolver(),
7676 Settings.Global.DISPLAY_DENSITY_FORCED);
7677 if (densityStr == null || densityStr.length() == 0) {
7678 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
7680 if (densityStr != null && densityStr.length() > 0) {
7683 density = Integer.parseInt(densityStr);
7684 synchronized(displayContent.mDisplaySizeLock) {
7685 if (displayContent.mBaseDisplayDensity != density) {
7686 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
7687 displayContent.mBaseDisplayDensity = density;
7690 } catch (NumberFormatException ex) {
7695 // displayContent must not be null
7696 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
7697 Slog.i(TAG, "Using new display size: " + width + "x" + height);
7699 synchronized(displayContent.mDisplaySizeLock) {
7700 displayContent.mBaseDisplayWidth = width;
7701 displayContent.mBaseDisplayHeight = height;
7703 reconfigureDisplayLocked(displayContent);
7707 public void clearForcedDisplaySize(int displayId) {
7708 if (mContext.checkCallingOrSelfPermission(
7709 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7710 PackageManager.PERMISSION_GRANTED) {
7711 throw new SecurityException("Must hold permission " +
7712 android.Manifest.permission.WRITE_SECURE_SETTINGS);
7714 if (displayId != Display.DEFAULT_DISPLAY) {
7715 throw new IllegalArgumentException("Can only set the default display");
7717 synchronized(mWindowMap) {
7718 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7719 if (displayContent != null) {
7720 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
7721 displayContent.mInitialDisplayHeight);
7722 Settings.Global.putString(mContext.getContentResolver(),
7723 Settings.Global.DISPLAY_SIZE_FORCED, "");
7729 public int getInitialDisplayDensity(int displayId) {
7730 synchronized (mWindowMap) {
7731 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7732 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7733 synchronized(displayContent.mDisplaySizeLock) {
7734 return displayContent.mInitialDisplayDensity;
7742 public int getBaseDisplayDensity(int displayId) {
7743 synchronized (mWindowMap) {
7744 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7745 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7746 synchronized(displayContent.mDisplaySizeLock) {
7747 return displayContent.mBaseDisplayDensity;
7755 public void setForcedDisplayDensity(int displayId, int density) {
7756 if (mContext.checkCallingOrSelfPermission(
7757 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7758 PackageManager.PERMISSION_GRANTED) {
7759 throw new SecurityException("Must hold permission " +
7760 android.Manifest.permission.WRITE_SECURE_SETTINGS);
7762 if (displayId != Display.DEFAULT_DISPLAY) {
7763 throw new IllegalArgumentException("Can only set the default display");
7765 synchronized(mWindowMap) {
7766 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7767 if (displayContent != null) {
7768 setForcedDisplayDensityLocked(displayContent, density);
7769 Settings.Global.putString(mContext.getContentResolver(),
7770 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
7775 // displayContent must not be null
7776 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
7777 Slog.i(TAG, "Using new display density: " + density);
7779 synchronized(displayContent.mDisplaySizeLock) {
7780 displayContent.mBaseDisplayDensity = density;
7782 reconfigureDisplayLocked(displayContent);
7786 public void clearForcedDisplayDensity(int displayId) {
7787 if (mContext.checkCallingOrSelfPermission(
7788 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7789 PackageManager.PERMISSION_GRANTED) {
7790 throw new SecurityException("Must hold permission " +
7791 android.Manifest.permission.WRITE_SECURE_SETTINGS);
7793 if (displayId != Display.DEFAULT_DISPLAY) {
7794 throw new IllegalArgumentException("Can only set the default display");
7796 synchronized(mWindowMap) {
7797 final DisplayContent displayContent = getDisplayContentLocked(displayId);
7798 if (displayContent != null) {
7799 setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
7800 Settings.Global.putString(mContext.getContentResolver(),
7801 Settings.Global.DISPLAY_DENSITY_FORCED, "");
7806 // displayContent must not be null
7807 private void reconfigureDisplayLocked(DisplayContent displayContent) {
7808 // TODO: Multidisplay: for now only use with default display.
7809 configureDisplayPolicyLocked(displayContent);
7810 displayContent.layoutNeeded = true;
7812 boolean configChanged = updateOrientationFromAppTokensLocked(false);
7813 mTempConfiguration.setToDefaults();
7814 mTempConfiguration.fontScale = mCurConfiguration.fontScale;
7815 if (computeScreenConfigurationLocked(mTempConfiguration)) {
7816 if (mCurConfiguration.diff(mTempConfiguration) != 0) {
7817 configChanged = true;
7821 if (configChanged) {
7822 mWaitingForConfig = true;
7823 startFreezingDisplayLocked(false, 0, 0);
7824 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
7827 performLayoutAndPlaceSurfacesLocked();
7830 private void configureDisplayPolicyLocked(DisplayContent displayContent) {
7831 mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
7832 displayContent.mBaseDisplayWidth,
7833 displayContent.mBaseDisplayHeight,
7834 displayContent.mBaseDisplayDensity);
7836 DisplayInfo displayInfo = displayContent.getDisplayInfo();
7837 mPolicy.setDisplayOverscan(displayContent.getDisplay(),
7838 displayInfo.overscanLeft, displayInfo.overscanTop,
7839 displayInfo.overscanRight, displayInfo.overscanBottom);
7843 public void setOverscan(int displayId, int left, int top, int right, int bottom) {
7844 if (mContext.checkCallingOrSelfPermission(
7845 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7846 PackageManager.PERMISSION_GRANTED) {
7847 throw new SecurityException("Must hold permission " +
7848 android.Manifest.permission.WRITE_SECURE_SETTINGS);
7850 synchronized(mWindowMap) {
7851 DisplayContent displayContent = getDisplayContentLocked(displayId);
7852 if (displayContent != null) {
7853 setOverscanLocked(displayContent, left, top, right, bottom);
7858 private void setOverscanLocked(DisplayContent displayContent,
7859 int left, int top, int right, int bottom) {
7860 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7861 synchronized (displayContent.mDisplaySizeLock) {
7862 displayInfo.overscanLeft = left;
7863 displayInfo.overscanTop = top;
7864 displayInfo.overscanRight = right;
7865 displayInfo.overscanBottom = bottom;
7868 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom);
7869 mDisplaySettings.writeSettingsLocked();
7871 reconfigureDisplayLocked(displayContent);
7874 // -------------------------------------------------------------
7876 // -------------------------------------------------------------
7878 final WindowState windowForClientLocked(Session session, IWindow client,
7879 boolean throwOnError) {
7880 return windowForClientLocked(session, client.asBinder(), throwOnError);
7883 final WindowState windowForClientLocked(Session session, IBinder client,
7884 boolean throwOnError) {
7885 WindowState win = mWindowMap.get(client);
7886 if (localLOGV) Slog.v(
7887 TAG, "Looking up client " + client + ": " + win);
7889 RuntimeException ex = new IllegalArgumentException(
7890 "Requested window " + client + " does not exist");
7894 Slog.w(TAG, "Failed looking up window", ex);
7897 if (session != null && win.mSession != session) {
7898 RuntimeException ex = new IllegalArgumentException(
7899 "Requested window " + client + " is in session " +
7900 win.mSession + ", not " + session);
7904 Slog.w(TAG, "Failed looking up window", ex);
7911 final void rebuildAppWindowListLocked() {
7912 // TODO: Multidisplay, when ActivityStacks and tasks exist on more than one display.
7913 rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
7916 private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
7917 final WindowList windows = displayContent.getWindowList();
7918 int NW = windows.size();
7923 if (mRebuildTmp.length < NW) {
7924 mRebuildTmp = new WindowState[NW+10];
7927 // First remove all existing app windows.
7930 WindowState w = windows.get(i);
7931 if (w.mAppToken != null) {
7932 WindowState win = windows.remove(i);
7933 win.mRebuilding = true;
7934 mRebuildTmp[numRemoved] = win;
7935 mWindowsChanged = true;
7936 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win);
7940 } else if (lastBelow == i-1) {
7941 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
7948 // Keep whatever windows were below the app windows still below,
7949 // by skipping them.
7953 // First add all of the exiting app tokens... these are no longer
7954 // in the main app list, but still have windows shown. We put them
7955 // in the back because now that the animation is over we no longer
7956 // will care about them.
7957 AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
7958 int NT = exitingAppTokens.size();
7959 for (int j=0; j<NT; j++) {
7960 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
7963 // And add in the still active app tokens in Z order.
7964 final ArrayList<Task> tasks = displayContent.getTasks();
7965 final int numTasks = tasks.size();
7966 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
7967 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
7968 final int numTokens = tokens.size();
7969 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
7970 final AppWindowToken wtoken = tokens.get(tokenNdx);
7971 i = reAddAppWindowsLocked(displayContent, i, wtoken);
7976 if (i != numRemoved) {
7977 Slog.w(TAG, "Rebuild removed " + numRemoved + " windows but added " + i,
7978 new RuntimeException("here").fillInStackTrace());
7979 for (i=0; i<numRemoved; i++) {
7980 WindowState ws = mRebuildTmp[i];
7981 if (ws.mRebuilding) {
7982 StringWriter sw = new StringWriter();
7983 PrintWriter pw = new FastPrintWriter(sw, false, 1024);
7984 ws.dump(pw, "", true);
7986 Slog.w(TAG, "This window was lost: " + ws);
7987 Slog.w(TAG, sw.toString());
7988 ws.mWinAnimator.destroySurfaceLocked();
7991 Slog.w(TAG, "Current app token list:");
7992 dumpAppTokensLocked();
7993 Slog.w(TAG, "Final window list:");
7994 dumpWindowsLocked();
7998 private final void assignLayersLocked(WindowList windows) {
7999 int N = windows.size();
8000 int curBaseLayer = 0;
8004 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows,
8005 new RuntimeException("here").fillInStackTrace());
8007 boolean anyLayerChanged = false;
8009 for (i=0; i<N; i++) {
8010 final WindowState w = windows.get(i);
8011 final WindowStateAnimator winAnimator = w.mWinAnimator;
8012 boolean layerChanged = false;
8013 int oldLayer = w.mLayer;
8014 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
8015 || (i > 0 && w.mIsWallpaper)) {
8016 curLayer += WINDOW_LAYER_MULTIPLIER;
8017 w.mLayer = curLayer;
8019 curBaseLayer = curLayer = w.mBaseLayer;
8020 w.mLayer = curLayer;
8022 if (w.mLayer != oldLayer) {
8023 layerChanged = true;
8024 anyLayerChanged = true;
8026 final AppWindowToken wtoken = w.mAppToken;
8027 oldLayer = winAnimator.mAnimLayer;
8028 if (w.mTargetAppToken != null) {
8029 winAnimator.mAnimLayer =
8030 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
8031 } else if (wtoken != null) {
8032 winAnimator.mAnimLayer =
8033 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment;
8035 winAnimator.mAnimLayer = w.mLayer;
8037 if (w.mIsImWindow) {
8038 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
8039 } else if (w.mIsWallpaper) {
8040 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
8042 if (winAnimator.mAnimLayer != oldLayer) {
8043 layerChanged = true;
8044 anyLayerChanged = true;
8046 if (layerChanged && w.getStack().isDimming(winAnimator)) {
8047 // Force an animation pass just to update the mDimLayer layer.
8048 scheduleAnimationLocked();
8050 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
8051 + "mBase=" + w.mBaseLayer
8052 + " mLayer=" + w.mLayer
8054 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment)
8055 + " =mAnimLayer=" + winAnimator.mAnimLayer);
8056 //System.out.println(
8057 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
8060 //TODO (multidisplay): Magnification is supported only for the default display.
8061 if (mDisplayMagnifier != null && anyLayerChanged
8062 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
8063 mDisplayMagnifier.onWindowLayersChangedLocked();
8067 private final void performLayoutAndPlaceSurfacesLocked() {
8070 mTraversalScheduled = false;
8071 performLayoutAndPlaceSurfacesLockedLoop();
8072 mH.removeMessages(H.DO_TRAVERSAL);
8074 } while (mTraversalScheduled && loopCount > 0);
8075 mInnerFields.mWallpaperActionPending = false;
8078 private boolean mInLayout = false;
8079 private final void performLayoutAndPlaceSurfacesLockedLoop() {
8082 throw new RuntimeException("Recursive call!");
8084 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
8085 + Debug.getCallers(3));
8089 if (mWaitingForConfig) {
8090 // Our configuration has changed (most likely rotation), but we
8091 // don't yet have the complete configuration to report to
8092 // applications. Don't do any window layout until we have it.
8096 if (!mDisplayReady) {
8097 // Not yet initialized, nothing to do.
8101 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
8103 boolean recoveringMemory = false;
8106 if (mForceRemoves != null) {
8107 recoveringMemory = true;
8108 // Wait a little bit for things to settle down, and off we go.
8109 for (int i=0; i<mForceRemoves.size(); i++) {
8110 WindowState ws = mForceRemoves.get(i);
8111 Slog.i(TAG, "Force removing: " + ws);
8112 removeWindowInnerLocked(ws.mSession, ws);
8114 mForceRemoves = null;
8115 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
8116 Object tmp = new Object();
8117 synchronized (tmp) {
8120 } catch (InterruptedException e) {
8124 } catch (RuntimeException e) {
8125 Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
8129 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
8133 if (needsLayout()) {
8134 if (++mLayoutRepeatCount < 6) {
8135 requestTraversalLocked();
8137 Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
8138 mLayoutRepeatCount = 0;
8141 mLayoutRepeatCount = 0;
8144 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
8145 mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
8146 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE);
8148 } catch (RuntimeException e) {
8150 Log.wtf(TAG, "Unhandled exception while laying out windows", e);
8153 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
8156 private final void performLayoutLockedInner(final DisplayContent displayContent,
8157 boolean initial, boolean updateInputWindows) {
8158 if (!displayContent.layoutNeeded) {
8161 displayContent.layoutNeeded = false;
8162 WindowList windows = displayContent.getWindowList();
8163 boolean isDefaultDisplay = displayContent.isDefaultDisplay;
8165 DisplayInfo displayInfo = displayContent.getDisplayInfo();
8166 final int dw = displayInfo.logicalWidth;
8167 final int dh = displayInfo.logicalHeight;
8169 final int NFW = mFakeWindows.size();
8170 for (int i=0; i<NFW; i++) {
8171 mFakeWindows.get(i).layout(dw, dh);
8174 final int N = windows.size();
8178 Slog.v(TAG, "-------------------------------------");
8179 Slog.v(TAG, "performLayout: needed="
8180 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
8183 WindowStateAnimator universeBackground = null;
8185 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
8186 if (isDefaultDisplay) {
8187 // Not needed on non-default displays.
8188 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw();
8189 mScreenRect.set(0, 0, dw, dh);
8192 mPolicy.getContentRectLw(mTmpContentRect);
8193 displayContent.setStackBoxSize(mTmpContentRect);
8195 int seq = mLayoutSeq+1;
8196 if (seq < 0) seq = 0;
8199 boolean behindDream = false;
8201 // First perform layout of any root windows (not attached
8202 // to another window).
8203 int topAttached = -1;
8204 for (i = N-1; i >= 0; i--) {
8205 final WindowState win = windows.get(i);
8207 // Don't do layout of a window if it is not visible, or
8208 // soon won't be visible, to avoid wasting time and funky
8209 // changes while a window is animating away.
8210 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
8211 || win.isGoneForLayoutLw();
8213 if (DEBUG_LAYOUT && !win.mLayoutAttached) {
8214 Slog.v(TAG, "1ST PASS " + win
8215 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
8216 + " mLayoutAttached=" + win.mLayoutAttached
8217 + " screen changed=" + win.isConfigChanged());
8218 final AppWindowToken atoken = win.mAppToken;
8219 if (gone) Slog.v(TAG, " GONE: mViewVisibility="
8220 + win.mViewVisibility + " mRelayoutCalled="
8221 + win.mRelayoutCalled + " hidden="
8222 + win.mRootToken.hidden + " hiddenRequested="
8223 + (atoken != null && atoken.hiddenRequested)
8224 + " mAttachedHidden=" + win.mAttachedHidden);
8225 else Slog.v(TAG, " VIS: mViewVisibility="
8226 + win.mViewVisibility + " mRelayoutCalled="
8227 + win.mRelayoutCalled + " hidden="
8228 + win.mRootToken.hidden + " hiddenRequested="
8229 + (atoken != null && atoken.hiddenRequested)
8230 + " mAttachedHidden=" + win.mAttachedHidden);
8233 // If this view is GONE, then skip it -- keep the current
8234 // frame, and let the caller know so they can ignore it
8235 // if they want. (We do the normal layout for INVISIBLE
8236 // windows, since that means "perform layout as normal,
8237 // just don't display").
8238 if (!gone || !win.mHaveFrame || win.mLayoutNeeded
8239 || (win.mAttrs.type == TYPE_KEYGUARD && win.isConfigChanged())
8240 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8241 if (!win.mLayoutAttached) {
8243 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8244 win.mContentChanged = false;
8246 if (win.mAttrs.type == TYPE_DREAM) {
8247 // Don't layout windows behind a dream, so that if it
8248 // does stuff like hide the status bar we won't get a
8249 // bad transition when it goes away.
8252 win.mLayoutNeeded = false;
8254 mPolicy.layoutWindowLw(win, win.mAttrs, null);
8255 win.mLayoutSeq = seq;
8256 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame="
8257 + win.mFrame + " mContainingFrame="
8258 + win.mContainingFrame + " mDisplayFrame="
8259 + win.mDisplayFrame);
8261 if (topAttached < 0) topAttached = i;
8264 if (win.mViewVisibility == View.VISIBLE
8265 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
8266 && universeBackground == null) {
8267 universeBackground = win.mWinAnimator;
8271 if (mAnimator.mUniverseBackground != universeBackground) {
8272 mFocusMayChange = true;
8273 mAnimator.mUniverseBackground = universeBackground;
8276 boolean attachedBehindDream = false;
8278 // Now perform layout of attached windows, which usually
8279 // depend on the position of the window they are attached to.
8280 // XXX does not deal with windows that are attached to windows
8281 // that are themselves attached.
8282 for (i = topAttached; i >= 0; i--) {
8283 final WindowState win = windows.get(i);
8285 if (win.mLayoutAttached) {
8286 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
8287 + " mHaveFrame=" + win.mHaveFrame
8288 + " mViewVisibility=" + win.mViewVisibility
8289 + " mRelayoutCalled=" + win.mRelayoutCalled);
8290 // If this view is GONE, then skip it -- keep the current
8291 // frame, and let the caller know so they can ignore it
8292 // if they want. (We do the normal layout for INVISIBLE
8293 // windows, since that means "perform layout as normal,
8294 // just don't display").
8295 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
8298 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
8299 || !win.mHaveFrame || win.mLayoutNeeded) {
8301 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8302 win.mContentChanged = false;
8304 win.mLayoutNeeded = false;
8306 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
8307 win.mLayoutSeq = seq;
8308 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame="
8309 + win.mFrame + " mContainingFrame="
8310 + win.mContainingFrame + " mDisplayFrame="
8311 + win.mDisplayFrame);
8313 } else if (win.mAttrs.type == TYPE_DREAM) {
8314 // Don't layout windows behind a dream, so that if it
8315 // does stuff like hide the status bar we won't get a
8316 // bad transition when it goes away.
8317 attachedBehindDream = behindDream;
8321 // Window frames may have changed. Tell the input dispatcher about it.
8322 mInputMonitor.setUpdateInputWindowsNeededLw();
8323 if (updateInputWindows) {
8324 mInputMonitor.updateInputWindowsLw(false /*force*/);
8327 mPolicy.finishLayoutLw();
8330 void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
8331 // If the screen is currently frozen or off, then keep
8332 // it frozen/off until this window draws at its new
8334 if (!okToDisplay()) {
8335 if (DEBUG_ORIENTATION) Slog.v(TAG,
8336 "Changing surface while display frozen: " + w);
8337 w.mOrientationChanging = true;
8338 w.mLastFreezeDuration = 0;
8339 mInnerFields.mOrientationChangeComplete = false;
8340 if (!mWindowsFreezingScreen) {
8341 mWindowsFreezingScreen = true;
8342 // XXX should probably keep timeout from
8343 // when we first froze the display.
8344 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8345 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
8346 WINDOW_FREEZE_TIMEOUT_DURATION);
8352 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8353 * @param windows List of windows on default display.
8354 * @return bitmap indicating if another pass through layout must be made.
8356 public int handleAppTransitionReadyLocked(WindowList windows) {
8359 int NN = mOpeningApps.size();
8360 boolean goodToGo = true;
8361 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8362 "Checking " + NN + " opening apps (frozen="
8363 + mDisplayFrozen + " timeout="
8364 + mAppTransition.isTimeout() + ")...");
8365 if (!mDisplayFrozen && !mAppTransition.isTimeout()) {
8366 // If the display isn't frozen, wait to do anything until
8367 // all of the apps are ready. Otherwise just go because
8368 // we'll unfreeze the display when everyone is ready.
8369 for (i=0; i<NN && goodToGo; i++) {
8370 AppWindowToken wtoken = mOpeningApps.get(i);
8371 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8372 "Check opening app=" + wtoken + ": allDrawn="
8373 + wtoken.allDrawn + " startingDisplayed="
8374 + wtoken.startingDisplayed + " startingMoved="
8375 + wtoken.startingMoved);
8376 if (!wtoken.allDrawn && !wtoken.startingDisplayed
8377 && !wtoken.startingMoved) {
8383 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
8384 int transit = mAppTransition.getAppTransition();
8385 if (mSkipAppTransitionAnimation) {
8386 transit = AppTransition.TRANSIT_UNSET;
8388 mAppTransition.goodToGo();
8389 mStartingIconInTransition = false;
8390 mSkipAppTransitionAnimation = false;
8392 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
8394 rebuildAppWindowListLocked();
8396 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
8397 WindowState oldWallpaper =
8398 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
8399 && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
8400 ? null : mWallpaperTarget;
8402 mInnerFields.mWallpaperMayChange = false;
8404 // The top-most window will supply the layout params,
8405 // and we will determine it below.
8406 LayoutParams animLp = null;
8407 int bestAnimLayer = -1;
8408 boolean fullscreenAnim = false;
8410 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8411 "New wallpaper target=" + mWallpaperTarget
8412 + ", oldWallpaper=" + oldWallpaper
8413 + ", lower target=" + mLowerWallpaperTarget
8414 + ", upper target=" + mUpperWallpaperTarget);
8416 boolean openingAppHasWallpaper = false;
8417 boolean closingAppHasWallpaper = false;
8418 final AppWindowToken lowerWallpaperAppToken;
8419 final AppWindowToken upperWallpaperAppToken;
8420 if (mLowerWallpaperTarget == null) {
8421 lowerWallpaperAppToken = upperWallpaperAppToken = null;
8423 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
8424 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
8427 // Do a first pass through the tokens for two
8429 // (1) Determine if both the closing and opening
8430 // app token sets are wallpaper targets, in which
8431 // case special animations are needed
8432 // (since the wallpaper needs to stay static
8434 // (2) Find the layout params of the top-most
8435 // application window in the tokens, which is
8436 // what will control the animation theme.
8437 final int NC = mClosingApps.size();
8438 NN = NC + mOpeningApps.size();
8439 for (i=0; i<NN; i++) {
8440 final AppWindowToken wtoken;
8442 wtoken = mClosingApps.get(i);
8443 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8444 closingAppHasWallpaper = true;
8447 wtoken = mOpeningApps.get(i - NC);
8448 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8449 openingAppHasWallpaper = true;
8453 if (wtoken.appFullscreen) {
8454 WindowState ws = wtoken.findMainWindow();
8457 bestAnimLayer = ws.mLayer;
8458 fullscreenAnim = true;
8460 } else if (!fullscreenAnim) {
8461 WindowState ws = wtoken.findMainWindow();
8463 if (ws.mLayer > bestAnimLayer) {
8465 bestAnimLayer = ws.mLayer;
8471 if (closingAppHasWallpaper && openingAppHasWallpaper) {
8472 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
8474 case AppTransition.TRANSIT_ACTIVITY_OPEN:
8475 case AppTransition.TRANSIT_TASK_OPEN:
8476 case AppTransition.TRANSIT_TASK_TO_FRONT:
8477 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
8479 case AppTransition.TRANSIT_ACTIVITY_CLOSE:
8480 case AppTransition.TRANSIT_TASK_CLOSE:
8481 case AppTransition.TRANSIT_TASK_TO_BACK:
8482 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
8485 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
8486 } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
8487 // We are transitioning from an activity with
8488 // a wallpaper to one without.
8489 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
8490 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8491 "New transit away from wallpaper: " + transit);
8492 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
8493 // We are transitioning from an activity without
8494 // a wallpaper to now showing the wallpaper
8495 transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
8496 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8497 "New transit into wallpaper: " + transit);
8500 // If all closing windows are obscured, then there is
8501 // no need to do an animation. This is the case, for
8502 // example, when this transition is being done behind
8504 if (!mPolicy.allowAppAnimationsLw()) {
8508 AppWindowToken topOpeningApp = null;
8509 int topOpeningLayer = 0;
8511 NN = mOpeningApps.size();
8512 for (i=0; i<NN; i++) {
8513 AppWindowToken wtoken = mOpeningApps.get(i);
8514 final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
8515 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
8516 appAnimator.clearThumbnail();
8517 wtoken.inPendingTransaction = false;
8518 appAnimator.animation = null;
8519 setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
8520 wtoken.updateReportedVisibilityLocked();
8521 wtoken.waitingToShow = false;
8523 appAnimator.mAllAppWinAnimators.clear();
8524 final int N = wtoken.allAppWindows.size();
8525 for (int j = 0; j < N; j++) {
8526 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
8528 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
8530 if (animLp != null) {
8532 for (int j=0; j<wtoken.windows.size(); j++) {
8533 WindowState win = wtoken.windows.get(j);
8534 if (win.mWinAnimator.mAnimLayer > layer) {
8535 layer = win.mWinAnimator.mAnimLayer;
8538 if (topOpeningApp == null || layer > topOpeningLayer) {
8539 topOpeningApp = wtoken;
8540 topOpeningLayer = layer;
8544 NN = mClosingApps.size();
8545 for (i=0; i<NN; i++) {
8546 AppWindowToken wtoken = mClosingApps.get(i);
8547 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8548 "Now closing app " + wtoken);
8549 wtoken.mAppAnimator.clearThumbnail();
8550 wtoken.inPendingTransaction = false;
8551 wtoken.mAppAnimator.animation = null;
8552 setTokenVisibilityLocked(wtoken, animLp, false,
8554 wtoken.updateReportedVisibilityLocked();
8555 wtoken.waitingToHide = false;
8556 // Force the allDrawn flag, because we want to start
8557 // this guy's animations regardless of whether it's
8559 wtoken.allDrawn = true;
8560 wtoken.deferClearAllDrawn = false;
8563 AppWindowAnimator appAnimator =
8564 topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
8565 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
8566 if (nextAppTransitionThumbnail != null && appAnimator != null
8567 && appAnimator.animation != null) {
8568 // This thumbnail animation is very special, we need to have
8569 // an extra surface with the thumbnail included with the animation.
8570 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
8571 nextAppTransitionThumbnail.getHeight());
8573 // TODO(multi-display): support other displays
8574 final DisplayContent displayContent = getDefaultDisplayContentLocked();
8575 final Display display = displayContent.getDisplay();
8576 SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
8578 dirty.width(), dirty.height(),
8579 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
8580 surfaceControl.setLayerStack(display.getLayerStack());
8581 appAnimator.thumbnail = surfaceControl;
8582 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE");
8583 Surface drawSurface = new Surface();
8584 drawSurface.copyFrom(surfaceControl);
8585 Canvas c = drawSurface.lockCanvas(dirty);
8586 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
8587 drawSurface.unlockCanvasAndPost(c);
8588 drawSurface.release();
8589 appAnimator.thumbnailLayer = topOpeningLayer;
8590 DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
8591 Animation anim = mAppTransition.createThumbnailAnimationLocked(
8592 transit, true, true, displayInfo.appWidth, displayInfo.appHeight);
8593 appAnimator.thumbnailAnimation = anim;
8594 anim.restrictDuration(MAX_ANIMATION_DURATION);
8595 anim.scaleCurrentDuration(mTransitionAnimationScale);
8596 Point p = new Point();
8597 mAppTransition.getStartingPoint(p);
8598 appAnimator.thumbnailX = p.x;
8599 appAnimator.thumbnailY = p.y;
8600 } catch (OutOfResourcesException e) {
8601 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
8602 + " h=" + dirty.height(), e);
8603 appAnimator.clearThumbnail();
8607 mAppTransition.postAnimationCallback();
8608 mAppTransition.clear();
8610 mOpeningApps.clear();
8611 mClosingApps.clear();
8613 // This has changed the visibility of windows, so perform
8614 // a new layout to get them all up-to-date.
8615 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
8616 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
8617 getDefaultDisplayContentLocked().layoutNeeded = true;
8619 // TODO(multidisplay): IMEs are only supported on the default display.
8620 if (windows == getDefaultWindowListLocked()
8621 && !moveInputMethodWindowsIfNeededLocked(true)) {
8622 assignLayersLocked(windows);
8624 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/);
8625 mFocusMayChange = false;
8632 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8633 * @return bitmap indicating if another pass through layout must be made.
8635 private int handleAnimatingStoppedAndTransitionLocked() {
8638 mAppTransition.setIdle();
8639 // Restore window app tokens to the ActivityManager views
8640 final DisplayContent displayContent = getDefaultDisplayContentLocked();
8641 final ArrayList<Task> tasks = displayContent.getTasks();
8642 final int numTasks = tasks.size();
8643 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
8644 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8645 final int numTokens = tokens.size();
8646 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
8647 final AppWindowToken wtoken = tokens.get(tokenNdx);
8648 wtoken.sendingToBottom = false;
8651 rebuildAppWindowListLocked();
8653 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
8654 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
8655 "Wallpaper layer changed: assigning layers + relayout");
8656 moveInputMethodWindowsIfNeededLocked(true);
8657 mInnerFields.mWallpaperMayChange = true;
8658 // Since the window list has been rebuilt, focus might
8659 // have to be recomputed since the actual order of windows
8660 // might have changed again.
8661 mFocusMayChange = true;
8666 private void updateResizingWindows(final WindowState w) {
8667 final WindowStateAnimator winAnimator = w.mWinAnimator;
8668 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
8669 w.mOverscanInsetsChanged |=
8670 !w.mLastOverscanInsets.equals(w.mOverscanInsets);
8671 w.mContentInsetsChanged |=
8672 !w.mLastContentInsets.equals(w.mContentInsets);
8673 w.mVisibleInsetsChanged |=
8674 !w.mLastVisibleInsets.equals(w.mVisibleInsets);
8675 boolean configChanged = w.isConfigChanged();
8676 if (DEBUG_CONFIGURATION && configChanged) {
8677 Slog.v(TAG, "Win " + w + " config changed: "
8678 + mCurConfiguration);
8680 if (localLOGV) Slog.v(TAG, "Resizing " + w
8681 + ": configChanged=" + configChanged
8682 + " last=" + w.mLastFrame + " frame=" + w.mFrame);
8683 w.mLastFrame.set(w.mFrame);
8684 if (w.mContentInsetsChanged
8685 || w.mVisibleInsetsChanged
8686 || winAnimator.mSurfaceResized
8688 if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
8689 Slog.v(TAG, "Resize reasons for w=" + w + ": "
8690 + " contentInsetsChanged=" + w.mContentInsetsChanged
8691 + " " + w.mContentInsets.toShortString()
8692 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
8693 + " " + w.mVisibleInsets.toShortString()
8694 + " surfaceResized=" + winAnimator.mSurfaceResized
8695 + " configChanged=" + configChanged);
8698 w.mLastOverscanInsets.set(w.mOverscanInsets);
8699 w.mLastContentInsets.set(w.mContentInsets);
8700 w.mLastVisibleInsets.set(w.mVisibleInsets);
8701 makeWindowFreezingScreenIfNeededLocked(w);
8702 // If the orientation is changing, then we need to
8703 // hold off on unfreezing the display until this
8704 // window has been redrawn; to do that, we need
8705 // to go through the process of getting informed
8706 // by the application when it has finished drawing.
8707 if (w.mOrientationChanging) {
8708 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
8709 "Orientation start waiting for draw mDrawState=DRAW_PENDING in "
8710 + w + ", surface " + winAnimator.mSurfaceControl);
8711 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
8712 if (w.mAppToken != null) {
8713 w.mAppToken.allDrawn = false;
8714 w.mAppToken.deferClearAllDrawn = false;
8717 if (!mResizingWindows.contains(w)) {
8718 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
8719 "Resizing window " + w + " to " + winAnimator.mSurfaceW
8720 + "x" + winAnimator.mSurfaceH);
8721 mResizingWindows.add(w);
8723 } else if (w.mOrientationChanging) {
8724 if (w.isDrawnLw()) {
8725 if (DEBUG_ORIENTATION) Slog.v(TAG,
8726 "Orientation not waiting for draw in "
8727 + w + ", surface " + winAnimator.mSurfaceControl);
8728 w.mOrientationChanging = false;
8729 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
8730 - mDisplayFreezeTime);
8737 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8739 * @param w WindowState this method is applied to.
8740 * @param currentTime The time which animations use for calculating transitions.
8741 * @param innerDw Width of app window.
8742 * @param innerDh Height of app window.
8744 private void handleNotObscuredLocked(final WindowState w, final long currentTime,
8745 final int innerDw, final int innerDh) {
8746 final WindowManager.LayoutParams attrs = w.mAttrs;
8747 final int attrFlags = attrs.flags;
8748 final boolean canBeSeen = w.isDisplayedLw();
8750 if (w.mHasSurface) {
8751 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
8752 mInnerFields.mHoldScreen = w.mSession;
8754 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0
8755 && mInnerFields.mScreenBrightness < 0) {
8756 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness;
8758 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0
8759 && mInnerFields.mButtonBrightness < 0) {
8760 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
8762 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
8763 && mInnerFields.mUserActivityTimeout < 0) {
8764 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
8767 final int type = attrs.type;
8769 && (type == TYPE_SYSTEM_DIALOG
8770 || type == TYPE_RECENTS_OVERLAY
8771 || type == TYPE_KEYGUARD
8772 || type == TYPE_SYSTEM_ERROR)) {
8773 mInnerFields.mSyswin = true;
8777 if (type == TYPE_DREAM || type == TYPE_KEYGUARD) {
8778 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_MIRROR;
8779 } else if (mInnerFields.mDisplayHasContent
8780 == LayoutFields.DISPLAY_CONTENT_UNKNOWN) {
8781 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNIQUE;
8786 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
8787 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
8788 // This window completely covers everything behind it,
8789 // so we want to leave all of them as undimmed (for
8790 // performance reasons).
8791 mInnerFields.mObscured = true;
8795 private void handleFlagDimBehind(WindowState w, int innerDw, int innerDh) {
8796 final WindowManager.LayoutParams attrs = w.mAttrs;
8797 if ((attrs.flags & FLAG_DIM_BEHIND) != 0
8798 && w.isDisplayedLw()
8800 final WindowStateAnimator winAnimator = w.mWinAnimator;
8801 final TaskStack stack = w.getStack();
8802 stack.setDimmingTag();
8803 if (!stack.isDimming(winAnimator)) {
8804 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
8805 stack.startDimmingIfNeeded(winAnimator);
8810 private void updateAllDrawnLocked(DisplayContent displayContent) {
8811 // See if any windows have been drawn, so they (and others
8812 // associated with them) can now be shown.
8813 final ArrayList<Task> tasks = displayContent.getTasks();
8814 final int numTasks = tasks.size();
8815 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
8816 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8817 final int numTokens = tokens.size();
8818 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
8819 final AppWindowToken wtoken = tokens.get(tokenNdx);
8820 if (!wtoken.allDrawn) {
8821 int numInteresting = wtoken.numInterestingWindows;
8822 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
8823 if (DEBUG_VISIBILITY) Slog.v(TAG,
8824 "allDrawn: " + wtoken
8825 + " interesting=" + numInteresting
8826 + " drawn=" + wtoken.numDrawnWindows);
8827 wtoken.allDrawn = true;
8828 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
8835 // "Something has changed! Let's make it correct now."
8836 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
8837 if (DEBUG_WINDOW_TRACE) {
8838 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
8839 + Debug.getCallers(3));
8842 final long currentTime = SystemClock.uptimeMillis();
8846 if (mFocusMayChange) {
8847 mFocusMayChange = false;
8848 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
8849 false /*updateInputWindows*/);
8852 // Initialize state of exiting tokens.
8853 final int numDisplays = mDisplayContents.size();
8854 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
8855 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
8856 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
8857 displayContent.mExitingTokens.get(i).hasVisible = false;
8860 // Initialize state of exiting applications.
8861 for (i=displayContent.mExitingAppTokens.size()-1; i>=0; i--) {
8862 displayContent.mExitingAppTokens.get(i).hasVisible = false;
8866 mInnerFields.mHoldScreen = null;
8867 mInnerFields.mScreenBrightness = -1;
8868 mInnerFields.mButtonBrightness = -1;
8869 mInnerFields.mUserActivityTimeout = -1;
8870 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN;
8872 mTransactionSequence++;
8874 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
8875 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
8876 final int defaultDw = defaultInfo.logicalWidth;
8877 final int defaultDh = defaultInfo.logicalHeight;
8879 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
8880 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
8881 SurfaceControl.openTransaction();
8884 if (mWatermark != null) {
8885 mWatermark.positionSurface(defaultDw, defaultDh);
8887 if (mStrictModeFlash != null) {
8888 mStrictModeFlash.positionSurface(defaultDw, defaultDh);
8891 boolean focusDisplayed = false;
8893 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
8894 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
8895 boolean updateAllDrawn = false;
8896 WindowList windows = displayContent.getWindowList();
8897 DisplayInfo displayInfo = displayContent.getDisplayInfo();
8898 final int displayId = displayContent.getDisplayId();
8899 final int dw = displayInfo.logicalWidth;
8900 final int dh = displayInfo.logicalHeight;
8901 final int innerDw = displayInfo.appWidth;
8902 final int innerDh = displayInfo.appHeight;
8903 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
8905 // Reset for each display unless we are forcing mirroring.
8906 if (mInnerFields.mDisplayHasContent != LayoutFields.DISPLAY_CONTENT_MIRROR) {
8907 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN;
8914 Slog.w(TAG, "Animation repeat aborted after too many iterations");
8915 displayContent.layoutNeeded = false;
8919 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
8920 displayContent.pendingLayoutChanges);
8922 if ((displayContent.pendingLayoutChanges &
8923 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
8924 (adjustWallpaperWindowsLocked() &
8925 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
8926 assignLayersLocked(windows);
8927 displayContent.layoutNeeded = true;
8930 if (isDefaultDisplay && (displayContent.pendingLayoutChanges
8931 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
8932 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
8933 if (updateOrientationFromAppTokensLocked(true)) {
8934 displayContent.layoutNeeded = true;
8935 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
8939 if ((displayContent.pendingLayoutChanges
8940 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
8941 displayContent.layoutNeeded = true;
8944 // FIRST LOOP: Perform a layout, if needed.
8946 performLayoutLockedInner(displayContent, repeats == 1,
8947 false /*updateInputWindows*/);
8949 Slog.w(TAG, "Layout repeat skipped after too many iterations");
8952 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
8954 displayContent.pendingLayoutChanges = 0;
8956 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
8957 + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
8959 if (isDefaultDisplay) {
8960 mPolicy.beginPostLayoutPolicyLw(dw, dh);
8961 for (i = windows.size() - 1; i >= 0; i--) {
8962 WindowState w = windows.get(i);
8963 if (w.mHasSurface) {
8964 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs);
8967 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
8968 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
8969 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
8971 } while (displayContent.pendingLayoutChanges != 0);
8973 mInnerFields.mObscured = false;
8974 mInnerFields.mSyswin = false;
8975 displayContent.resetDimming();
8977 // Only used if default window
8978 final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
8980 final int N = windows.size();
8981 for (i=N-1; i>=0; i--) {
8982 WindowState w = windows.get(i);
8984 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
8987 w.mObscured = mInnerFields.mObscured;
8988 if (!mInnerFields.mObscured) {
8989 handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
8992 if (!w.getStack().testDimmingTag()) {
8993 handleFlagDimBehind(w, innerDw, innerDh);
8996 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
8997 && w.isVisibleLw()) {
8998 // This is the wallpaper target and its obscured state
8999 // changed... make sure the current wallaper's visibility
9000 // has been updated accordingly.
9001 updateWallpaperVisibilityLocked();
9004 final WindowStateAnimator winAnimator = w.mWinAnimator;
9006 // If the window has moved due to its containing
9007 // content frame changing, then we'd like to animate
9009 if (w.mHasSurface && w.shouldAnimateMove()) {
9010 // Frame has moved, containing content frame
9011 // has also moved, and we're not currently animating...
9012 // let's do something.
9013 Animation a = AnimationUtils.loadAnimation(mContext,
9014 com.android.internal.R.anim.window_move_from_decor);
9015 winAnimator.setAnimation(a);
9016 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
9017 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
9019 w.mClient.moved(w.mFrame.left, w.mFrame.top);
9020 } catch (RemoteException e) {
9024 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
9025 w.mContentChanged = false;
9027 // Moved from updateWindowsAndWallpaperLocked().
9028 if (w.mHasSurface) {
9029 // Take care of the window being ready to display.
9030 final boolean committed =
9031 winAnimator.commitFinishDrawingLocked(currentTime);
9032 if (isDefaultDisplay && committed) {
9033 if (w.mAttrs.type == TYPE_DREAM) {
9034 // HACK: When a dream is shown, it may at that
9035 // point hide the lock screen. So we need to
9036 // redo the layout to let the phone window manager
9037 // make this happen.
9038 displayContent.pendingLayoutChanges |=
9039 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9040 if (DEBUG_LAYOUT_REPEATS) {
9042 "dream and commitFinishDrawingLocked true",
9043 displayContent.pendingLayoutChanges);
9046 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
9047 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
9048 "First draw done in potential wallpaper target " + w);
9049 mInnerFields.mWallpaperMayChange = true;
9050 displayContent.pendingLayoutChanges |=
9051 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9052 if (DEBUG_LAYOUT_REPEATS) {
9054 "wallpaper and commitFinishDrawingLocked true",
9055 displayContent.pendingLayoutChanges);
9060 winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
9062 final AppWindowToken atoken = w.mAppToken;
9063 if (DEBUG_STARTING_WINDOW && atoken != null
9064 && w == atoken.startingWindow) {
9065 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
9066 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
9067 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
9070 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
9071 if (atoken.lastTransactionSequence != mTransactionSequence) {
9072 atoken.lastTransactionSequence = mTransactionSequence;
9073 atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9074 atoken.startingDisplayed = false;
9076 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
9077 && !w.mExiting && !w.mDestroying) {
9078 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
9079 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
9080 + ", isAnimating=" + winAnimator.isAnimating());
9081 if (!w.isDrawnLw()) {
9082 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
9083 + " pv=" + w.mPolicyVisibility
9084 + " mDrawState=" + winAnimator.mDrawState
9085 + " ah=" + w.mAttachedHidden
9086 + " th=" + atoken.hiddenRequested
9087 + " a=" + winAnimator.mAnimating);
9090 if (w != atoken.startingWindow) {
9091 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
9092 atoken.numInterestingWindows++;
9093 if (w.isDrawnLw()) {
9094 atoken.numDrawnWindows++;
9095 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
9096 "tokenMayBeDrawn: " + atoken
9097 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
9098 + " mAppFreezing=" + w.mAppFreezing);
9099 updateAllDrawn = true;
9102 } else if (w.isDrawnLw()) {
9103 atoken.startingDisplayed = true;
9109 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
9110 && w.isDisplayedLw()) {
9111 focusDisplayed = true;
9114 updateResizingWindows(w);
9117 final boolean hasUniqueContent;
9118 switch (mInnerFields.mDisplayHasContent) {
9119 case LayoutFields.DISPLAY_CONTENT_MIRROR:
9120 hasUniqueContent = isDefaultDisplay;
9122 case LayoutFields.DISPLAY_CONTENT_UNIQUE:
9123 hasUniqueContent = true;
9125 case LayoutFields.DISPLAY_CONTENT_UNKNOWN:
9127 hasUniqueContent = false;
9130 mDisplayManagerService.setDisplayHasContent(displayId, hasUniqueContent,
9131 true /* inTraversal, must call performTraversalInTrans... below */);
9133 getDisplayContentLocked(displayId).stopDimmingIfNeeded();
9135 if (updateAllDrawn) {
9136 updateAllDrawnLocked(displayContent);
9140 if (focusDisplayed) {
9141 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
9144 // Give the display manager a chance to adjust properties
9145 // like display rotation if it needs to.
9146 mDisplayManagerService.performTraversalInTransactionFromWindowManager();
9148 } catch (RuntimeException e) {
9149 Log.wtf(TAG, "Unhandled exception in Window Manager", e);
9151 SurfaceControl.closeTransaction();
9152 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9153 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
9156 final WindowList defaultWindows = defaultDisplay.getWindowList();
9158 // If we are ready to perform an app transition, check through
9159 // all of the app tokens to be shown and see if they are ready
9161 if (mAppTransition.isReady()) {
9162 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
9163 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
9164 defaultDisplay.pendingLayoutChanges);
9167 if (!mAnimator.mAnimating && mAppTransition.isRunning()) {
9168 // We have finished the animation of an app transition. To do
9169 // this, we have delayed a lot of operations like showing and
9170 // hiding apps, moving apps in Z-order, etc. The app token list
9171 // reflects the correct Z-order, but the window list may now
9172 // be out of sync with it. So here we will just rebuild the
9173 // entire app window list. Fun!
9174 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
9175 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
9176 defaultDisplay.pendingLayoutChanges);
9179 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
9180 && !mAppTransition.isReady()) {
9181 // At this point, there was a window with a wallpaper that
9182 // was force hiding other windows behind it, but now it
9183 // is going away. This may be simple -- just animate
9184 // away the wallpaper and its window -- or it may be
9185 // hard -- the wallpaper now needs to be shown behind
9186 // something that was hidden.
9187 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9188 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
9189 defaultDisplay.pendingLayoutChanges);
9191 mInnerFields.mWallpaperForceHidingChanged = false;
9193 if (mInnerFields.mWallpaperMayChange) {
9194 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting");
9195 defaultDisplay.pendingLayoutChanges |=
9196 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9197 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
9198 defaultDisplay.pendingLayoutChanges);
9201 if (mFocusMayChange) {
9202 mFocusMayChange = false;
9203 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
9204 false /*updateInputWindows*/)) {
9205 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
9209 if (needsLayout()) {
9210 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9211 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
9212 defaultDisplay.pendingLayoutChanges);
9215 for (i = mResizingWindows.size() - 1; i >= 0; i--) {
9216 WindowState win = mResizingWindows.get(i);
9217 if (win.mAppFreezing) {
9218 // Don't remove this window until rotation has completed.
9221 final WindowStateAnimator winAnimator = win.mWinAnimator;
9223 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
9224 "Reporting new frame to " + win + ": " + win.mCompatFrame);
9226 boolean configChanged = win.isConfigChanged();
9227 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
9229 Slog.i(TAG, "Sending new config to window " + win + ": "
9230 + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH
9231 + " / " + mCurConfiguration + " / 0x"
9232 + Integer.toHexString(diff));
9234 win.setConfiguration(mCurConfiguration);
9235 if (DEBUG_ORIENTATION &&
9236 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(
9237 TAG, "Resizing " + win + " WITH DRAW PENDING");
9238 final IWindow client = win.mClient;
9239 final Rect frame = win.mFrame;
9240 final Rect overscanInsets = win.mLastOverscanInsets;
9241 final Rect contentInsets = win.mLastContentInsets;
9242 final Rect visibleInsets = win.mLastVisibleInsets;
9243 final boolean reportDraw
9244 = winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING;
9245 final Configuration newConfig = configChanged ? win.mConfiguration : null;
9246 if (win.mClient instanceof IWindow.Stub) {
9247 // To prevent deadlock simulate one-way call if win.mClient is a local object.
9248 mH.post(new Runnable() {
9252 client.resized(frame, overscanInsets, contentInsets,
9253 visibleInsets, reportDraw, newConfig);
9254 } catch (RemoteException e) {
9255 // Not a remote call, RemoteException won't be raised.
9260 client.resized(frame, overscanInsets, contentInsets, visibleInsets, reportDraw,
9263 win.mOverscanInsetsChanged = false;
9264 win.mContentInsetsChanged = false;
9265 win.mVisibleInsetsChanged = false;
9266 winAnimator.mSurfaceResized = false;
9267 } catch (RemoteException e) {
9268 win.mOrientationChanging = false;
9269 win.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
9270 - mDisplayFreezeTime);
9272 mResizingWindows.remove(i);
9275 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
9276 "With display frozen, orientationChangeComplete="
9277 + mInnerFields.mOrientationChangeComplete);
9278 if (mInnerFields.mOrientationChangeComplete) {
9279 if (mWindowsFreezingScreen) {
9280 mWindowsFreezingScreen = false;
9281 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource;
9282 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9284 stopFreezingDisplayLocked();
9287 // Destroy the surface of any windows that are no longer visible.
9288 boolean wallpaperDestroyed = false;
9289 i = mDestroySurface.size();
9293 WindowState win = mDestroySurface.get(i);
9294 win.mDestroying = false;
9295 if (mInputMethodWindow == win) {
9296 mInputMethodWindow = null;
9298 if (win == mWallpaperTarget) {
9299 wallpaperDestroyed = true;
9301 win.mWinAnimator.destroySurfaceLocked();
9303 mDestroySurface.clear();
9306 // Time to remove any exiting tokens?
9307 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9308 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9309 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
9310 for (i = exitingTokens.size() - 1; i >= 0; i--) {
9311 WindowToken token = exitingTokens.get(i);
9312 if (!token.hasVisible) {
9313 exitingTokens.remove(i);
9314 if (token.windowType == TYPE_WALLPAPER) {
9315 mWallpaperTokens.remove(token);
9320 // Time to remove any exiting applications?
9321 AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
9322 for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
9323 AppWindowToken token = exitingAppTokens.get(i);
9324 if (!token.hasVisible && !mClosingApps.contains(token)) {
9325 // Make sure there is no animation running on this token,
9326 // so any windows associated with it will be removed as
9327 // soon as their animations are complete
9328 token.mAppAnimator.clearAnimation();
9329 token.mAppAnimator.animating = false;
9330 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
9331 "performLayout: App token exiting now removed" + token);
9332 final Task task = mTaskIdToTask.get(token.groupId);
9333 if (task != null && task.removeAppToken(token)) {
9334 mTaskIdToTask.delete(token.groupId);
9336 exitingAppTokens.remove(i);
9341 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
9342 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
9344 mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
9345 } catch (RemoteException e) {
9348 mRelayoutWhileAnimating.clear();
9351 if (wallpaperDestroyed) {
9352 defaultDisplay.pendingLayoutChanges |=
9353 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9354 defaultDisplay.layoutNeeded = true;
9357 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9358 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9359 if (displayContent.pendingLayoutChanges != 0) {
9360 displayContent.layoutNeeded = true;
9364 // Finally update all input windows now that the window changes have stabilized.
9365 mInputMonitor.updateInputWindowsLw(true /*force*/);
9367 setHoldScreenLocked(mInnerFields.mHoldScreen);
9368 if (!mDisplayFrozen) {
9369 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
9370 mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1);
9372 mPowerManager.setScreenBrightnessOverrideFromWindowManager(
9373 toBrightnessOverride(mInnerFields.mScreenBrightness));
9375 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
9376 mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1);
9378 mPowerManager.setButtonBrightnessOverrideFromWindowManager(
9379 toBrightnessOverride(mInnerFields.mButtonBrightness));
9381 mPowerManager.setUserActivityTimeoutOverrideFromWindowManager(
9382 mInnerFields.mUserActivityTimeout);
9385 if (mTurnOnScreen) {
9386 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
9387 mPowerManager.wakeUp(SystemClock.uptimeMillis());
9388 mTurnOnScreen = false;
9391 if (mInnerFields.mUpdateRotation) {
9392 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
9393 if (updateRotationUncheckedLocked(false)) {
9394 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9396 mInnerFields.mUpdateRotation = false;
9400 if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded
9401 && !mInnerFields.mUpdateRotation) {
9402 checkDrawnWindowsLocked();
9405 final int N = mPendingRemove.size();
9407 if (mPendingRemoveTmp.length < N) {
9408 mPendingRemoveTmp = new WindowState[N+10];
9410 mPendingRemove.toArray(mPendingRemoveTmp);
9411 mPendingRemove.clear();
9412 DisplayContentList displayList = new DisplayContentList();
9413 for (i = 0; i < N; i++) {
9414 WindowState w = mPendingRemoveTmp[i];
9415 removeWindowInnerLocked(w.mSession, w);
9416 if (!displayList.contains(w.mDisplayContent)) {
9417 displayList.add(w.mDisplayContent);
9421 for (DisplayContent displayContent : displayList) {
9422 assignLayersLocked(displayContent.getWindowList());
9423 displayContent.layoutNeeded = true;
9427 setFocusedStackFrame();
9429 // Check to see if we are now in a state where the screen should
9430 // be enabled, because the window obscured flags have changed.
9431 enableScreenIfNeededLocked();
9433 scheduleAnimationLocked();
9435 if (DEBUG_WINDOW_TRACE) {
9436 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
9437 + mAnimator.mAnimating);
9441 private int toBrightnessOverride(float value) {
9442 return (int)(value * PowerManager.BRIGHTNESS_ON);
9445 void checkDrawnWindowsLocked() {
9446 if (mWaitingForDrawn.size() > 0) {
9447 for (int j=mWaitingForDrawn.size()-1; j>=0; j--) {
9448 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j);
9449 WindowState win = pair.first;
9450 //Slog.i(TAG, "Waiting for drawn " + win + ": removed="
9451 // + win.mRemoved + " visible=" + win.isVisibleLw()
9452 // + " shown=" + win.mSurfaceShown);
9454 // Window has been removed; no draw will now happen, so stop waiting.
9455 Slog.w(TAG, "Aborted waiting for drawn: " + pair.first);
9457 pair.second.sendResult(null);
9458 } catch (RemoteException e) {
9460 mWaitingForDrawn.remove(pair);
9461 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9462 } else if (win.mWinAnimator.mSurfaceShown) {
9463 // Window is now drawn (and shown).
9465 pair.second.sendResult(null);
9466 } catch (RemoteException e) {
9468 mWaitingForDrawn.remove(pair);
9469 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9476 public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
9477 if (token != null && callback != null) {
9478 synchronized (mWindowMap) {
9479 WindowState win = windowForClientLocked(null, token, true);
9481 Pair<WindowState, IRemoteCallback> pair =
9482 new Pair<WindowState, IRemoteCallback>(win, callback);
9483 Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9484 mH.sendMessageDelayed(m, 2000);
9485 mWaitingForDrawn.add(pair);
9486 checkDrawnWindowsLocked();
9489 Slog.i(TAG, "waitForWindowDrawn: win null");
9495 void setHoldScreenLocked(final Session newHoldScreen) {
9496 final boolean hold = newHoldScreen != null;
9498 if (hold && mHoldingScreenOn != newHoldScreen) {
9499 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
9501 mHoldingScreenOn = newHoldScreen;
9503 final boolean state = mHoldingScreenWakeLock.isHeld();
9504 if (hold != state) {
9506 mHoldingScreenWakeLock.acquire();
9507 mPolicy.keepScreenOnStartedLw();
9509 mPolicy.keepScreenOnStoppedLw();
9510 mHoldingScreenWakeLock.release();
9516 public void requestTraversal() {
9517 synchronized (mWindowMap) {
9518 requestTraversalLocked();
9522 void requestTraversalLocked() {
9523 if (!mTraversalScheduled) {
9524 mTraversalScheduled = true;
9525 mH.sendEmptyMessage(H.DO_TRAVERSAL);
9529 /** Note that Locked in this case is on mLayoutToAnim */
9530 void scheduleAnimationLocked() {
9531 if (!mAnimationScheduled) {
9532 mAnimationScheduled = true;
9533 mChoreographer.postCallback(
9534 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
9538 private boolean needsLayout() {
9539 final int numDisplays = mDisplayContents.size();
9540 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9541 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9542 if (displayContent.layoutNeeded) {
9549 boolean copyAnimToLayoutParamsLocked() {
9550 boolean doRequest = false;
9552 final int bulkUpdateParams = mAnimator.mBulkUpdateParams;
9553 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
9554 mInnerFields.mUpdateRotation = true;
9557 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
9558 mInnerFields.mWallpaperMayChange = true;
9561 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
9562 mInnerFields.mWallpaperForceHidingChanged = true;
9565 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
9566 mInnerFields.mOrientationChangeComplete = false;
9568 mInnerFields.mOrientationChangeComplete = true;
9569 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource;
9570 if (mWindowsFreezingScreen) {
9574 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
9575 mTurnOnScreen = true;
9577 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) {
9578 mInnerFields.mWallpaperActionPending = true;
9584 /** If a window that has an animation specifying a colored background and the current wallpaper
9585 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
9586 * suddenly disappear. */
9587 int adjustAnimationBackground(WindowStateAnimator winAnimator) {
9588 WindowList windows = winAnimator.mWin.getWindowList();
9589 for (int i = windows.size() - 1; i >= 0; --i) {
9590 WindowState testWin = windows.get(i);
9591 if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
9592 return testWin.mWinAnimator.mAnimLayer;
9595 return winAnimator.mAnimLayer;
9598 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
9600 final SurfaceControl surface = winAnimator.mSurfaceControl;
9601 boolean leakedSurface = false;
9602 boolean killedApps = false;
9604 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
9605 winAnimator.mSession.mPid, operation);
9607 if (mForceRemoves == null) {
9608 mForceRemoves = new ArrayList<WindowState>();
9611 long callingIdentity = Binder.clearCallingIdentity();
9613 // There was some problem... first, do a sanity check of the
9614 // window list to make sure we haven't left any dangling surfaces
9617 Slog.i(TAG, "Out of memory for surface! Looking for leaks...");
9618 final int numDisplays = mDisplayContents.size();
9619 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9620 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9621 final int numWindows = windows.size();
9622 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9623 final WindowState ws = windows.get(winNdx);
9624 WindowStateAnimator wsa = ws.mWinAnimator;
9625 if (wsa.mSurfaceControl != null) {
9626 if (!mSessions.contains(wsa.mSession)) {
9627 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
9628 + ws + " surface=" + wsa.mSurfaceControl
9629 + " token=" + ws.mToken
9630 + " pid=" + ws.mSession.mPid
9631 + " uid=" + ws.mSession.mUid);
9632 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9633 wsa.mSurfaceControl.destroy();
9634 wsa.mSurfaceShown = false;
9635 wsa.mSurfaceControl = null;
9636 ws.mHasSurface = false;
9637 mForceRemoves.add(ws);
9638 leakedSurface = true;
9639 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
9640 Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
9641 + ws + " surface=" + wsa.mSurfaceControl
9642 + " token=" + ws.mAppToken);
9643 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9644 wsa.mSurfaceControl.destroy();
9645 wsa.mSurfaceShown = false;
9646 wsa.mSurfaceControl = null;
9647 ws.mHasSurface = false;
9648 leakedSurface = true;
9654 if (!leakedSurface) {
9655 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
9656 SparseIntArray pidCandidates = new SparseIntArray();
9657 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9658 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9659 final int numWindows = windows.size();
9660 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9661 final WindowState ws = windows.get(winNdx);
9662 if (mForceRemoves.contains(ws)) {
9665 WindowStateAnimator wsa = ws.mWinAnimator;
9666 if (wsa.mSurfaceControl != null) {
9667 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
9670 if (pidCandidates.size() > 0) {
9671 int[] pids = new int[pidCandidates.size()];
9672 for (int i=0; i<pids.length; i++) {
9673 pids[i] = pidCandidates.keyAt(i);
9676 if (mActivityManager.killPids(pids, "Free memory", secure)) {
9679 } catch (RemoteException e) {
9685 if (leakedSurface || killedApps) {
9686 // We managed to reclaim some memory, so get rid of the trouble
9687 // surface and ask the app to request another one.
9688 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
9689 if (surface != null) {
9690 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
9691 "RECOVER DESTROY", null);
9693 winAnimator.mSurfaceShown = false;
9694 winAnimator.mSurfaceControl = null;
9695 winAnimator.mWin.mHasSurface = false;
9696 scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken);
9700 winAnimator.mWin.mClient.dispatchGetNewSurface();
9701 } catch (RemoteException e) {
9705 Binder.restoreCallingIdentity(callingIdentity);
9708 return leakedSurface || killedApps;
9711 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
9712 WindowState newFocus = computeFocusedWindowLocked();
9713 if (mCurrentFocus != newFocus) {
9714 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
9715 // This check makes sure that we don't already have the focus
9716 // change message pending.
9717 mH.removeMessages(H.REPORT_FOCUS_CHANGE);
9718 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
9719 // TODO(multidisplay): Focused windows on default display only.
9720 final DisplayContent displayContent = getDefaultDisplayContentLocked();
9721 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
9722 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
9723 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
9724 if (imWindowChanged) {
9725 displayContent.layoutNeeded = true;
9726 newFocus = computeFocusedWindowLocked();
9729 if (true || DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " +
9730 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
9731 final WindowState oldFocus = mCurrentFocus;
9732 mCurrentFocus = newFocus;
9733 mLosingFocus.remove(newFocus);
9734 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
9736 if (imWindowChanged && oldFocus != mInputMethodWindow) {
9737 // Focus of the input method window changed. Perform layout if needed.
9738 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9739 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9740 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9741 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
9742 // Client will do the layout, but we need to assign layers
9743 // for handleNewWindowLocked() below.
9744 assignLayersLocked(displayContent.getWindowList());
9748 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9749 // The change in focus caused us to need to do a layout. Okay.
9750 displayContent.layoutNeeded = true;
9751 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9752 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9756 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
9757 // If we defer assigning layers, then the caller is responsible for
9759 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows);
9762 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
9768 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) {
9769 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
9772 private WindowState computeFocusedWindowLocked() {
9773 if (mAnimator.mUniverseBackground != null
9774 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
9775 return mAnimator.mUniverseBackground.mWin;
9778 final int displayCount = mDisplayContents.size();
9779 for (int i = 0; i < displayCount; i++) {
9780 final DisplayContent displayContent = mDisplayContents.valueAt(i);
9781 WindowState win = findFocusedWindowLocked(displayContent);
9789 private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
9790 final WindowList windows = displayContent.getWindowList();
9791 for (int i = windows.size() - 1; i >= 0; i--) {
9792 final WindowState win = windows.get(i);
9794 if (localLOGV || DEBUG_FOCUS) Slog.v(
9795 TAG, "Looking for focus: " + i
9797 + ", flags=" + win.mAttrs.flags
9798 + ", canReceive=" + win.canReceiveKeys());
9800 AppWindowToken wtoken = win.mAppToken;
9802 // If this window's application has been removed, just skip it.
9803 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
9804 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because "
9805 + (wtoken.removed ? "removed" : "sendingToBottom"));
9809 if (!win.canReceiveKeys()) {
9813 // Descend through all of the app tokens and find the first that either matches
9814 // win.mAppToken (return win) or mFocusedApp (return null).
9815 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
9816 mFocusedApp != null) {
9817 ArrayList<Task> tasks = displayContent.getTasks();
9818 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9819 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9820 int tokenNdx = tokens.size() - 1;
9821 for ( ; tokenNdx >= 0; --tokenNdx) {
9822 final AppWindowToken token = tokens.get(tokenNdx);
9823 if (wtoken == token) {
9826 if (mFocusedApp == token) {
9827 // Whoops, we are below the focused app... no focus for you!
9828 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG,
9829 "findFocusedWindow: Reached focused app=" + mFocusedApp);
9833 if (tokenNdx >= 0) {
9834 // Early exit from loop, must have found the matching token.
9840 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i +
9845 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows.");
9849 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
9850 if (mDisplayFrozen) {
9854 if (!mDisplayReady || !mPolicy.isScreenOnFully()) {
9855 // No need to freeze the screen before the system is ready or if
9856 // the screen is off.
9860 mScreenFrozenLock.acquire();
9862 mDisplayFrozen = true;
9863 mDisplayFreezeTime = SystemClock.elapsedRealtime();
9864 mLastFinishedFreezeSource = null;
9866 mInputMonitor.freezeInputDispatchingLw();
9868 // Clear the last input window -- that is just used for
9869 // clean transitions between IMEs, and if we are freezing
9870 // the screen then the whole world is changing behind the scenes.
9871 mPolicy.setLastInputMethodWindowLw(null, null);
9873 if (mAppTransition.isTransitionSet()) {
9874 mAppTransition.freeze();
9877 if (PROFILE_ORIENTATION) {
9878 File file = new File("/data/system/frozen");
9879 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
9882 if (CUSTOM_SCREEN_ROTATION) {
9883 mExitAnimId = exitAnim;
9884 mEnterAnimId = enterAnim;
9885 final DisplayContent displayContent = getDefaultDisplayContentLocked();
9886 final int displayId = displayContent.getDisplayId();
9887 ScreenRotationAnimation screenRotationAnimation =
9888 mAnimator.getScreenRotationAnimationLocked(displayId);
9889 if (screenRotationAnimation != null) {
9890 screenRotationAnimation.kill();
9893 // TODO(multidisplay): rotation on main screen only.
9894 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
9895 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced());
9896 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9900 private void stopFreezingDisplayLocked() {
9901 if (!mDisplayFrozen) {
9905 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
9906 || mClientFreezingScreen) {
9907 if (DEBUG_ORIENTATION) Slog.d(TAG,
9908 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
9909 + ", mAppsFreezingScreen=" + mAppsFreezingScreen
9910 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
9911 + ", mClientFreezingScreen=" + mClientFreezingScreen);
9915 mDisplayFrozen = false;
9916 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
9917 StringBuilder sb = new StringBuilder(128);
9918 sb.append("Screen frozen for ");
9919 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
9920 if (mLastFinishedFreezeSource != null) {
9921 sb.append(" due to ");
9922 sb.append(mLastFinishedFreezeSource);
9924 Slog.i(TAG, sb.toString());
9925 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
9926 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
9927 if (PROFILE_ORIENTATION) {
9928 Debug.stopMethodTracing();
9931 boolean updateRotation = false;
9933 final DisplayContent displayContent = getDefaultDisplayContentLocked();
9934 final int displayId = displayContent.getDisplayId();
9935 ScreenRotationAnimation screenRotationAnimation =
9936 mAnimator.getScreenRotationAnimationLocked(displayId);
9937 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
9938 && screenRotationAnimation.hasScreenshot()) {
9939 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
9940 // TODO(multidisplay): rotation on main screen only.
9941 DisplayInfo displayInfo = displayContent.getDisplayInfo();
9942 // Get rotation animation again, with new top window
9943 boolean isDimming = displayContent.isDimming();
9944 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
9945 mExitAnimId = mEnterAnimId = 0;
9947 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
9948 mTransitionAnimationScale, displayInfo.logicalWidth,
9949 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
9950 scheduleAnimationLocked();
9952 screenRotationAnimation.kill();
9953 screenRotationAnimation = null;
9954 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9955 updateRotation = true;
9958 if (screenRotationAnimation != null) {
9959 screenRotationAnimation.kill();
9960 screenRotationAnimation = null;
9961 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9963 updateRotation = true;
9966 mInputMonitor.thawInputDispatchingLw();
9968 boolean configChanged;
9970 // While the display is frozen we don't re-compute the orientation
9971 // to avoid inconsistent states. However, something interesting
9972 // could have actually changed during that time so re-evaluate it
9973 // now to catch that.
9974 configChanged = updateOrientationFromAppTokensLocked(false);
9976 // A little kludge: a lot could have happened while the
9977 // display was frozen, so now that we are coming back we
9978 // do a gc so that any remote references the system
9979 // processes holds on others can be released if they are
9980 // no longer needed.
9981 mH.removeMessages(H.FORCE_GC);
9982 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
9984 mScreenFrozenLock.release();
9986 if (updateRotation) {
9987 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
9988 configChanged |= updateRotationUncheckedLocked(false);
9991 if (configChanged) {
9992 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9996 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
9997 DisplayMetrics dm) {
9998 if (index < tokens.length) {
9999 String str = tokens[index];
10000 if (str != null && str.length() > 0) {
10002 int val = Integer.parseInt(str);
10004 } catch (Exception e) {
10008 if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
10011 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
10015 void createWatermarkInTransaction() {
10016 if (mWatermark != null) {
10020 File file = new File("/system/etc/setup.conf");
10021 FileInputStream in = null;
10022 DataInputStream ind = null;
10024 in = new FileInputStream(file);
10025 ind = new DataInputStream(in);
10026 String line = ind.readLine();
10027 if (line != null) {
10028 String[] toks = line.split("%");
10029 if (toks != null && toks.length > 0) {
10030 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
10031 mRealDisplayMetrics, mFxSession, toks);
10034 } catch (FileNotFoundException e) {
10035 } catch (IOException e) {
10040 } catch (IOException e) {
10042 } else if (in != null) {
10045 } catch (IOException e) {
10052 public void statusBarVisibilityChanged(int visibility) {
10053 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
10054 != PackageManager.PERMISSION_GRANTED) {
10055 throw new SecurityException("Caller does not hold permission "
10056 + android.Manifest.permission.STATUS_BAR);
10059 synchronized (mWindowMap) {
10060 mLastStatusBarVisibility = visibility;
10061 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
10062 updateStatusBarVisibilityLocked(visibility);
10066 // TOOD(multidisplay): StatusBar on multiple screens?
10067 void updateStatusBarVisibilityLocked(int visibility) {
10068 mInputManager.setSystemUiVisibility(visibility);
10069 final WindowList windows = getDefaultWindowListLocked();
10070 final int N = windows.size();
10071 for (int i = 0; i < N; i++) {
10072 WindowState ws = windows.get(i);
10074 int curValue = ws.mSystemUiVisibility;
10075 int diff = curValue ^ visibility;
10076 // We are only interested in differences of one of the
10077 // clearable flags...
10078 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
10079 // ...if it has actually been cleared.
10080 diff &= ~visibility;
10081 int newValue = (curValue&~diff) | (visibility&diff);
10082 if (newValue != curValue) {
10084 ws.mSystemUiVisibility = newValue;
10086 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
10087 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
10088 visibility, newValue, diff);
10090 } catch (RemoteException e) {
10097 public void reevaluateStatusBarVisibility() {
10098 synchronized (mWindowMap) {
10099 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
10100 updateStatusBarVisibilityLocked(visibility);
10101 performLayoutAndPlaceSurfacesLocked();
10106 public FakeWindow addFakeWindow(Looper looper,
10107 InputEventReceiver.Factory inputEventReceiverFactory,
10108 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags,
10109 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) {
10110 synchronized (mWindowMap) {
10111 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
10113 layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys,
10114 hasFocus, touchFullscreen);
10116 while (i<mFakeWindows.size()) {
10117 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
10121 mFakeWindows.add(i, fw);
10122 mInputMonitor.updateInputWindowsLw(true);
10127 boolean removeFakeWindowLocked(FakeWindow window) {
10128 synchronized (mWindowMap) {
10129 if (mFakeWindows.remove(window)) {
10130 mInputMonitor.updateInputWindowsLw(true);
10137 // It is assumed that this method is called only by InputMethodManagerService.
10138 public void saveLastInputMethodWindowForTransition() {
10139 synchronized (mWindowMap) {
10140 // TODO(multidisplay): Pass in the displayID.
10141 DisplayContent displayContent = getDefaultDisplayContentLocked();
10142 if (mInputMethodWindow != null) {
10143 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
10149 public boolean hasNavigationBar() {
10150 return mPolicy.hasNavigationBar();
10154 public void lockNow(Bundle options) {
10155 mPolicy.lockNow(options);
10159 public boolean isSafeModeEnabled() {
10163 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10164 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
10165 mPolicy.dump(" ", pw, args);
10168 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10169 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
10170 mAnimator.dumpLocked(pw, " ", dumpAll);
10173 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
10174 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
10175 if (mTokenMap.size() > 0) {
10176 pw.println(" All tokens:");
10177 Iterator<WindowToken> it = mTokenMap.values().iterator();
10178 while (it.hasNext()) {
10179 WindowToken token = it.next();
10180 pw.print(" "); pw.print(token);
10183 token.dump(pw, " ");
10189 if (mWallpaperTokens.size() > 0) {
10191 pw.println(" Wallpaper tokens:");
10192 for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
10193 WindowToken token = mWallpaperTokens.get(i);
10194 pw.print(" Wallpaper #"); pw.print(i);
10195 pw.print(' '); pw.print(token);
10198 token.dump(pw, " ");
10204 if (mFinishedStarting.size() > 0) {
10206 pw.println(" Finishing start of application tokens:");
10207 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10208 WindowToken token = mFinishedStarting.get(i);
10209 pw.print(" Finished Starting #"); pw.print(i);
10210 pw.print(' '); pw.print(token);
10213 token.dump(pw, " ");
10219 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
10221 if (mOpeningApps.size() > 0) {
10222 pw.print(" mOpeningApps="); pw.println(mOpeningApps);
10224 if (mClosingApps.size() > 0) {
10225 pw.print(" mClosingApps="); pw.println(mClosingApps);
10230 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
10231 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
10232 if (mSessions.size() > 0) {
10233 Iterator<Session> it = mSessions.iterator();
10234 while (it.hasNext()) {
10235 Session s = it.next();
10236 pw.print(" Session "); pw.print(s); pw.println(':');
10242 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
10243 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
10244 if (mDisplayReady) {
10245 final int numDisplays = mDisplayContents.size();
10246 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10247 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10248 displayContent.dump(" ", pw);
10251 pw.println(" NO DISPLAY");
10255 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
10256 ArrayList<WindowState> windows) {
10257 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
10258 dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
10261 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
10262 ArrayList<WindowState> windows) {
10263 final int numDisplays = mDisplayContents.size();
10264 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10265 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
10266 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10267 final WindowState w = windowList.get(winNdx);
10268 if (windows == null || windows.contains(w)) {
10269 pw.print(" Window #"); pw.print(winNdx); pw.print(' ');
10270 pw.print(w); pw.println(":");
10271 w.dump(pw, " ", dumpAll || windows != null);
10275 if (mInputMethodDialogs.size() > 0) {
10277 pw.println(" Input method dialogs:");
10278 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10279 WindowState w = mInputMethodDialogs.get(i);
10280 if (windows == null || windows.contains(w)) {
10281 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
10285 if (mPendingRemove.size() > 0) {
10287 pw.println(" Remove pending for:");
10288 for (int i=mPendingRemove.size()-1; i>=0; i--) {
10289 WindowState w = mPendingRemove.get(i);
10290 if (windows == null || windows.contains(w)) {
10291 pw.print(" Remove #"); pw.print(i); pw.print(' ');
10295 w.dump(pw, " ", true);
10302 if (mForceRemoves != null && mForceRemoves.size() > 0) {
10304 pw.println(" Windows force removing:");
10305 for (int i=mForceRemoves.size()-1; i>=0; i--) {
10306 WindowState w = mForceRemoves.get(i);
10307 pw.print(" Removing #"); pw.print(i); pw.print(' ');
10311 w.dump(pw, " ", true);
10317 if (mDestroySurface.size() > 0) {
10319 pw.println(" Windows waiting to destroy their surface:");
10320 for (int i=mDestroySurface.size()-1; i>=0; i--) {
10321 WindowState w = mDestroySurface.get(i);
10322 if (windows == null || windows.contains(w)) {
10323 pw.print(" Destroy #"); pw.print(i); pw.print(' ');
10327 w.dump(pw, " ", true);
10334 if (mLosingFocus.size() > 0) {
10336 pw.println(" Windows losing focus:");
10337 for (int i=mLosingFocus.size()-1; i>=0; i--) {
10338 WindowState w = mLosingFocus.get(i);
10339 if (windows == null || windows.contains(w)) {
10340 pw.print(" Losing #"); pw.print(i); pw.print(' ');
10344 w.dump(pw, " ", true);
10351 if (mResizingWindows.size() > 0) {
10353 pw.println(" Windows waiting to resize:");
10354 for (int i=mResizingWindows.size()-1; i>=0; i--) {
10355 WindowState w = mResizingWindows.get(i);
10356 if (windows == null || windows.contains(w)) {
10357 pw.print(" Resizing #"); pw.print(i); pw.print(' ');
10361 w.dump(pw, " ", true);
10368 if (mWaitingForDrawn.size() > 0) {
10370 pw.println(" Clients waiting for these windows to be drawn:");
10371 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
10372 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i);
10373 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first);
10374 pw.print(": "); pw.println(pair.second);
10378 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration);
10379 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
10380 if (mLastFocus != mCurrentFocus) {
10381 pw.print(" mLastFocus="); pw.println(mLastFocus);
10383 pw.print(" mFocusedApp="); pw.println(mFocusedApp);
10384 if (mInputMethodTarget != null) {
10385 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
10387 pw.print(" mInTouchMode="); pw.print(mInTouchMode);
10388 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
10389 pw.print(" mLastDisplayFreezeDuration=");
10390 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
10391 if ( mLastFinishedFreezeSource != null) {
10392 pw.print(" due to ");
10393 pw.print(mLastFinishedFreezeSource);
10397 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer);
10398 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
10399 if (mLastStatusBarVisibility != 0) {
10400 pw.print(" mLastStatusBarVisibility=0x");
10401 pw.println(Integer.toHexString(mLastStatusBarVisibility));
10403 if (mInputMethodWindow != null) {
10404 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
10406 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget);
10407 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
10408 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
10409 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
10411 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX);
10412 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
10413 if (mInputMethodAnimLayerAdjustment != 0 ||
10414 mWallpaperAnimLayerAdjustment != 0) {
10415 pw.print(" mInputMethodAnimLayerAdjustment=");
10416 pw.print(mInputMethodAnimLayerAdjustment);
10417 pw.print(" mWallpaperAnimLayerAdjustment=");
10418 pw.println(mWallpaperAnimLayerAdjustment);
10420 pw.print(" mSystemBooted="); pw.print(mSystemBooted);
10421 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10422 if (needsLayout()) {
10423 pw.print(" layoutNeeded on displays=");
10424 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10425 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10426 if (displayContent.layoutNeeded) {
10427 pw.print(displayContent.getDisplayId());
10432 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence);
10433 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
10434 pw.print(" windows="); pw.print(mWindowsFreezingScreen);
10435 pw.print(" client="); pw.print(mClientFreezingScreen);
10436 pw.print(" apps="); pw.print(mAppsFreezingScreen);
10437 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
10438 pw.print(" mRotation="); pw.print(mRotation);
10439 pw.print(" mAltOrientation="); pw.println(mAltOrientation);
10440 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
10441 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
10442 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
10443 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
10444 pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale);
10445 pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale);
10446 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled);
10447 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
10448 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
10449 pw.println(" mLayoutToAnim:");
10450 mAppTransition.dump(pw);
10454 boolean dumpWindows(PrintWriter pw, String name, String[] args,
10455 int opti, boolean dumpAll) {
10456 WindowList windows = new WindowList();
10457 if ("visible".equals(name)) {
10458 synchronized(mWindowMap) {
10459 final int numDisplays = mDisplayContents.size();
10460 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10461 final WindowList windowList =
10462 mDisplayContents.valueAt(displayNdx).getWindowList();
10463 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10464 final WindowState w = windowList.get(winNdx);
10465 if (w.mWinAnimator.mSurfaceShown) {
10473 // See if this is an object ID.
10475 objectId = Integer.parseInt(name, 16);
10477 } catch (RuntimeException e) {
10479 synchronized(mWindowMap) {
10480 final int numDisplays = mDisplayContents.size();
10481 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10482 final WindowList windowList =
10483 mDisplayContents.valueAt(displayNdx).getWindowList();
10484 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10485 final WindowState w = windowList.get(winNdx);
10486 if (name != null) {
10487 if (w.mAttrs.getTitle().toString().contains(name)) {
10490 } else if (System.identityHashCode(w) == objectId) {
10498 if (windows.size() <= 0) {
10502 synchronized(mWindowMap) {
10503 dumpWindowsLocked(pw, dumpAll, windows);
10508 void dumpLastANRLocked(PrintWriter pw) {
10509 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
10510 if (mLastANRState == null) {
10511 pw.println(" <no ANR has occurred since boot>");
10513 pw.println(mLastANRState);
10518 * Saves information about the state of the window manager at
10519 * the time an ANR occurred before anything else in the system changes
10522 * @param appWindowToken The application that ANR'd, may be null.
10523 * @param windowState The window that ANR'd, may be null.
10524 * @param reason The reason for the ANR, may be null.
10526 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
10528 StringWriter sw = new StringWriter();
10529 PrintWriter pw = new FastPrintWriter(sw, false, 1024);
10530 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date()));
10531 if (appWindowToken != null) {
10532 pw.println(" Application at fault: " + appWindowToken.stringName);
10534 if (windowState != null) {
10535 pw.println(" Window at fault: " + windowState.mAttrs.getTitle());
10537 if (reason != null) {
10538 pw.println(" Reason: " + reason);
10541 dumpWindowsNoHeaderLocked(pw, true, null);
10543 mLastANRState = sw.toString();
10547 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10548 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
10549 != PackageManager.PERMISSION_GRANTED) {
10550 pw.println("Permission Denial: can't dump WindowManager from from pid="
10551 + Binder.getCallingPid()
10552 + ", uid=" + Binder.getCallingUid());
10556 boolean dumpAll = false;
10559 while (opti < args.length) {
10560 String opt = args[opti];
10561 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10565 if ("-a".equals(opt)) {
10567 } else if ("-h".equals(opt)) {
10568 pw.println("Window manager dump options:");
10569 pw.println(" [-a] [-h] [cmd] ...");
10570 pw.println(" cmd may be one of:");
10571 pw.println(" l[astanr]: last ANR information");
10572 pw.println(" p[policy]: policy state");
10573 pw.println(" a[animator]: animator state");
10574 pw.println(" s[essions]: active sessions");
10575 pw.println(" d[isplays]: active display contents");
10576 pw.println(" t[okens]: token list");
10577 pw.println(" w[indows]: window list");
10578 pw.println(" cmd may also be a NAME to dump windows. NAME may");
10579 pw.println(" be a partial substring in a window name, a");
10580 pw.println(" Window hex object identifier, or");
10581 pw.println(" \"all\" for all windows, or");
10582 pw.println(" \"visible\" for the visible windows.");
10583 pw.println(" -a: include all available server state.");
10586 pw.println("Unknown argument: " + opt + "; use -h for help");
10590 // Is the caller requesting to dump a particular piece of data?
10591 if (opti < args.length) {
10592 String cmd = args[opti];
10594 if ("lastanr".equals(cmd) || "l".equals(cmd)) {
10595 synchronized(mWindowMap) {
10596 dumpLastANRLocked(pw);
10599 } else if ("policy".equals(cmd) || "p".equals(cmd)) {
10600 synchronized(mWindowMap) {
10601 dumpPolicyLocked(pw, args, true);
10604 } else if ("animator".equals(cmd) || "a".equals(cmd)) {
10605 synchronized(mWindowMap) {
10606 dumpAnimatorLocked(pw, args, true);
10609 } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
10610 synchronized(mWindowMap) {
10611 dumpSessionsLocked(pw, true);
10614 } else if ("displays".equals(cmd) || "d".equals(cmd)) {
10615 synchronized(mWindowMap) {
10616 dumpDisplayContentsLocked(pw, true);
10619 } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
10620 synchronized(mWindowMap) {
10621 dumpTokensLocked(pw, true);
10624 } else if ("windows".equals(cmd) || "w".equals(cmd)) {
10625 synchronized(mWindowMap) {
10626 dumpWindowsLocked(pw, true, null);
10629 } else if ("all".equals(cmd) || "a".equals(cmd)) {
10630 synchronized(mWindowMap) {
10631 dumpWindowsLocked(pw, true, null);
10635 // Dumping a single name?
10636 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
10637 pw.println("Bad window command, or no windows match: " + cmd);
10638 pw.println("Use -h for help.");
10644 synchronized(mWindowMap) {
10647 pw.println("-------------------------------------------------------------------------------");
10649 dumpLastANRLocked(pw);
10652 pw.println("-------------------------------------------------------------------------------");
10654 dumpPolicyLocked(pw, args, dumpAll);
10657 pw.println("-------------------------------------------------------------------------------");
10659 dumpAnimatorLocked(pw, args, dumpAll);
10662 pw.println("-------------------------------------------------------------------------------");
10664 dumpSessionsLocked(pw, dumpAll);
10667 pw.println("-------------------------------------------------------------------------------");
10669 dumpDisplayContentsLocked(pw, dumpAll);
10672 pw.println("-------------------------------------------------------------------------------");
10674 dumpTokensLocked(pw, dumpAll);
10677 pw.println("-------------------------------------------------------------------------------");
10679 dumpWindowsLocked(pw, dumpAll, null);
10683 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
10685 public void monitor() {
10686 synchronized (mWindowMap) { }
10689 public interface OnHardKeyboardStatusChangeListener {
10690 public void onHardKeyboardStatusChange(boolean available, boolean enabled);
10693 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
10694 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
10695 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
10696 Integer.toHexString(pendingLayoutChanges));
10700 private DisplayContent newDisplayContentLocked(final Display display) {
10701 DisplayContent displayContent = new DisplayContent(display, this);
10702 final int displayId = display.getDisplayId();
10703 mDisplayContents.put(displayId, displayContent);
10705 DisplayInfo displayInfo = displayContent.getDisplayInfo();
10706 final Rect rect = new Rect();
10707 mDisplaySettings.getOverscanLocked(displayInfo.name, rect);
10708 synchronized (displayContent.mDisplaySizeLock) {
10709 displayInfo.overscanLeft = rect.left;
10710 displayInfo.overscanTop = rect.top;
10711 displayInfo.overscanRight = rect.right;
10712 displayInfo.overscanBottom = rect.bottom;
10713 mDisplayManagerService.setDisplayInfoOverrideFromWindowManager(
10714 displayId, displayInfo);
10716 configureDisplayPolicyLocked(displayContent);
10718 // TODO: Create an input channel for each display with touch capability.
10719 if (displayId == Display.DEFAULT_DISPLAY) {
10720 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent);
10721 registerPointerEventListener(displayContent.mTapDetector);
10724 return displayContent;
10727 public void createDisplayContentLocked(final Display display) {
10728 if (display == null) {
10729 throw new IllegalArgumentException("getDisplayContent: display must not be null");
10731 getDisplayContentLocked(display.getDisplayId());
10735 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
10736 * there is a Display for the displayId.
10737 * @param displayId The display the caller is interested in.
10738 * @return The DisplayContent associated with displayId or null if there is no Display for it.
10740 public DisplayContent getDisplayContentLocked(final int displayId) {
10741 DisplayContent displayContent = mDisplayContents.get(displayId);
10742 if (displayContent == null) {
10743 final Display display = mDisplayManager.getDisplay(displayId);
10744 if (display != null) {
10745 displayContent = newDisplayContentLocked(display);
10748 return displayContent;
10751 // There is an inherent assumption that this will never return null.
10752 public DisplayContent getDefaultDisplayContentLocked() {
10753 return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
10756 public WindowList getDefaultWindowListLocked() {
10757 return getDefaultDisplayContentLocked().getWindowList();
10760 public DisplayInfo getDefaultDisplayInfoLocked() {
10761 return getDefaultDisplayContentLocked().getDisplayInfo();
10765 * Return the list of WindowStates associated on the passed display.
10766 * @param display The screen to return windows from.
10767 * @return The list of WindowStates on the screen, or null if the there is no screen.
10769 public WindowList getWindowListLocked(final Display display) {
10770 return getWindowListLocked(display.getDisplayId());
10774 * Return the list of WindowStates associated on the passed display.
10775 * @param displayId The screen to return windows from.
10776 * @return The list of WindowStates on the screen, or null if the there is no screen.
10778 public WindowList getWindowListLocked(final int displayId) {
10779 final DisplayContent displayContent = getDisplayContentLocked(displayId);
10780 return displayContent != null ? displayContent.getWindowList() : null;
10784 public void onDisplayAdded(int displayId) {
10785 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
10788 private void handleDisplayAddedLocked(int displayId) {
10789 final Display display = mDisplayManager.getDisplay(displayId);
10790 if (display != null) {
10791 createDisplayContentLocked(display);
10792 displayReady(displayId);
10797 public void onDisplayRemoved(int displayId) {
10798 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
10801 private void handleDisplayRemovedLocked(int displayId) {
10802 final DisplayContent displayContent = getDisplayContentLocked(displayId);
10803 if (displayContent != null) {
10804 mDisplayContents.delete(displayId);
10805 displayContent.close();
10806 if (displayId == Display.DEFAULT_DISPLAY) {
10807 unregisterPointerEventListener(displayContent.mTapDetector);
10809 WindowList windows = displayContent.getWindowList();
10810 while (!windows.isEmpty()) {
10811 final WindowState win = windows.get(windows.size() - 1);
10812 removeWindowLocked(win.mSession, win);
10815 mAnimator.removeDisplayLocked(displayId);
10819 public void onDisplayChanged(int displayId) {
10820 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
10823 private void handleDisplayChangedLocked(int displayId) {
10824 final DisplayContent displayContent = getDisplayContentLocked(displayId);
10825 if (displayContent != null) {
10826 displayContent.updateDisplayInfo();
10831 public Object getWindowManagerLock() {