blob: 673c609dd7c4bd07a6160a79eb8fc2fb11011594 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
Jorim Jaggia4a58ef2016-01-27 02:10:08 -080019import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -080020import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
Jorim Jaggi2e95a482016-01-14 17:36:55 -080021import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
Chong Zhangf6525ce2016-01-14 17:09:56 -080022import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
23import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
24import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -080025
Romain Guy6b7bd242010-10-06 19:49:23 -070026import android.Manifest;
Chet Haasecca2c982011-05-20 14:34:18 -070027import android.animation.LayoutTransition;
Romain Guy6b7bd242010-10-06 19:49:23 -070028import android.app.ActivityManagerNative;
29import android.content.ClipDescription;
30import android.content.ComponentCallbacks;
31import android.content.Context;
32import android.content.pm.PackageManager;
33import android.content.res.CompatibilityInfo;
34import android.content.res.Configuration;
35import android.content.res.Resources;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.graphics.Canvas;
Alan Viverettefed3f722013-11-14 14:48:20 -080037import android.graphics.Matrix;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.graphics.PixelFormat;
Christopher Tate2c095f32010-10-04 14:13:40 -070039import android.graphics.Point;
Christopher Tatea53146c2010-09-07 11:57:52 -070040import android.graphics.PointF;
Romain Guy6b7bd242010-10-06 19:49:23 -070041import android.graphics.PorterDuff;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.graphics.Rect;
43import android.graphics.Region;
Svetoslav Ganov42138042012-03-20 11:51:39 -070044import android.graphics.drawable.Drawable;
Jeff Brownd912e1f2014-04-11 18:46:22 -070045import android.hardware.display.DisplayManager;
46import android.hardware.display.DisplayManager.DisplayListener;
Jun Mukai347e5d42015-12-03 01:13:31 -080047import android.hardware.input.InputManager;
Romain Guy6b7bd242010-10-06 19:49:23 -070048import android.media.AudioManager;
49import android.os.Binder;
Michael Wright5bd69e62015-05-14 14:48:08 +010050import android.os.Build;
Romain Guy6b7bd242010-10-06 19:49:23 -070051import android.os.Bundle;
52import android.os.Debug;
53import android.os.Handler;
Romain Guy6b7bd242010-10-06 19:49:23 -070054import android.os.Looper;
55import android.os.Message;
56import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.os.Process;
Romain Guy6b7bd242010-10-06 19:49:23 -070058import android.os.RemoteException;
Romain Guy6b7bd242010-10-06 19:49:23 -070059import android.os.SystemClock;
Romain Guy59a12ca2011-06-09 17:48:21 -070060import android.os.SystemProperties;
Jeff Brown481c1572012-03-09 14:41:15 -080061import android.os.Trace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062import android.util.AndroidRuntimeException;
Mitsuru Oshima9189cab2009-06-03 11:19:12 -070063import android.util.DisplayMetrics;
Romain Guy6b7bd242010-10-06 19:49:23 -070064import android.util.Log;
Chet Haase949dbf72010-08-11 18:41:06 -070065import android.util.Slog;
John Reckba6adf62015-02-19 14:36:50 -080066import android.util.TimeUtils;
Dianne Hackborn711e62a2010-11-29 16:38:22 -080067import android.util.TypedValue;
John Reck44fd8d22014-02-26 11:00:11 -080068import android.view.Surface.OutOfResourcesException;
Jeff Browna175a5b2012-02-15 19:18:31 -080069import android.view.View.AttachInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.view.View.MeasureSpec;
svetoslavganov75986cf2009-05-14 22:28:01 -070071import android.view.accessibility.AccessibilityEvent;
72import android.view.accessibility.AccessibilityManager;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070073import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
Chris Craikcce47eb2014-07-16 15:12:15 -070074import android.view.accessibility.AccessibilityManager.HighTextContrastChangeListener;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070075import android.view.accessibility.AccessibilityNodeInfo;
Alan Viverette25acc7e2015-05-19 11:32:08 -070076import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
Svetoslav Ganov02107852011-10-03 17:06:56 -070077import android.view.accessibility.AccessibilityNodeProvider;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070078import android.view.accessibility.IAccessibilityInteractionConnection;
79import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
Dianne Hackborn0f761d62010-11-30 22:06:10 -080080import android.view.animation.AccelerateDecelerateInterpolator;
81import android.view.animation.Interpolator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.view.inputmethod.InputConnection;
83import android.view.inputmethod.InputMethodManager;
84import android.widget.Scroller;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070085
Svetoslav Ganov42138042012-03-20 11:51:39 -070086import com.android.internal.R;
Clara Bayarri75e09792015-07-29 16:20:40 +010087import com.android.internal.os.IResultReceiver;
Svetoslav Ganov758143e2012-08-06 16:40:27 -070088import com.android.internal.os.SomeArgs;
Adam Powell6711f3b2015-05-06 15:57:09 -070089import com.android.internal.policy.PhoneFallbackEventHandler;
Romain Guy6b7bd242010-10-06 19:49:23 -070090import com.android.internal.view.BaseSurfaceHolder;
Romain Guy6b7bd242010-10-06 19:49:23 -070091import com.android.internal.view.RootViewSurfaceTaker;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092
Jeff Brown5182c782013-10-15 20:31:52 -070093import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import java.io.IOException;
95import java.io.OutputStream;
Jeff Brown5182c782013-10-15 20:31:52 -070096import java.io.PrintWriter;
Romain Guy6b7bd242010-10-06 19:49:23 -070097import java.lang.ref.WeakReference;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import java.util.ArrayList;
Chong Zhang8dbd9ad2015-10-09 10:06:11 -070099import java.util.concurrent.CountDownLatch;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700100import java.util.HashSet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102/**
103 * The top of a view hierarchy, implementing the needed protocol between View
104 * and the WindowManager. This is for the most part an internal implementation
Jeff Brown98365d72012-08-19 20:30:52 -0700105 * detail of {@link WindowManagerGlobal}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106 *
107 * {@hide}
108 */
Romain Guy812ccbe2010-06-01 14:07:24 -0700109@SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"})
Jeff Browna175a5b2012-02-15 19:18:31 -0800110public final class ViewRootImpl implements ViewParent,
John Reck51aaf902015-12-02 15:08:07 -0800111 View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {
Dianne Hackborn70a3f672011-08-08 14:32:41 -0700112 private static final String TAG = "ViewRootImpl";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 private static final boolean DBG = false;
Romain Guy812ccbe2010-06-01 14:07:24 -0700114 private static final boolean LOCAL_LOGV = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 /** @noinspection PointlessBooleanExpression*/
116 private static final boolean DEBUG_DRAW = false || LOCAL_LOGV;
117 private static final boolean DEBUG_LAYOUT = false || LOCAL_LOGV;
Dianne Hackborn711e62a2010-11-29 16:38:22 -0800118 private static final boolean DEBUG_DIALOG = false || LOCAL_LOGV;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 private static final boolean DEBUG_INPUT_RESIZE = false || LOCAL_LOGV;
120 private static final boolean DEBUG_ORIENTATION = false || LOCAL_LOGV;
121 private static final boolean DEBUG_TRACKBALL = false || LOCAL_LOGV;
122 private static final boolean DEBUG_IMF = false || LOCAL_LOGV;
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700123 private static final boolean DEBUG_CONFIGURATION = false || LOCAL_LOGV;
Chet Haase2f2022a2011-10-11 06:41:59 -0700124 private static final boolean DEBUG_FPS = false;
Michael Wright06a79252014-05-05 17:45:29 -0700125 private static final boolean DEBUG_INPUT_STAGES = false || LOCAL_LOGV;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126
Romain Guy59a12ca2011-06-09 17:48:21 -0700127 /**
Skuhneb8160872015-09-22 09:51:39 -0700128 * Set to false if we do not want to use the multi threaded renderer. Note that by disabling
129 * this, WindowCallbacks will not fire.
130 */
131 private static final boolean USE_MT_RENDERER = true;
132
133 /**
Romain Guy59a12ca2011-06-09 17:48:21 -0700134 * Set this system property to true to force the view hierarchy to render
135 * at 60 Hz. This can be used to measure the potential framerate.
136 */
Romain Guye9bc11f2013-05-23 12:47:26 -0700137 private static final String PROPERTY_PROFILE_RENDERING = "viewroot.profile_rendering";
Michael Chan53071d62009-05-13 17:29:48 -0700138
Griff Hazena0938022015-03-13 10:01:41 -0700139 // properties used by emulator to determine display shape
Griff Hazena0938022015-03-13 10:01:41 -0700140 public static final String PROPERTY_EMULATOR_WIN_OUTSET_BOTTOM_PX =
141 "ro.emu.win_outset_bottom_px";
Michael Kolb437d3132014-06-20 13:28:44 -0700142
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 /**
144 * Maximum time we allow the user to roll the trackball enough to generate
145 * a key event, before resetting the counters.
146 */
147 static final int MAX_TRACKBALL_DELAY = 250;
148
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100149 private static final int RESIZE_MODE_FREEFORM = 0;
150 private static final int RESIZE_MODE_DOCKED_DIVIDER = 1;
151
Alan Viverettebea0c7da2015-09-01 16:00:20 -0400152 static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153
Skuhneb8160872015-09-22 09:51:39 -0700154 static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList();
Dianne Hackborn2a9094d2010-02-03 19:20:09 -0800155 static boolean sFirstDrawComplete = false;
Craig Mautner8f303ad2013-06-14 11:32:22 -0700156
Skuhneb8160872015-09-22 09:51:39 -0700157 static final ArrayList<ComponentCallbacks> sConfigCallbacks = new ArrayList();
Romain Guy59a12ca2011-06-09 17:48:21 -0700158
Chong Zhangdcee1de2015-10-06 10:26:00 -0700159 final ArrayList<WindowCallbacks> mWindowCallbacks = new ArrayList();
Jeff Brownf9e989d2013-04-04 23:04:03 -0700160 final Context mContext;
Jeff Brown98365d72012-08-19 20:30:52 -0700161 final IWindowSession mWindowSession;
162 final Display mDisplay;
Jeff Brownd912e1f2014-04-11 18:46:22 -0700163 final DisplayManager mDisplayManager;
Dianne Hackbornc2293022013-02-06 23:14:49 -0800164 final String mBasePackageName;
Jeff Brown98365d72012-08-19 20:30:52 -0700165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 final int[] mTmpLocation = new int[2];
Romain Guy8506ab42009-06-11 17:35:47 -0700167
Dianne Hackborn711e62a2010-11-29 16:38:22 -0800168 final TypedValue mTmpValue = new TypedValue();
Jeff Brownf9e989d2013-04-04 23:04:03 -0700169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 final Thread mThread;
171
172 final WindowLeaked mLocation;
173
174 final WindowManager.LayoutParams mWindowAttributes = new WindowManager.LayoutParams();
175
176 final W mWindow;
177
Dianne Hackborn180c4842011-09-13 12:39:25 -0700178 final int mTargetSdkVersion;
179
Dianne Hackborn9a230e02011-10-06 11:51:27 -0700180 int mSeq;
181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 View mView;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700183
184 View mAccessibilityFocusedHost;
185 AccessibilityNodeInfo mAccessibilityFocusedVirtualView;
186
Jun Mukai347e5d42015-12-03 01:13:31 -0800187 // The view which captures mouse input, or null when no one is capturing.
188 View mCapturingView;
189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 int mViewVisibility;
191 boolean mAppVisible = true;
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -0800192 // For recents to freeform transition we need to keep drawing after the app receives information
193 // that it became invisible. This will ignore that information and depend on the decor view
194 // visibility to control drawing. The decor view visibility will get adjusted when the app get
195 // stopped and that's when the app will stop drawing further frames.
196 private boolean mForceDecorViewVisibility = false;
Dianne Hackborn180c4842011-09-13 12:39:25 -0700197 int mOrigWindowType = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198
Alan Viverette64bf97a2015-09-18 16:42:00 -0400199 /** Whether the window had focus during the most recent traversal. */
200 boolean mHadWindowFocus;
201
202 /**
203 * Whether the window lost focus during a previous traversal and has not
204 * yet gained it back. Used to determine whether a WINDOW_STATE_CHANGE
205 * accessibility events should be sent during traversal.
206 */
207 boolean mLostWindowFocus;
208
Dianne Hackbornce418e62011-03-01 14:31:38 -0800209 // Set to true if the owner of this window is in the stopped state,
210 // so the window should no longer be active.
211 boolean mStopped = false;
Craig Mautner8f303ad2013-06-14 11:32:22 -0700212
Daniel Koulomzin087ae472015-12-16 17:52:25 -0500213 // Set to true if the owner of this window is in ambient mode,
214 // which means it won't receive input events.
215 boolean mIsAmbientMode = false;
216
George Mount41725de2015-04-09 08:23:05 -0700217 // Set to true to stop input during an Activity Transition.
218 boolean mPausedForTransition = false;
219
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700220 boolean mLastInCompatMode = false;
221
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700222 SurfaceHolder.Callback2 mSurfaceHolderCallback;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700223 BaseSurfaceHolder mSurfaceHolder;
224 boolean mIsCreating;
225 boolean mDrawingAllowed;
Craig Mautner8f303ad2013-06-14 11:32:22 -0700226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 final Region mTransparentRegion;
228 final Region mPreviousTransparentRegion;
229
230 int mWidth;
231 int mHeight;
Romain Guy7d7b5492011-01-24 16:33:45 -0800232 Rect mDirty;
Romain Guybb93d552009-03-24 21:04:15 -0700233 boolean mIsAnimating;
Romain Guy8506ab42009-06-11 17:35:47 -0700234
Chong Zhang0275e392015-09-17 10:41:44 -0700235 private boolean mDragResizing;
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100236 private int mResizeMode;
Chong Zhang0275e392015-09-17 10:41:44 -0700237 private int mCanvasOffsetX;
238 private int mCanvasOffsetY;
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100239 private boolean mActivityRelaunched;
Chong Zhang0275e392015-09-17 10:41:44 -0700240
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700241 CompatibilityInfo.Translator mTranslator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242
243 final View.AttachInfo mAttachInfo;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700244 InputChannel mInputChannel;
Dianne Hackborn1e4b9f32010-06-23 14:10:57 -0700245 InputQueue.Callback mInputQueueCallback;
246 InputQueue mInputQueue;
Joe Onorato86f67862010-11-05 18:57:34 -0700247 FallbackEventHandler mFallbackEventHandler;
Jeff Brown96e942d2011-11-30 19:55:01 -0800248 Choreographer mChoreographer;
Igor Murashkina86ab6402013-08-30 12:58:36 -0700249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 final Rect mTempRect; // used in the transaction to not thrash the heap.
251 final Rect mVisRect; // used to retrieve visible rect of focused view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252
253 boolean mTraversalScheduled;
Jeff Browne0dbd002012-02-15 19:34:58 -0800254 int mTraversalBarrier;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 boolean mWillDrawSoon;
Craig Mautnerdf2390a2012-08-29 20:59:22 -0700256 /** Set to true while in performTraversals for detecting when die(true) is called from internal
257 * callbacks such as onMeasure, onPreDraw, onDraw and deferring doDie() until later. */
258 boolean mIsInTraversal;
Adrian Roosfa104232014-06-20 16:10:14 -0700259 boolean mApplyInsetsRequested;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 boolean mLayoutRequested;
261 boolean mFirst;
262 boolean mReportNextDraw;
263 boolean mFullRedrawNeeded;
264 boolean mNewSurfaceNeeded;
265 boolean mHasHadWindowFocus;
266 boolean mLastWasImTarget;
Jorim Jaggia4a58ef2016-01-27 02:10:08 -0800267 boolean mForceNextWindowRelayout;
Chong Zhang8dbd9ad2015-10-09 10:06:11 -0700268 CountDownLatch mWindowDrawCountDown;
Jorim Jaggi827e0fa2015-05-07 11:41:41 -0700269
Romain Guy1f59e5c2012-05-06 14:11:16 -0700270 boolean mIsDrawing;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700271 int mLastSystemUiVisibility;
Dianne Hackborn9d090892012-06-11 18:35:41 -0700272 int mClientWindowLayoutFlags;
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800273 boolean mLastOverscanRequested;
Jeff Brown4952dfd2011-11-30 19:23:22 -0800274
275 // Pool of queued input events.
276 private static final int MAX_QUEUED_INPUT_EVENT_POOL_SIZE = 10;
277 private QueuedInputEvent mQueuedInputEventPool;
278 private int mQueuedInputEventPoolSize;
Jeff Brown4952dfd2011-11-30 19:23:22 -0800279
Michael Wrightc8a7e542013-03-20 17:58:33 -0700280 /* Input event queue.
Jeff Brownf9e989d2013-04-04 23:04:03 -0700281 * Pending input events are input events waiting to be delivered to the input stages
282 * and handled by the application.
Michael Wrightc8a7e542013-03-20 17:58:33 -0700283 */
284 QueuedInputEvent mPendingInputEventHead;
285 QueuedInputEvent mPendingInputEventTail;
Michael Wright95ae9422013-03-14 10:58:50 -0700286 int mPendingInputEventCount;
Jeff Brown96e942d2011-11-30 19:55:01 -0800287 boolean mProcessInputEventsScheduled;
Michael Wright9d744c72014-02-18 21:27:42 -0800288 boolean mUnbufferedInputDispatch;
Michael Wright95ae9422013-03-14 10:58:50 -0700289 String mPendingInputEventQueueLengthCounterName = "pq";
Jeff Brownf9e989d2013-04-04 23:04:03 -0700290
291 InputStage mFirstInputStage;
292 InputStage mFirstPostImeInputStage;
Michael Wright899d7052014-04-23 17:23:39 -0700293 InputStage mSyntheticInputStage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294
295 boolean mWindowAttributesChanged = false;
Romain Guyf21c9b02011-09-06 16:56:54 -0700296 int mWindowAttributesChangesFlag = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297
298 // These can be accessed by any thread, must be protected with a lock.
Mathias Agopian5583dc62009-07-09 16:28:11 -0700299 // Surface can never be reassigned or cleared (use Surface.clear()).
John Reckb13de072014-11-19 16:33:47 -0800300 final Surface mSurface = new Surface();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301
302 boolean mAdded;
303 boolean mAddedTouchMode;
304
Craig Mautner48d0d182013-06-11 07:53:06 -0700305 final DisplayAdjustments mDisplayAdjustments;
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 // These are accessed by multiple threads.
308 final Rect mWinFrame; // frame given by window manager.
309
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800310 final Rect mPendingOverscanInsets = new Rect();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 final Rect mPendingVisibleInsets = new Rect();
Adrian Roosfa104232014-06-20 16:10:14 -0700312 final Rect mPendingStableInsets = new Rect();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 final Rect mPendingContentInsets = new Rect();
Filip Gruszczynski2217f612015-05-26 11:32:08 -0700314 final Rect mPendingOutsets = new Rect();
Jorim Jaggia7262a82015-11-03 15:15:40 +0100315 final Rect mPendingBackDropFrame = new Rect();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
317 = new ViewTreeObserver.InternalInsetsInfo();
318
Adrian Roosfa104232014-06-20 16:10:14 -0700319 final Rect mDispatchContentInsets = new Rect();
320 final Rect mDispatchStableInsets = new Rect();
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700321
Filip Gruszczynski954289d2015-02-26 15:46:47 -0800322 private WindowInsets mLastWindowInsets;
323
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700324 final Configuration mLastConfiguration = new Configuration();
325 final Configuration mPendingConfiguration = new Configuration();
Romain Guy59a12ca2011-06-09 17:48:21 -0700326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327 boolean mScrollMayChange;
328 int mSoftInputMode;
Svetoslav Ganov149567f2013-01-08 15:23:34 -0800329 WeakReference<View> mLastScrolledFocus;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 int mScrollY;
331 int mCurScrollY;
332 Scroller mScroller;
John Recke56e9df2014-02-21 15:45:10 -0800333 static final Interpolator mResizeInterpolator = new AccelerateDecelerateInterpolator();
Chet Haasecca2c982011-05-20 14:34:18 -0700334 private ArrayList<LayoutTransition> mPendingTransitions;
Romain Guy8506ab42009-06-11 17:35:47 -0700335
Romain Guy8506ab42009-06-11 17:35:47 -0700336 final ViewConfiguration mViewConfiguration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337
Christopher Tatea53146c2010-09-07 11:57:52 -0700338 /* Drag/drop */
339 ClipDescription mDragDescription;
340 View mCurrentDragView;
Christopher Tate7fb8b562011-01-20 13:46:41 -0800341 volatile Object mLocalDragState;
Christopher Tatea53146c2010-09-07 11:57:52 -0700342 final PointF mDragPoint = new PointF();
Christopher Tate2c095f32010-10-04 14:13:40 -0700343 final PointF mLastTouchPoint = new PointF();
Vladislav Kaznacheevba761122016-01-22 12:09:45 -0800344 int mLastTouchSource;
Igor Murashkina86ab6402013-08-30 12:58:36 -0700345
346 private boolean mProfileRendering;
Romain Guyd0750312012-11-29 11:34:43 -0800347 private Choreographer.FrameCallback mRenderProfiler;
348 private boolean mRenderProfilingEnabled;
Christopher Tatea53146c2010-09-07 11:57:52 -0700349
Chet Haase2f2022a2011-10-11 06:41:59 -0700350 // Variables to track frames per second, enabled via DEBUG_FPS flag
351 private long mFpsStartTime = -1;
352 private long mFpsPrevTime = -1;
353 private int mFpsNumFrames;
354
Jun Mukai1db53972015-09-11 18:08:31 -0700355 private int mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
Jun Mukaid4eaef72015-10-30 15:54:33 -0700356 private PointerIcon mCustomPointerIcon = null;
Jun Mukai1db53972015-09-11 18:08:31 -0700357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 /**
359 * see {@link #playSoundEffect(int)}
360 */
361 AudioManager mAudioManager;
362
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700363 final AccessibilityManager mAccessibilityManager;
364
Gilles Debunne5ac84422011-10-19 09:35:58 -0700365 AccessibilityInteractionController mAccessibilityInteractionController;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700366
367 AccessibilityInteractionConnectionManager mAccessibilityInteractionConnectionManager;
Chris Craikcce47eb2014-07-16 15:12:15 -0700368 HighContrastTextManager mHighContrastTextManager;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700369
Svetoslav Ganova0156172011-06-26 17:55:44 -0700370 SendWindowContentChangedAccessibilityEvent mSendWindowContentChangedAccessibilityEvent;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700371
Svetoslav Ganov42138042012-03-20 11:51:39 -0700372 HashSet<View> mTempHashSet;
Svetoslav Ganov79311c42012-01-17 20:24:26 -0800373
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700374 private final int mDensity;
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700375 private final int mNoncompatDensity;
Adam Powellb08013c2010-09-16 16:28:11 -0700376
Chet Haase97140572012-09-13 14:56:47 -0700377 private boolean mInLayout = false;
378 ArrayList<View> mLayoutRequesters = new ArrayList<View>();
379 boolean mHandlingLayoutInLayoutRequest = false;
380
Fabrice Di Megliob003e282012-10-17 17:20:19 -0700381 private int mViewLayoutDirectionInitial;
Chet Haase97140572012-09-13 14:56:47 -0700382
Craig Mautner8f303ad2013-06-14 11:32:22 -0700383 /** Set to true once doDie() has been called. */
384 private boolean mRemoved;
385
Jeff Brown21bc5c92011-02-28 18:27:14 -0800386 /**
387 * Consistency verifier for debugging purposes.
388 */
389 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
390 InputEventConsistencyVerifier.isInstrumentationEnabled() ?
391 new InputEventConsistencyVerifier(this, 0) : null;
392
Dianne Hackborn9a230e02011-10-06 11:51:27 -0700393 static final class SystemUiVisibilityInfo {
394 int seq;
395 int globalVisibility;
396 int localValue;
397 int localChanges;
398 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700399
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -0800400 private String mTag = TAG;
401
Jeff Brown98365d72012-08-19 20:30:52 -0700402 public ViewRootImpl(Context context, Display display) {
Jeff Brownf9e989d2013-04-04 23:04:03 -0700403 mContext = context;
404 mWindowSession = WindowManagerGlobal.getWindowSession();
Jeff Brown98365d72012-08-19 20:30:52 -0700405 mDisplay = display;
Dianne Hackbornc2293022013-02-06 23:14:49 -0800406 mBasePackageName = context.getBasePackageName();
Jeff Brown98365d72012-08-19 20:30:52 -0700407
Craig Mautner48d0d182013-06-11 07:53:06 -0700408 mDisplayAdjustments = display.getDisplayAdjustments();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 mThread = Thread.currentThread();
411 mLocation = new WindowLeaked(null);
412 mLocation.fillInStackTrace();
413 mWidth = -1;
414 mHeight = -1;
415 mDirty = new Rect();
416 mTempRect = new Rect();
417 mVisRect = new Rect();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 mWinFrame = new Rect();
Romain Guyfb8b7632010-08-23 21:05:08 -0700419 mWindow = new W(this);
Dianne Hackborn180c4842011-09-13 12:39:25 -0700420 mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 mViewVisibility = View.GONE;
422 mTransparentRegion = new Region();
423 mPreviousTransparentRegion = new Region();
424 mFirst = true; // true for the first time the view is added
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425 mAdded = false;
Chris Craikcce47eb2014-07-16 15:12:15 -0700426 mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700427 mAccessibilityManager = AccessibilityManager.getInstance(context);
428 mAccessibilityInteractionConnectionManager =
429 new AccessibilityInteractionConnectionManager();
Svetoslav Ganov00d0c142012-02-24 11:30:49 -0800430 mAccessibilityManager.addAccessibilityStateChangeListener(
431 mAccessibilityInteractionConnectionManager);
Chris Craikcce47eb2014-07-16 15:12:15 -0700432 mHighContrastTextManager = new HighContrastTextManager();
433 mAccessibilityManager.addHighTextContrastStateChangeListener(
434 mHighContrastTextManager);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 mViewConfiguration = ViewConfiguration.get(context);
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700436 mDensity = context.getResources().getDisplayMetrics().densityDpi;
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700437 mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
Jorim Jaggib10e33f2015-02-04 21:57:40 +0100438 mFallbackEventHandler = new PhoneFallbackEventHandler(context);
Jeff Brown96e942d2011-11-30 19:55:01 -0800439 mChoreographer = Choreographer.getInstance();
Jeff Brownd912e1f2014-04-11 18:46:22 -0700440 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
Dianne Hackborna53de062012-05-08 18:53:51 -0700441 loadSystemProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 }
443
Dianne Hackborn2a9094d2010-02-03 19:20:09 -0800444 public static void addFirstDrawHandler(Runnable callback) {
445 synchronized (sFirstDrawHandlers) {
446 if (!sFirstDrawComplete) {
447 sFirstDrawHandlers.add(callback);
448 }
449 }
450 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700451
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800452 public static void addConfigCallback(ComponentCallbacks callback) {
453 synchronized (sConfigCallbacks) {
454 sConfigCallbacks.add(callback);
455 }
456 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700457
Chong Zhangdcee1de2015-10-06 10:26:00 -0700458 public void addWindowCallbacks(WindowCallbacks callback) {
Skuhneb8160872015-09-22 09:51:39 -0700459 if (USE_MT_RENDERER) {
Chong Zhangdcee1de2015-10-06 10:26:00 -0700460 synchronized (mWindowCallbacks) {
461 mWindowCallbacks.add(callback);
Skuhneb8160872015-09-22 09:51:39 -0700462 }
463 }
464 }
465
Chong Zhangdcee1de2015-10-06 10:26:00 -0700466 public void removeWindowCallbacks(WindowCallbacks callback) {
Skuhneb8160872015-09-22 09:51:39 -0700467 if (USE_MT_RENDERER) {
Chong Zhangdcee1de2015-10-06 10:26:00 -0700468 synchronized (mWindowCallbacks) {
469 mWindowCallbacks.remove(callback);
Skuhneb8160872015-09-22 09:51:39 -0700470 }
471 }
472 }
473
Chong Zhang8dbd9ad2015-10-09 10:06:11 -0700474 public void reportDrawFinish() {
475 if (mWindowDrawCountDown != null) {
476 mWindowDrawCountDown.countDown();
477 }
478 }
479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 // FIXME for perf testing only
481 private boolean mProfile = false;
482
483 /**
484 * Call this to profile the next traversal call.
485 * FIXME for perf testing only. Remove eventually
486 */
487 public void profile() {
488 mProfile = true;
489 }
490
491 /**
492 * Indicates whether we are in touch mode. Calling this method triggers an IPC
493 * call and should be avoided whenever possible.
494 *
495 * @return True, if the device is in touch mode, false otherwise.
496 *
497 * @hide
498 */
499 static boolean isInTouchMode() {
Jeff Brown98365d72012-08-19 20:30:52 -0700500 IWindowSession windowSession = WindowManagerGlobal.peekWindowSession();
501 if (windowSession != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 try {
Jeff Brown98365d72012-08-19 20:30:52 -0700503 return windowSession.getInTouchMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800504 } catch (RemoteException e) {
505 }
506 }
507 return false;
508 }
509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 /**
511 * We have one child
512 */
Romain Guye4d01122010-06-16 18:44:05 -0700513 public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800514 synchronized (this) {
515 if (mView == null) {
Mitsuru Oshima8169dae2009-04-28 18:12:09 -0700516 mView = view;
Jeff Brownd912e1f2014-04-11 18:46:22 -0700517
518 mAttachInfo.mDisplayState = mDisplay.getState();
519 mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
520
Fabrice Di Megliob003e282012-10-17 17:20:19 -0700521 mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
Joe Onorato86f67862010-11-05 18:57:34 -0700522 mFallbackEventHandler.setView(view);
Mitsuru Oshima9189cab2009-06-03 11:19:12 -0700523 mWindowAttributes.copyFrom(attrs);
Dianne Hackbornc2293022013-02-06 23:14:49 -0800524 if (mWindowAttributes.packageName == null) {
525 mWindowAttributes.packageName = mBasePackageName;
526 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -0700527 attrs = mWindowAttributes;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -0800528 setTag();
Dianne Hackborn9d090892012-06-11 18:35:41 -0700529 // Keep track of the actual window flags supplied by the client.
530 mClientWindowLayoutFlags = attrs.flags;
Svetoslav Ganov791fd312012-05-14 15:12:30 -0700531
Svetoslav Ganov45a02e02012-06-17 15:07:29 -0700532 setAccessibilityFocus(null, null);
Svetoslav Ganov791fd312012-05-14 15:12:30 -0700533
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700534 if (view instanceof RootViewSurfaceTaker) {
535 mSurfaceHolderCallback =
536 ((RootViewSurfaceTaker)view).willYouTakeTheSurface();
537 if (mSurfaceHolderCallback != null) {
538 mSurfaceHolder = new TakenSurfaceHolder();
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700539 mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700540 }
541 }
Romain Guy1aec9a22011-01-05 09:37:12 -0800542
Alan Viverette49a22e82014-07-12 20:01:27 -0700543 // Compute surface insets required to draw at specified Z value.
544 // TODO: Use real shadow insets for a constant max Z.
Alan Viverette5435a302015-01-29 10:25:34 -0800545 if (!attrs.hasManualSurfaceInsets) {
546 final int surfaceInset = (int) Math.ceil(view.getZ() * 2);
547 attrs.surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset);
548 }
Alan Viverette49a22e82014-07-12 20:01:27 -0700549
Craig Mautner48d0d182013-06-11 07:53:06 -0700550 CompatibilityInfo compatibilityInfo = mDisplayAdjustments.getCompatibilityInfo();
Romain Guy856d4e12011-10-14 15:47:55 -0700551 mTranslator = compatibilityInfo.getTranslator();
552
Romain Guy1aec9a22011-01-05 09:37:12 -0800553 // If the application owns the surface, don't enable hardware acceleration
554 if (mSurfaceHolder == null) {
Romain Guy3b748a42013-04-17 18:54:38 -0700555 enableHardwareAcceleration(attrs);
Romain Guy1aec9a22011-01-05 09:37:12 -0800556 }
557
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700558 boolean restore = false;
Romain Guy35b38ce2009-10-07 13:38:55 -0700559 if (mTranslator != null) {
Romain Guy856d4e12011-10-14 15:47:55 -0700560 mSurface.setCompatibilityTranslator(mTranslator);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700561 restore = true;
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700562 attrs.backup();
563 mTranslator.translateWindowLayout(attrs);
Mitsuru Oshima3d914922009-05-13 22:29:15 -0700564 }
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -0800565 if (DEBUG_LAYOUT) Log.d(mTag, "WindowLayout in setView:" + attrs);
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700566
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -0700567 if (!compatibilityInfo.supportsScreen()) {
Adam Lesinski95c42972013-10-02 10:13:27 -0700568 attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700569 mLastInCompatMode = true;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -0700570 }
571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572 mSoftInputMode = attrs.softInputMode;
573 mWindowAttributesChanged = true;
Romain Guyf21c9b02011-09-06 16:56:54 -0700574 mWindowAttributesChangesFlag = WindowManager.LayoutParams.EVERYTHING_CHANGED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800575 mAttachInfo.mRootView = view;
Romain Guy35b38ce2009-10-07 13:38:55 -0700576 mAttachInfo.mScalingRequired = mTranslator != null;
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700577 mAttachInfo.mApplicationScale =
578 mTranslator == null ? 1.0f : mTranslator.applicationScale;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800579 if (panelParentView != null) {
580 mAttachInfo.mPanelParentWindowToken
581 = panelParentView.getApplicationWindowToken();
582 }
583 mAdded = true;
584 int res; /* = WindowManagerImpl.ADD_OKAY; */
Romain Guy8506ab42009-06-11 17:35:47 -0700585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800586 // Schedule the first layout -before- adding to the window
587 // manager, to make sure we do the relayout before receiving
588 // any other events from the system.
589 requestLayout();
Jeff Browncc4f7db2011-08-30 20:34:48 -0700590 if ((mWindowAttributes.inputFeatures
591 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
592 mInputChannel = new InputChannel();
593 }
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -0800594 mForceDecorViewVisibility = (mWindowAttributes.privateFlags
595 & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 try {
Dianne Hackborn180c4842011-09-13 12:39:25 -0700597 mOrigWindowType = mWindowAttributes.type;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700598 mAttachInfo.mRecomputeGlobalAttributes = true;
599 collectViewAttributes();
Jeff Brown98365d72012-08-19 20:30:52 -0700600 res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
601 getHostVisibility(), mDisplay.getDisplayId(),
Filip Gruszczynski0ec13282015-06-25 11:26:01 -0700602 mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
603 mAttachInfo.mOutsets, mInputChannel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 } catch (RemoteException e) {
605 mAdded = false;
606 mView = null;
607 mAttachInfo.mRootView = null;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700608 mInputChannel = null;
Joe Onorato86f67862010-11-05 18:57:34 -0700609 mFallbackEventHandler.setView(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 unscheduleTraversals();
Svetoslav Ganov45a02e02012-06-17 15:07:29 -0700611 setAccessibilityFocus(null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 throw new RuntimeException("Adding window failed", e);
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700613 } finally {
614 if (restore) {
615 attrs.restore();
616 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800617 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700618
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700619 if (mTranslator != null) {
620 mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets);
Mitsuru Oshima9189cab2009-06-03 11:19:12 -0700621 }
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800622 mPendingOverscanInsets.set(0, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 mPendingContentInsets.set(mAttachInfo.mContentInsets);
Adrian Roosfa104232014-06-20 16:10:14 -0700624 mPendingStableInsets.set(mAttachInfo.mStableInsets);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 mPendingVisibleInsets.set(0, 0, 0, 0);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -0800626 if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
Jeff Brown98365d72012-08-19 20:30:52 -0700627 if (res < WindowManagerGlobal.ADD_OKAY) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628 mAttachInfo.mRootView = null;
629 mAdded = false;
Joe Onorato86f67862010-11-05 18:57:34 -0700630 mFallbackEventHandler.setView(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631 unscheduleTraversals();
Svetoslav Ganov45a02e02012-06-17 15:07:29 -0700632 setAccessibilityFocus(null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 switch (res) {
Jeff Brown98365d72012-08-19 20:30:52 -0700634 case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
635 case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
636 throw new WindowManager.BadTokenException(
Wale Ogunwale74bf0652015-01-12 10:24:36 -0800637 "Unable to add window -- token " + attrs.token
638 + " is not valid; is your activity running?");
Jeff Brown98365d72012-08-19 20:30:52 -0700639 case WindowManagerGlobal.ADD_NOT_APP_TOKEN:
640 throw new WindowManager.BadTokenException(
Wale Ogunwale74bf0652015-01-12 10:24:36 -0800641 "Unable to add window -- token " + attrs.token
642 + " is not for an application");
Jeff Brown98365d72012-08-19 20:30:52 -0700643 case WindowManagerGlobal.ADD_APP_EXITING:
644 throw new WindowManager.BadTokenException(
Wale Ogunwale74bf0652015-01-12 10:24:36 -0800645 "Unable to add window -- app for token " + attrs.token
646 + " is exiting");
Jeff Brown98365d72012-08-19 20:30:52 -0700647 case WindowManagerGlobal.ADD_DUPLICATE_ADD:
648 throw new WindowManager.BadTokenException(
Wale Ogunwale74bf0652015-01-12 10:24:36 -0800649 "Unable to add window -- window " + mWindow
650 + " has already been added");
Jeff Brown98365d72012-08-19 20:30:52 -0700651 case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652 // Silently ignore -- we would have just removed it
653 // right away, anyway.
654 return;
Jeff Brown98365d72012-08-19 20:30:52 -0700655 case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON:
Alan Viverette73f6d602015-09-14 16:01:19 -0400656 throw new WindowManager.BadTokenException("Unable to add window "
657 + mWindow + " -- another window of type "
658 + mWindowAttributes.type + " already exists");
Jeff Brown98365d72012-08-19 20:30:52 -0700659 case WindowManagerGlobal.ADD_PERMISSION_DENIED:
Alan Viverette73f6d602015-09-14 16:01:19 -0400660 throw new WindowManager.BadTokenException("Unable to add window "
661 + mWindow + " -- permission denied for window type "
662 + mWindowAttributes.type);
Craig Mautner6018aee2012-10-23 14:27:49 -0700663 case WindowManagerGlobal.ADD_INVALID_DISPLAY:
Alan Viverette73f6d602015-09-14 16:01:19 -0400664 throw new WindowManager.InvalidDisplayException("Unable to add window "
665 + mWindow + " -- the specified display can not be found");
Wale Ogunwale74bf0652015-01-12 10:24:36 -0800666 case WindowManagerGlobal.ADD_INVALID_TYPE:
Alan Viverette73f6d602015-09-14 16:01:19 -0400667 throw new WindowManager.InvalidDisplayException("Unable to add window "
668 + mWindow + " -- the specified window type "
669 + mWindowAttributes.type + " is not valid");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 }
671 throw new RuntimeException(
Wale Ogunwale74bf0652015-01-12 10:24:36 -0800672 "Unable to add window -- unknown error code " + res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800673 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700674
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700675 if (view instanceof RootViewSurfaceTaker) {
676 mInputQueueCallback =
677 ((RootViewSurfaceTaker)view).willYouTakeTheInputQueue();
678 }
Jeff Browncc4f7db2011-08-30 20:34:48 -0700679 if (mInputChannel != null) {
680 if (mInputQueueCallback != null) {
Michael Wrighta44dd262013-04-10 21:12:00 -0700681 mInputQueue = new InputQueue();
Jeff Browncc4f7db2011-08-30 20:34:48 -0700682 mInputQueueCallback.onInputQueueCreated(mInputQueue);
Jeff Browncc4f7db2011-08-30 20:34:48 -0700683 }
Michael Wrighta44dd262013-04-10 21:12:00 -0700684 mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
685 Looper.myLooper());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700686 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 view.assignParent(this);
Jeff Brown98365d72012-08-19 20:30:52 -0700689 mAddedTouchMode = (res & WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE) != 0;
690 mAppVisible = (res & WindowManagerGlobal.ADD_FLAG_APP_VISIBLE) != 0;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700691
692 if (mAccessibilityManager.isEnabled()) {
693 mAccessibilityInteractionConnectionManager.ensureConnection();
694 }
Svetoslav Ganov42138042012-03-20 11:51:39 -0700695
696 if (view.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
697 view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
698 }
Michael Wright95ae9422013-03-14 10:58:50 -0700699
Jeff Brownf9e989d2013-04-04 23:04:03 -0700700 // Set up the input pipeline.
701 CharSequence counterSuffix = attrs.getTitle();
Michael Wright899d7052014-04-23 17:23:39 -0700702 mSyntheticInputStage = new SyntheticInputStage();
703 InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
Jeff Brownf9e989d2013-04-04 23:04:03 -0700704 InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
705 "aq:native-post-ime:" + counterSuffix);
706 InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
707 InputStage imeStage = new ImeInputStage(earlyPostImeStage,
708 "aq:ime:" + counterSuffix);
709 InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
710 InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
711 "aq:native-pre-ime:" + counterSuffix);
712
713 mFirstInputStage = nativePreImeStage;
714 mFirstPostImeInputStage = earlyPostImeStage;
715 mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 }
717 }
718 }
719
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -0800720 private void setTag() {
721 final String[] split = mWindowAttributes.getTitle().toString().split("\\.");
722 if (split.length > 0) {
723 mTag = TAG + "[" + split[split.length - 1] + "]";
724 }
725 }
726
keunyoung30f420f2013-08-02 14:23:10 -0700727 /** Whether the window is in local focus mode or not */
728 private boolean isInLocalFocusMode() {
729 return (mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE) != 0;
730 }
731
Dianne Hackborn49b043f2015-05-07 14:21:38 -0700732 public int getWindowFlags() {
733 return mWindowAttributes.flags;
734 }
735
Dianne Hackbornece0f4f2015-06-11 13:29:01 -0700736 public int getDisplayId() {
737 return mDisplay.getDisplayId();
738 }
739
Dianne Hackborna7bb6fb2015-02-03 18:13:40 -0800740 public CharSequence getTitle() {
741 return mWindowAttributes.getTitle();
742 }
743
Romain Guy8ff6b9e2011-11-09 20:10:18 -0800744 void destroyHardwareResources() {
Romain Guy31f2c2e2011-11-21 10:55:41 -0800745 if (mAttachInfo.mHardwareRenderer != null) {
746 mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView);
John Reckf47a5942014-06-30 16:20:04 -0700747 mAttachInfo.mHardwareRenderer.destroy();
Romain Guy31f2c2e2011-11-21 10:55:41 -0800748 }
749 }
750
Bo Liu845535a2014-03-21 12:06:23 -0700751 public void detachFunctor(long functor) {
John Reck44ac42a2014-05-16 14:46:07 -0700752 if (mAttachInfo.mHardwareRenderer != null) {
753 // Fence so that any pending invokeFunctor() messages will be processed
754 // before we return from detachFunctor.
John Reckf47a5942014-06-30 16:20:04 -0700755 mAttachInfo.mHardwareRenderer.stopDrawing();
John Reck44ac42a2014-05-16 14:46:07 -0700756 }
Romain Guyba6be8a2012-04-23 18:22:09 -0700757 }
758
John Reck3b202512014-06-23 13:13:08 -0700759 /**
760 * Schedules the functor for execution in either kModeProcess or
761 * kModeProcessNoContext, depending on whether or not there is an EGLContext.
762 *
763 * @param functor The native functor to invoke
764 * @param waitForCompletion If true, this will not return until the functor
765 * has invoked. If false, the functor may be invoked
766 * asynchronously.
767 */
Hui Shu9970aee2014-06-23 17:10:30 -0700768 public void invokeFunctor(long functor, boolean waitForCompletion) {
John Reck3b202512014-06-23 13:13:08 -0700769 ThreadedRenderer.invokeFunctor(functor, waitForCompletion);
Bo Liuae738a72014-04-27 16:22:04 -0700770 }
771
John Reck119907c2014-08-14 09:02:01 -0700772 public void registerAnimatingRenderNode(RenderNode animator) {
773 if (mAttachInfo.mHardwareRenderer != null) {
774 mAttachInfo.mHardwareRenderer.registerAnimatingRenderNode(animator);
775 } else {
776 if (mAttachInfo.mPendingAnimatingRenderNodes == null) {
777 mAttachInfo.mPendingAnimatingRenderNodes = new ArrayList<RenderNode>();
778 }
779 mAttachInfo.mPendingAnimatingRenderNodes.add(animator);
780 }
781 }
782
Romain Guy3b748a42013-04-17 18:54:38 -0700783 private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
Dianne Hackborn7eec10e2010-11-12 18:03:47 -0800784 mAttachInfo.mHardwareAccelerated = false;
785 mAttachInfo.mHardwareAccelerationRequested = false;
Romain Guy4f6aff32011-01-12 16:21:41 -0800786
Romain Guy856d4e12011-10-14 15:47:55 -0700787 // Don't enable hardware acceleration when the application is in compatibility mode
John Reckdd58e792014-04-02 16:54:28 +0000788 if (mTranslator != null) return;
Romain Guy856d4e12011-10-14 15:47:55 -0700789
Dianne Hackborn7eec10e2010-11-12 18:03:47 -0800790 // Try to enable hardware acceleration if requested
Igor Murashkina86ab6402013-08-30 12:58:36 -0700791 final boolean hardwareAccelerated =
Jim Miller1b365922011-03-09 19:38:07 -0800792 (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
793
John Reckdd58e792014-04-02 16:54:28 +0000794 if (hardwareAccelerated) {
John Reck51aaf902015-12-02 15:08:07 -0800795 if (!ThreadedRenderer.isAvailable()) {
Romain Guy1af23a32011-03-24 16:03:55 -0700796 return;
797 }
798
Dianne Hackborn5d927c22011-09-02 12:22:18 -0700799 // Persistent processes (including the system) should not do
800 // accelerated rendering on low-end devices. In that case,
801 // sRendererDisabled will be set. In addition, the system process
802 // itself should never do accelerated rendering. In that case, both
803 // sRendererDisabled and sSystemRendererDisabled are set. When
804 // sSystemRendererDisabled is set, PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED
805 // can be used by code on the system process to escape that and enable
806 // HW accelerated drawing. (This is basically for the lock screen.)
Jim Miller1b365922011-03-09 19:38:07 -0800807
John Reck61375a82014-09-18 19:27:48 +0000808 final boolean fakeHwAccelerated = (attrs.privateFlags &
809 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED) != 0;
Dianne Hackborn5d927c22011-09-02 12:22:18 -0700810 final boolean forceHwAccelerated = (attrs.privateFlags &
811 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED) != 0;
Jim Miller1b365922011-03-09 19:38:07 -0800812
John Reck61375a82014-09-18 19:27:48 +0000813 if (fakeHwAccelerated) {
814 // This is exclusively for the preview windows the window manager
815 // shows for launching applications, so they will look more like
816 // the app being launched.
817 mAttachInfo.mHardwareAccelerationRequested = true;
John Reck51aaf902015-12-02 15:08:07 -0800818 } else if (!ThreadedRenderer.sRendererDisabled
819 || (ThreadedRenderer.sSystemRendererDisabled && forceHwAccelerated)) {
Romain Guyb051e892010-09-28 19:09:36 -0700820 if (mAttachInfo.mHardwareRenderer != null) {
John Reckf47a5942014-06-30 16:20:04 -0700821 mAttachInfo.mHardwareRenderer.destroy();
Romain Guy211370f2012-02-01 16:10:55 -0800822 }
823
Alan Viverette2b12b582014-10-29 11:11:40 -0700824 final Rect insets = attrs.surfaceInsets;
Alan Viverette2cd23e62014-11-04 17:04:02 -0800825 final boolean hasSurfaceInsets = insets.left != 0 || insets.right != 0
826 || insets.top != 0 || insets.bottom != 0;
Alan Viverette2b12b582014-10-29 11:11:40 -0700827 final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
John Reck51aaf902015-12-02 15:08:07 -0800828 mAttachInfo.mHardwareRenderer = ThreadedRenderer.create(mContext, translucent);
Romain Guye55945e2013-04-04 15:26:04 -0700829 if (mAttachInfo.mHardwareRenderer != null) {
830 mAttachInfo.mHardwareRenderer.setName(attrs.getTitle().toString());
831 mAttachInfo.mHardwareAccelerated =
832 mAttachInfo.mHardwareAccelerationRequested = true;
833 }
Romain Guye4d01122010-06-16 18:44:05 -0700834 }
835 }
836 }
837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838 public View getView() {
839 return mView;
840 }
841
842 final WindowLeaked getLocation() {
843 return mLocation;
844 }
845
846 void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
847 synchronized (this) {
Alan Viverettedbed8932014-08-06 17:54:52 -0700848 final int oldInsetLeft = mWindowAttributes.surfaceInsets.left;
849 final int oldInsetTop = mWindowAttributes.surfaceInsets.top;
850 final int oldInsetRight = mWindowAttributes.surfaceInsets.right;
851 final int oldInsetBottom = mWindowAttributes.surfaceInsets.bottom;
852 final int oldSoftInputMode = mWindowAttributes.softInputMode;
Alan Viverette5435a302015-01-29 10:25:34 -0800853 final boolean oldHasManualSurfaceInsets = mWindowAttributes.hasManualSurfaceInsets;
Alan Viverettedbed8932014-08-06 17:54:52 -0700854
Dianne Hackborn9d090892012-06-11 18:35:41 -0700855 // Keep track of the actual window flags supplied by the client.
856 mClientWindowLayoutFlags = attrs.flags;
Alan Viverettedbed8932014-08-06 17:54:52 -0700857
858 // Preserve compatible window flag if exists.
859 final int compatibleWindowFlag = mWindowAttributes.privateFlags
Adam Lesinski95c42972013-10-02 10:13:27 -0700860 & WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
Alan Viverettedbed8932014-08-06 17:54:52 -0700861
862 // Transfer over system UI visibility values as they carry current state.
Craig Mautner3fe38c02012-05-03 17:28:09 -0700863 attrs.systemUiVisibility = mWindowAttributes.systemUiVisibility;
864 attrs.subtreeSystemUiVisibility = mWindowAttributes.subtreeSystemUiVisibility;
Alan Viverettedbed8932014-08-06 17:54:52 -0700865
Romain Guyf21c9b02011-09-06 16:56:54 -0700866 mWindowAttributesChangesFlag = mWindowAttributes.copyFrom(attrs);
John Spurlockbd957402013-10-03 11:38:39 -0400867 if ((mWindowAttributesChangesFlag
868 & WindowManager.LayoutParams.TRANSLUCENT_FLAGS_CHANGED) != 0) {
869 // Recompute system ui visibility.
870 mAttachInfo.mRecomputeGlobalAttributes = true;
871 }
Dianne Hackbornc2293022013-02-06 23:14:49 -0800872 if (mWindowAttributes.packageName == null) {
873 mWindowAttributes.packageName = mBasePackageName;
874 }
Adam Lesinski95c42972013-10-02 10:13:27 -0700875 mWindowAttributes.privateFlags |= compatibleWindowFlag;
Dianne Hackborn9d090892012-06-11 18:35:41 -0700876
Alan Viverettedbed8932014-08-06 17:54:52 -0700877 // Restore old surface insets.
878 mWindowAttributes.surfaceInsets.set(
879 oldInsetLeft, oldInsetTop, oldInsetRight, oldInsetBottom);
Alan Viverette5435a302015-01-29 10:25:34 -0800880 mWindowAttributes.hasManualSurfaceInsets = oldHasManualSurfaceInsets;
Alan Viverettedbed8932014-08-06 17:54:52 -0700881
Dianne Hackborn9d090892012-06-11 18:35:41 -0700882 applyKeepScreenOnFlag(mWindowAttributes);
883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800884 if (newView) {
885 mSoftInputMode = attrs.softInputMode;
886 requestLayout();
887 }
Alan Viverettedbed8932014-08-06 17:54:52 -0700888
The Android Open Source Project10592532009-03-18 17:39:46 -0700889 // Don't lose the mode we last auto-computed.
Alan Viverettedbed8932014-08-06 17:54:52 -0700890 if ((attrs.softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
The Android Open Source Project10592532009-03-18 17:39:46 -0700891 == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
892 mWindowAttributes.softInputMode = (mWindowAttributes.softInputMode
893 & ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
Alan Viverettedbed8932014-08-06 17:54:52 -0700894 | (oldSoftInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST);
The Android Open Source Project10592532009-03-18 17:39:46 -0700895 }
Alan Viverettedbed8932014-08-06 17:54:52 -0700896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 mWindowAttributesChanged = true;
898 scheduleTraversals();
899 }
900 }
901
902 void handleAppVisibility(boolean visible) {
903 if (mAppVisible != visible) {
904 mAppVisible = visible;
905 scheduleTraversals();
John Reck73840ea2014-09-22 07:39:18 -0700906 if (!mAppVisible) {
907 WindowManagerGlobal.trimForeground();
908 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909 }
910 }
911
912 void handleGetNewSurface() {
913 mNewSurfaceNeeded = true;
914 mFullRedrawNeeded = true;
915 scheduleTraversals();
916 }
917
Jeff Brownd912e1f2014-04-11 18:46:22 -0700918 private final DisplayListener mDisplayListener = new DisplayListener() {
919 @Override
920 public void onDisplayChanged(int displayId) {
921 if (mView != null && mDisplay.getDisplayId() == displayId) {
922 final int oldDisplayState = mAttachInfo.mDisplayState;
923 final int newDisplayState = mDisplay.getState();
924 if (oldDisplayState != newDisplayState) {
925 mAttachInfo.mDisplayState = newDisplayState;
Jeff Brownc2932a12014-11-20 18:04:05 -0800926 pokeDrawLockIfNeeded();
Jeff Brownd912e1f2014-04-11 18:46:22 -0700927 if (oldDisplayState != Display.STATE_UNKNOWN) {
928 final int oldScreenState = toViewScreenState(oldDisplayState);
929 final int newScreenState = toViewScreenState(newDisplayState);
930 if (oldScreenState != newScreenState) {
931 mView.dispatchScreenStateChanged(newScreenState);
932 }
933 if (oldDisplayState == Display.STATE_OFF) {
934 // Draw was suppressed so we need to for it to happen here.
935 mFullRedrawNeeded = true;
936 scheduleTraversals();
937 }
938 }
939 }
Romain Guy7e4e5612012-03-05 14:37:29 -0800940 }
941 }
Jeff Brownd912e1f2014-04-11 18:46:22 -0700942
943 @Override
944 public void onDisplayRemoved(int displayId) {
945 }
946
947 @Override
948 public void onDisplayAdded(int displayId) {
949 }
950
951 private int toViewScreenState(int displayState) {
952 return displayState == Display.STATE_OFF ?
953 View.SCREEN_STATE_OFF : View.SCREEN_STATE_ON;
954 }
955 };
Romain Guy7e4e5612012-03-05 14:37:29 -0800956
Jeff Brownc2932a12014-11-20 18:04:05 -0800957 void pokeDrawLockIfNeeded() {
958 final int displayState = mAttachInfo.mDisplayState;
959 if (mView != null && mAdded && mTraversalScheduled
960 && (displayState == Display.STATE_DOZE
961 || displayState == Display.STATE_DOZE_SUSPEND)) {
962 try {
963 mWindowSession.pokeDrawLock(mWindow);
964 } catch (RemoteException ex) {
965 // System server died, oh well.
966 }
967 }
968 }
969
Craig Mautner6018aee2012-10-23 14:27:49 -0700970 @Override
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700971 public void requestFitSystemWindows() {
972 checkThread();
Adrian Roosfa104232014-06-20 16:10:14 -0700973 mApplyInsetsRequested = true;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700974 scheduleTraversals();
975 }
976
Craig Mautner6018aee2012-10-23 14:27:49 -0700977 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 public void requestLayout() {
Chet Haase3efa7b52012-12-03 08:33:17 -0800979 if (!mHandlingLayoutInLayoutRequest) {
980 checkThread();
981 mLayoutRequested = true;
982 scheduleTraversals();
983 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 }
985
Craig Mautner6018aee2012-10-23 14:27:49 -0700986 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 public boolean isLayoutRequested() {
988 return mLayoutRequested;
989 }
990
Romain Guycfef1232012-02-23 13:50:37 -0800991 void invalidate() {
992 mDirty.set(0, 0, mWidth, mHeight);
John Recke4267ea2014-06-03 15:53:15 -0700993 if (!mWillDrawSoon) {
994 scheduleTraversals();
995 }
Romain Guycfef1232012-02-23 13:50:37 -0800996 }
997
Dianne Hackborna53de062012-05-08 18:53:51 -0700998 void invalidateWorld(View view) {
999 view.invalidate();
1000 if (view instanceof ViewGroup) {
Romain Guyf84208f2012-09-13 22:50:18 -07001001 ViewGroup parent = (ViewGroup) view;
1002 for (int i = 0; i < parent.getChildCount(); i++) {
Dianne Hackborna53de062012-05-08 18:53:51 -07001003 invalidateWorld(parent.getChildAt(i));
1004 }
1005 }
1006 }
1007
Craig Mautner6018aee2012-10-23 14:27:49 -07001008 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 public void invalidateChild(View child, Rect dirty) {
Romain Guycfef1232012-02-23 13:50:37 -08001010 invalidateChildInParent(null, dirty);
1011 }
1012
Craig Mautner8f303ad2013-06-14 11:32:22 -07001013 @Override
Romain Guycfef1232012-02-23 13:50:37 -08001014 public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 checkThread();
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001016 if (DEBUG_DRAW) Log.v(mTag, "Invalidate child: " + dirty);
Romain Guycfef1232012-02-23 13:50:37 -08001017
Chet Haase70d4ba12010-10-06 09:46:45 -07001018 if (dirty == null) {
Chet Haase70d4ba12010-10-06 09:46:45 -07001019 invalidate();
Romain Guycfef1232012-02-23 13:50:37 -08001020 return null;
Chet Haase3561d062012-10-23 12:54:51 -07001021 } else if (dirty.isEmpty() && !mIsAnimating) {
Chet Haase05e91ed2012-07-03 14:17:57 -07001022 return null;
Chet Haase70d4ba12010-10-06 09:46:45 -07001023 }
Romain Guycfef1232012-02-23 13:50:37 -08001024
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001025 if (mCurScrollY != 0 || mTranslator != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026 mTempRect.set(dirty);
Romain Guy1e095972009-07-07 11:22:45 -07001027 dirty = mTempRect;
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07001028 if (mCurScrollY != 0) {
Romain Guycfef1232012-02-23 13:50:37 -08001029 dirty.offset(0, -mCurScrollY);
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07001030 }
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001031 if (mTranslator != null) {
Romain Guy1e095972009-07-07 11:22:45 -07001032 mTranslator.translateRectInAppWindowToScreen(dirty);
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07001033 }
Romain Guy1e095972009-07-07 11:22:45 -07001034 if (mAttachInfo.mScalingRequired) {
1035 dirty.inset(-1, -1);
1036 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001037 }
Romain Guycfef1232012-02-23 13:50:37 -08001038
Alan Viverettea7ea65e2015-05-15 11:30:21 -07001039 invalidateRectOnScreen(dirty);
1040
1041 return null;
1042 }
1043
1044 private void invalidateRectOnScreen(Rect dirty) {
Romain Guycfef1232012-02-23 13:50:37 -08001045 final Rect localDirty = mDirty;
1046 if (!localDirty.isEmpty() && !localDirty.contains(dirty)) {
Romain Guy02ccac62011-06-24 13:20:23 -07001047 mAttachInfo.mSetIgnoreDirtyState = true;
Romain Guy7d695942010-12-01 17:22:29 -08001048 mAttachInfo.mIgnoreDirtyState = true;
1049 }
Romain Guycfef1232012-02-23 13:50:37 -08001050
1051 // Add the new dirty rect to the current one
1052 localDirty.union(dirty.left, dirty.top, dirty.right, dirty.bottom);
1053 // Intersect with the bounds of the window to skip
1054 // updates that lie outside of the visible region
Romain Guy7b2f8b82012-03-19 17:18:54 -07001055 final float appScale = mAttachInfo.mApplicationScale;
Chet Haase3561d062012-10-23 12:54:51 -07001056 final boolean intersected = localDirty.intersect(0, 0,
1057 (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
1058 if (!intersected) {
Chet Haaseb78ee0e2012-10-17 11:32:01 -07001059 localDirty.setEmpty();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060 }
Chet Haase3561d062012-10-23 12:54:51 -07001061 if (!mWillDrawSoon && (intersected || mIsAnimating)) {
1062 scheduleTraversals();
1063 }
Romain Guy0d9275e2010-10-26 14:22:30 -07001064 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065
Daniel Koulomzin087ae472015-12-16 17:52:25 -05001066 public void setIsAmbientMode(boolean ambient) {
1067 mIsAmbientMode = ambient;
1068 }
1069
George Mount41725de2015-04-09 08:23:05 -07001070 void setWindowStopped(boolean stopped) {
Dianne Hackbornce418e62011-03-01 14:31:38 -08001071 if (mStopped != stopped) {
1072 mStopped = stopped;
George Mount41725de2015-04-09 08:23:05 -07001073 if (!mStopped) {
Dianne Hackbornce418e62011-03-01 14:31:38 -08001074 scheduleTraversals();
1075 }
1076 }
1077 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001078
George Mount41725de2015-04-09 08:23:05 -07001079 /**
1080 * Block the input events during an Activity Transition. The KEYCODE_BACK event is allowed
1081 * through to allow quick reversal of the Activity Transition.
1082 *
1083 * @param paused true to pause, false to resume.
1084 */
1085 public void setPausedForTransition(boolean paused) {
1086 mPausedForTransition = paused;
1087 }
1088
Craig Mautner8f303ad2013-06-14 11:32:22 -07001089 @Override
Romain Guycfef1232012-02-23 13:50:37 -08001090 public ViewParent getParent() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 return null;
1092 }
1093
Craig Mautner8f303ad2013-06-14 11:32:22 -07001094 @Override
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001095 public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 if (child != mView) {
1097 throw new RuntimeException("child is not mine, honest!");
1098 }
1099 // Note: don't apply scroll offset, because we want to know its
1100 // visibility in the virtual canvas being given to the view hierarchy.
1101 return r.intersect(0, 0, mWidth, mHeight);
1102 }
1103
Igor Murashkina86ab6402013-08-30 12:58:36 -07001104 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 public void bringChildToFront(View child) {
1106 }
1107
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 int getHostVisibility() {
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -08001109 return (mAppVisible || mForceDecorViewVisibility) ? mView.getVisibility() : View.GONE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 }
Romain Guy8506ab42009-06-11 17:35:47 -07001111
Chet Haasecca2c982011-05-20 14:34:18 -07001112 /**
1113 * Add LayoutTransition to the list of transitions to be started in the next traversal.
1114 * This list will be cleared after the transitions on the list are start()'ed. These
1115 * transitionsa re added by LayoutTransition itself when it sets up animations. The setup
1116 * happens during the layout phase of traversal, which we want to complete before any of the
1117 * animations are started (because those animations may side-effect properties that layout
1118 * depends upon, like the bounding rectangles of the affected views). So we add the transition
1119 * to the list and it is started just prior to starting the drawing phase of traversal.
1120 *
1121 * @param transition The LayoutTransition to be started on the next traversal.
1122 *
1123 * @hide
1124 */
1125 public void requestTransitionStart(LayoutTransition transition) {
1126 if (mPendingTransitions == null || !mPendingTransitions.contains(transition)) {
1127 if (mPendingTransitions == null) {
1128 mPendingTransitions = new ArrayList<LayoutTransition>();
1129 }
1130 mPendingTransitions.add(transition);
1131 }
1132 }
1133
John Recka5dda642014-05-22 15:43:54 -07001134 /**
1135 * Notifies the HardwareRenderer that a new frame will be coming soon.
1136 * Currently only {@link ThreadedRenderer} cares about this, and uses
1137 * this knowledge to adjust the scheduling of off-thread animations
1138 */
1139 void notifyRendererOfFramePending() {
1140 if (mAttachInfo.mHardwareRenderer != null) {
1141 mAttachInfo.mHardwareRenderer.notifyFramePending();
1142 }
1143 }
1144
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001145 void scheduleTraversals() {
1146 if (!mTraversalScheduled) {
1147 mTraversalScheduled = true;
Jeff Brown3d4e7efe2015-02-26 15:34:16 -08001148 mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001149 mChoreographer.postCallback(
1150 Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
Michael Wright9d744c72014-02-18 21:27:42 -08001151 if (!mUnbufferedInputDispatch) {
1152 scheduleConsumeBatchedInput();
1153 }
John Recka5dda642014-05-22 15:43:54 -07001154 notifyRendererOfFramePending();
Jeff Brownc2932a12014-11-20 18:04:05 -08001155 pokeDrawLockIfNeeded();
Jeff Brown96e942d2011-11-30 19:55:01 -08001156 }
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001157 }
Jeff Brown96e942d2011-11-30 19:55:01 -08001158
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001159 void unscheduleTraversals() {
1160 if (mTraversalScheduled) {
1161 mTraversalScheduled = false;
Jeff Brown3d4e7efe2015-02-26 15:34:16 -08001162 mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001163 mChoreographer.removeCallbacks(
1164 Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
1165 }
1166 }
1167
1168 void doTraversal() {
1169 if (mTraversalScheduled) {
1170 mTraversalScheduled = false;
Jeff Brown3d4e7efe2015-02-26 15:34:16 -08001171 mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001172
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001173 if (mProfile) {
1174 Debug.startMethodTracing("ViewAncestor");
Jeff Brown96e942d2011-11-30 19:55:01 -08001175 }
Jeff Brown96e942d2011-11-30 19:55:01 -08001176
Chris Craike22c59b2015-05-21 18:33:37 -07001177 performTraversals();
Jeff Brown96e942d2011-11-30 19:55:01 -08001178
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001179 if (mProfile) {
1180 Debug.stopMethodTracing();
1181 mProfile = false;
1182 }
Jeff Brown96e942d2011-11-30 19:55:01 -08001183 }
1184 }
1185
Dianne Hackborn9d090892012-06-11 18:35:41 -07001186 private void applyKeepScreenOnFlag(WindowManager.LayoutParams params) {
1187 // Update window's global keep screen on flag: if a view has requested
1188 // that the screen be kept on, then it is always set; otherwise, it is
1189 // set to whatever the client last requested for the global state.
1190 if (mAttachInfo.mKeepScreenOn) {
1191 params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
1192 } else {
1193 params.flags = (params.flags&~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
1194 | (mClientWindowLayoutFlags&WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
1195 }
1196 }
1197
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001198 private boolean collectViewAttributes() {
Chris Craikd36a81f2014-07-17 10:16:51 -07001199 if (mAttachInfo.mRecomputeGlobalAttributes) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001200 //Log.i(mTag, "Computing view hierarchy attributes!");
Chris Craikd36a81f2014-07-17 10:16:51 -07001201 mAttachInfo.mRecomputeGlobalAttributes = false;
1202 boolean oldScreenOn = mAttachInfo.mKeepScreenOn;
1203 mAttachInfo.mKeepScreenOn = false;
1204 mAttachInfo.mSystemUiVisibility = 0;
1205 mAttachInfo.mHasSystemUiListeners = false;
1206 mView.dispatchCollectViewAttributes(mAttachInfo, 0);
1207 mAttachInfo.mSystemUiVisibility &= ~mAttachInfo.mDisabledSystemUiVisibility;
Craig Mautner7eac0f52012-09-13 13:14:14 -07001208 WindowManager.LayoutParams params = mWindowAttributes;
Chris Craikd36a81f2014-07-17 10:16:51 -07001209 mAttachInfo.mSystemUiVisibility |= getImpliedSystemUiVisibility(params);
1210 if (mAttachInfo.mKeepScreenOn != oldScreenOn
1211 || mAttachInfo.mSystemUiVisibility != params.subtreeSystemUiVisibility
1212 || mAttachInfo.mHasSystemUiListeners != params.hasSystemUiListeners) {
Dianne Hackborn9d090892012-06-11 18:35:41 -07001213 applyKeepScreenOnFlag(params);
Chris Craikd36a81f2014-07-17 10:16:51 -07001214 params.subtreeSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
1215 params.hasSystemUiListeners = mAttachInfo.mHasSystemUiListeners;
1216 mView.dispatchWindowSystemUiVisiblityChanged(mAttachInfo.mSystemUiVisibility);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001217 return true;
1218 }
1219 }
1220 return false;
1221 }
1222
John Spurlockbd957402013-10-03 11:38:39 -04001223 private int getImpliedSystemUiVisibility(WindowManager.LayoutParams params) {
1224 int vis = 0;
1225 // Translucent decor window flags imply stable system ui visibility.
1226 if ((params.flags & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) != 0) {
1227 vis |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
1228 }
1229 if ((params.flags & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) != 0) {
1230 vis |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
1231 }
1232 return vis;
1233 }
1234
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001235 private boolean measureHierarchy(final View host, final WindowManager.LayoutParams lp,
1236 final Resources res, final int desiredWindowWidth, final int desiredWindowHeight) {
1237 int childWidthMeasureSpec;
1238 int childHeightMeasureSpec;
1239 boolean windowSizeMayChange = false;
1240
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001241 if (DEBUG_ORIENTATION || DEBUG_LAYOUT) Log.v(mTag,
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001242 "Measuring " + host + " in display " + desiredWindowWidth
1243 + "x" + desiredWindowHeight + "...");
1244
1245 boolean goodMeasure = false;
1246 if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
1247 // On large screens, we don't want to allow dialogs to just
1248 // stretch to fill the entire width of the screen to display
1249 // one line of text. First try doing the layout at a smaller
1250 // size to see if it will fit.
1251 final DisplayMetrics packageMetrics = res.getDisplayMetrics();
1252 res.getValue(com.android.internal.R.dimen.config_prefDialogWidth, mTmpValue, true);
1253 int baseSize = 0;
1254 if (mTmpValue.type == TypedValue.TYPE_DIMENSION) {
1255 baseSize = (int)mTmpValue.getDimension(packageMetrics);
1256 }
Filip Gruszczynski1937a4c2016-01-19 16:17:13 -08001257 if (DEBUG_DIALOG) Log.v(mTag, "Window " + mView + ": baseSize=" + baseSize
1258 + ", desiredWindowWidth=" + desiredWindowWidth);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001259 if (baseSize != 0 && desiredWindowWidth > baseSize) {
1260 childWidthMeasureSpec = getRootMeasureSpec(baseSize, lp.width);
1261 childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
Jeff Brownc8d2668b2012-05-16 17:23:59 -07001262 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001263 if (DEBUG_DIALOG) Log.v(mTag, "Window " + mView + ": measured ("
Filip Gruszczynski1937a4c2016-01-19 16:17:13 -08001264 + host.getMeasuredWidth() + "," + host.getMeasuredHeight()
1265 + ") from width spec: " + MeasureSpec.toString(childWidthMeasureSpec)
1266 + " and height spec: " + MeasureSpec.toString(childHeightMeasureSpec));
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001267 if ((host.getMeasuredWidthAndState()&View.MEASURED_STATE_TOO_SMALL) == 0) {
1268 goodMeasure = true;
1269 } else {
1270 // Didn't fit in that size... try expanding a bit.
1271 baseSize = (baseSize+desiredWindowWidth)/2;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001272 if (DEBUG_DIALOG) Log.v(mTag, "Window " + mView + ": next baseSize="
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001273 + baseSize);
1274 childWidthMeasureSpec = getRootMeasureSpec(baseSize, lp.width);
Jeff Brownc8d2668b2012-05-16 17:23:59 -07001275 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001276 if (DEBUG_DIALOG) Log.v(mTag, "Window " + mView + ": measured ("
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001277 + host.getMeasuredWidth() + "," + host.getMeasuredHeight() + ")");
1278 if ((host.getMeasuredWidthAndState()&View.MEASURED_STATE_TOO_SMALL) == 0) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001279 if (DEBUG_DIALOG) Log.v(mTag, "Good!");
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001280 goodMeasure = true;
1281 }
1282 }
1283 }
1284 }
1285
1286 if (!goodMeasure) {
1287 childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width);
1288 childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
Jeff Brownc8d2668b2012-05-16 17:23:59 -07001289 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001290 if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()) {
1291 windowSizeMayChange = true;
1292 }
1293 }
1294
1295 if (DBG) {
1296 System.out.println("======================================");
1297 System.out.println("performTraversals -- after measure");
1298 host.debug();
1299 }
1300
1301 return windowSizeMayChange;
1302 }
1303
Alan Viverettefed3f722013-11-14 14:48:20 -08001304 /**
1305 * Modifies the input matrix such that it maps view-local coordinates to
1306 * on-screen coordinates.
1307 *
1308 * @param m input matrix to modify
1309 */
1310 void transformMatrixToGlobal(Matrix m) {
Dake Gu7bf379c2014-07-15 16:29:38 -07001311 m.preTranslate(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
Alan Viverettefed3f722013-11-14 14:48:20 -08001312 }
1313
1314 /**
1315 * Modifies the input matrix such that it maps on-screen coordinates to
1316 * view-local coordinates.
1317 *
1318 * @param m input matrix to modify
1319 */
1320 void transformMatrixToLocal(Matrix m) {
Dake Gu7bf379c2014-07-15 16:29:38 -07001321 m.postTranslate(-mAttachInfo.mWindowLeft, -mAttachInfo.mWindowTop);
Alan Viverettefed3f722013-11-14 14:48:20 -08001322 }
1323
Filip Gruszczynski954289d2015-02-26 15:46:47 -08001324 /* package */ WindowInsets getWindowInsets(boolean forceConstruct) {
1325 if (mLastWindowInsets == null || forceConstruct) {
1326 mDispatchContentInsets.set(mAttachInfo.mContentInsets);
1327 mDispatchStableInsets.set(mAttachInfo.mStableInsets);
1328 Rect contentInsets = mDispatchContentInsets;
1329 Rect stableInsets = mDispatchStableInsets;
1330 // For dispatch we preserve old logic, but for direct requests from Views we allow to
1331 // immediately use pending insets.
1332 if (!forceConstruct
1333 && (!mPendingContentInsets.equals(contentInsets) ||
1334 !mPendingStableInsets.equals(stableInsets))) {
1335 contentInsets = mPendingContentInsets;
1336 stableInsets = mPendingStableInsets;
1337 }
Filip Gruszczynski2217f612015-05-26 11:32:08 -07001338 Rect outsets = mAttachInfo.mOutsets;
1339 if (outsets.left > 0 || outsets.top > 0 || outsets.right > 0 || outsets.bottom > 0) {
1340 contentInsets = new Rect(contentInsets.left + outsets.left,
1341 contentInsets.top + outsets.top, contentInsets.right + outsets.right,
1342 contentInsets.bottom + outsets.bottom);
1343 }
Filip Gruszczynski954289d2015-02-26 15:46:47 -08001344 mLastWindowInsets = new WindowInsets(contentInsets,
Adam Powell01f280d2015-05-18 16:07:42 -07001345 null /* windowDecorInsets */, stableInsets,
1346 mContext.getResources().getConfiguration().isScreenRound());
Filip Gruszczynski954289d2015-02-26 15:46:47 -08001347 }
1348 return mLastWindowInsets;
1349 }
1350
Adam Powell2accbf92014-04-16 23:14:57 +00001351 void dispatchApplyInsets(View host) {
Filip Gruszczynski954289d2015-02-26 15:46:47 -08001352 host.dispatchApplyWindowInsets(getWindowInsets(true /* forceConstruct */));
Adam Powell2accbf92014-04-16 23:14:57 +00001353 }
1354
Chong Zhangf6525ce2016-01-14 17:09:56 -08001355 private static boolean shouldUseDisplaySize(final WindowManager.LayoutParams lp) {
1356 return lp.type == TYPE_STATUS_BAR_PANEL
1357 || lp.type == TYPE_INPUT_METHOD
1358 || lp.type == TYPE_VOLUME_OVERLAY;
1359 }
1360
1361 private int dipToPx(int dip) {
1362 final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
1363 return (int) (displayMetrics.density * dip + 0.5f);
1364 }
1365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 private void performTraversals() {
1367 // cache mView since it is used so much below...
1368 final View host = mView;
1369
1370 if (DBG) {
1371 System.out.println("======================================");
1372 System.out.println("performTraversals");
1373 host.debug();
1374 }
1375
1376 if (host == null || !mAdded)
1377 return;
1378
Craig Mautnerdf2390a2012-08-29 20:59:22 -07001379 mIsInTraversal = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 mWillDrawSoon = true;
Dianne Hackborn711e62a2010-11-29 16:38:22 -08001381 boolean windowSizeMayChange = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 boolean newSurface = false;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07001383 boolean surfaceChanged = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 WindowManager.LayoutParams lp = mWindowAttributes;
1385
1386 int desiredWindowWidth;
1387 int desiredWindowHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 final int viewVisibility = getHostVisibility();
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001390 final boolean viewVisibilityChanged = !mFirst
1391 && (mViewVisibility != viewVisibility || mNewSurfaceNeeded);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392
1393 WindowManager.LayoutParams params = null;
1394 if (mWindowAttributesChanged) {
1395 mWindowAttributesChanged = false;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07001396 surfaceChanged = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 params = lp;
1398 }
Craig Mautner48d0d182013-06-11 07:53:06 -07001399 CompatibilityInfo compatibilityInfo = mDisplayAdjustments.getCompatibilityInfo();
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001400 if (compatibilityInfo.supportsScreen() == mLastInCompatMode) {
1401 params = lp;
Jeff Brown96e942d2011-11-30 19:55:01 -08001402 mFullRedrawNeeded = true;
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001403 mLayoutRequested = true;
1404 if (mLastInCompatMode) {
Adam Lesinski95c42972013-10-02 10:13:27 -07001405 params.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001406 mLastInCompatMode = false;
1407 } else {
Adam Lesinski95c42972013-10-02 10:13:27 -07001408 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001409 mLastInCompatMode = true;
1410 }
1411 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07001412
Romain Guyf21c9b02011-09-06 16:56:54 -07001413 mWindowAttributesChangesFlag = 0;
Igor Murashkina86ab6402013-08-30 12:58:36 -07001414
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001415 Rect frame = mWinFrame;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001416 if (mFirst) {
Jeff Brown96e942d2011-11-30 19:55:01 -08001417 mFullRedrawNeeded = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418 mLayoutRequested = true;
1419
Chong Zhangf6525ce2016-01-14 17:09:56 -08001420 if (shouldUseDisplaySize(lp)) {
Dianne Hackborna239c842011-06-01 12:28:20 -07001421 // NOTE -- system code, won't try to do compat mode.
Jeff Brownbc68a592011-07-25 12:58:12 -07001422 Point size = new Point();
Jeff Brown98365d72012-08-19 20:30:52 -07001423 mDisplay.getRealSize(size);
Jeff Brownbc68a592011-07-25 12:58:12 -07001424 desiredWindowWidth = size.x;
1425 desiredWindowHeight = size.y;
Dianne Hackborna239c842011-06-01 12:28:20 -07001426 } else {
Chong Zhangf6525ce2016-01-14 17:09:56 -08001427 Configuration config = mContext.getResources().getConfiguration();
1428 desiredWindowWidth = dipToPx(config.screenWidthDp);
1429 desiredWindowHeight = dipToPx(config.screenHeightDp);
Dianne Hackborna239c842011-06-01 12:28:20 -07001430 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001431
Romain Guyc5d55862011-01-21 19:01:46 -08001432 // We used to use the following condition to choose 32 bits drawing caches:
1433 // PixelFormat.hasAlpha(lp.format) || lp.format == PixelFormat.RGBX_8888
1434 // However, windows are now always 32 bits by default, so choose 32 bits
Chris Craikd36a81f2014-07-17 10:16:51 -07001435 mAttachInfo.mUse32BitDrawingCache = true;
1436 mAttachInfo.mHasWindowFocus = false;
1437 mAttachInfo.mWindowVisibility = viewVisibility;
1438 mAttachInfo.mRecomputeGlobalAttributes = false;
Dianne Hackborn694f79b2010-03-17 19:44:59 -07001439 mLastConfiguration.setTo(host.getResources().getConfiguration());
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001440 mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
Fabrice Di Megliob003e282012-10-17 17:20:19 -07001441 // Set the layout direction if it has not been set before (inherit is the default)
1442 if (mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
1443 host.setLayoutDirection(mLastConfiguration.getLayoutDirection());
1444 }
Chris Craikd36a81f2014-07-17 10:16:51 -07001445 host.dispatchAttachedToWindow(mAttachInfo, 0);
1446 mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(true);
Adam Powell2accbf92014-04-16 23:14:57 +00001447 dispatchApplyInsets(host);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001448 //Log.i(mTag, "Screen on initialized: " + attachInfo.mKeepScreenOn);
svetoslavganov75986cf2009-05-14 22:28:01 -07001449
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001450 } else {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001451 desiredWindowWidth = frame.width();
1452 desiredWindowHeight = frame.height();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001454 if (DEBUG_ORIENTATION) Log.v(mTag, "View " + host + " resized to: " + frame);
Jeff Brown96e942d2011-11-30 19:55:01 -08001455 mFullRedrawNeeded = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 mLayoutRequested = true;
Dianne Hackborn711e62a2010-11-29 16:38:22 -08001457 windowSizeMayChange = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 }
1459 }
1460
1461 if (viewVisibilityChanged) {
Chris Craikd36a81f2014-07-17 10:16:51 -07001462 mAttachInfo.mWindowVisibility = viewVisibility;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 host.dispatchWindowVisibilityChanged(viewVisibility);
1464 if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
Skuhneb8160872015-09-22 09:51:39 -07001465 endDragResizing();
Romain Guy65b345f2011-07-27 18:51:50 -07001466 destroyHardwareResources();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 }
1468 if (viewVisibility == View.GONE) {
1469 // After making a window gone, we will count it as being
1470 // shown for the first time the next time it gets focus.
1471 mHasHadWindowFocus = false;
1472 }
1473 }
1474
Alan Viverette7dbc3bf2015-01-28 16:14:36 -08001475 // Non-visible windows can't hold accessibility focus.
1476 if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
1477 host.clearAccessibilityFocus();
1478 }
1479
Chet Haaseb78c2842012-04-19 13:39:50 -07001480 // Execute enqueued actions on every traversal in case a detached view enqueued an action
Chris Craikd36a81f2014-07-17 10:16:51 -07001481 getRunQueue().executeActions(mAttachInfo.mHandler);
Chet Haaseb78c2842012-04-19 13:39:50 -07001482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 boolean insetsChanged = false;
Romain Guy8506ab42009-06-11 17:35:47 -07001484
Craig Mautner72d6f212015-02-19 16:33:09 -08001485 boolean layoutRequested = mLayoutRequested && (!mStopped || mReportNextDraw);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001486 if (layoutRequested) {
Romain Guy15df6702009-08-17 20:17:30 -07001487
Dianne Hackborn711e62a2010-11-29 16:38:22 -08001488 final Resources res = mView.getContext().getResources();
1489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 if (mFirst) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 // make sure touch mode code executes by setting cached value
1492 // to opposite of the added touch mode.
1493 mAttachInfo.mInTouchMode = !mAddedTouchMode;
Romain Guy2d4cff62010-04-09 15:39:00 -07001494 ensureTouchModeLocally(mAddedTouchMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001495 } else {
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001496 if (!mPendingOverscanInsets.equals(mAttachInfo.mOverscanInsets)) {
1497 insetsChanged = true;
1498 }
Dianne Hackbornfa6b35b2011-08-24 17:03:54 -07001499 if (!mPendingContentInsets.equals(mAttachInfo.mContentInsets)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 insetsChanged = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 }
Adrian Roosfa104232014-06-20 16:10:14 -07001502 if (!mPendingStableInsets.equals(mAttachInfo.mStableInsets)) {
1503 insetsChanged = true;
1504 }
Dianne Hackbornfa6b35b2011-08-24 17:03:54 -07001505 if (!mPendingVisibleInsets.equals(mAttachInfo.mVisibleInsets)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001507 if (DEBUG_LAYOUT) Log.v(mTag, "Visible insets changing to: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 + mAttachInfo.mVisibleInsets);
1509 }
Filip Gruszczynski2217f612015-05-26 11:32:08 -07001510 if (!mPendingOutsets.equals(mAttachInfo.mOutsets)) {
1511 insetsChanged = true;
1512 }
Chong Zhangf6525ce2016-01-14 17:09:56 -08001513 if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
1514 || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
Dianne Hackborn711e62a2010-11-29 16:38:22 -08001515 windowSizeMayChange = true;
Chong Zhangf6525ce2016-01-14 17:09:56 -08001516
1517 if (shouldUseDisplaySize(lp)) {
1518 // NOTE -- system code, won't try to do compat mode.
1519 Point size = new Point();
1520 mDisplay.getRealSize(size);
1521 desiredWindowWidth = size.x;
1522 desiredWindowHeight = size.y;
1523 } else {
1524 Configuration config = res.getConfiguration();
1525 desiredWindowWidth = dipToPx(config.screenWidthDp);
1526 desiredWindowHeight = dipToPx(config.screenHeightDp);
1527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 }
1529 }
1530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 // Ask host how big it wants to be
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001532 windowSizeMayChange |= measureHierarchy(host, lp, res,
1533 desiredWindowWidth, desiredWindowHeight);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 }
1535
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001536 if (collectViewAttributes()) {
1537 params = lp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 }
Chris Craikd36a81f2014-07-17 10:16:51 -07001539 if (mAttachInfo.mForceReportNewAttributes) {
1540 mAttachInfo.mForceReportNewAttributes = false;
Dianne Hackborn9a230e02011-10-06 11:51:27 -07001541 params = lp;
1542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543
Chris Craikd36a81f2014-07-17 10:16:51 -07001544 if (mFirst || mAttachInfo.mViewVisibilityChanged) {
1545 mAttachInfo.mViewVisibilityChanged = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 int resizeMode = mSoftInputMode &
1547 WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
1548 // If we are in auto resize mode, then we need to determine
1549 // what mode to use now.
1550 if (resizeMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
Chris Craikd36a81f2014-07-17 10:16:51 -07001551 final int N = mAttachInfo.mScrollContainers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 for (int i=0; i<N; i++) {
Chris Craikd36a81f2014-07-17 10:16:51 -07001553 if (mAttachInfo.mScrollContainers.get(i).isShown()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
1555 }
1556 }
1557 if (resizeMode == 0) {
1558 resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
1559 }
1560 if ((lp.softInputMode &
1561 WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) != resizeMode) {
1562 lp.softInputMode = (lp.softInputMode &
1563 ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) |
1564 resizeMode;
1565 params = lp;
1566 }
1567 }
1568 }
Romain Guy8506ab42009-06-11 17:35:47 -07001569
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001570 if (params != null) {
1571 if ((host.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
1572 if (!PixelFormat.formatHasAlpha(params.format)) {
1573 params.format = PixelFormat.TRANSLUCENT;
1574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 }
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001576 mAttachInfo.mOverscanRequested = (params.flags
1577 & WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001578 }
1579
Adrian Roosfa104232014-06-20 16:10:14 -07001580 if (mApplyInsetsRequested) {
1581 mApplyInsetsRequested = false;
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001582 mLastOverscanRequested = mAttachInfo.mOverscanRequested;
Adam Powell2accbf92014-04-16 23:14:57 +00001583 dispatchApplyInsets(host);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001584 if (mLayoutRequested) {
1585 // Short-circuit catching a new layout request here, so
1586 // we don't need to go through two layout passes when things
1587 // change due to fitting system windows, which can happen a lot.
1588 windowSizeMayChange |= measureHierarchy(host, lp,
1589 mView.getContext().getResources(),
1590 desiredWindowWidth, desiredWindowHeight);
1591 }
1592 }
1593
1594 if (layoutRequested) {
1595 // Clear this now, so that if anything requests a layout in the
1596 // rest of this function we will catch it and re-run a full
1597 // layout pass.
1598 mLayoutRequested = false;
1599 }
1600
1601 boolean windowShouldResize = layoutRequested && windowSizeMayChange
Dianne Hackborn189ee182010-12-02 21:48:53 -08001602 && ((mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight())
Romain Guy2e4f4262010-04-06 11:07:52 -07001603 || (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT &&
1604 frame.width() < desiredWindowWidth && frame.width() != mWidth)
1605 || (lp.height == ViewGroup.LayoutParams.WRAP_CONTENT &&
1606 frame.height() < desiredWindowHeight && frame.height() != mHeight));
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001607 windowShouldResize |= mDragResizing && mResizeMode == RESIZE_MODE_FREEFORM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001609 // If the activity was just relaunched, it might have unfrozen the task bounds (while
1610 // relaunching), so we need to force a call into window manager to pick up the latest
1611 // bounds.
1612 windowShouldResize |= mActivityRelaunched;
1613
Jeff Brown2e05ec32013-09-30 15:57:43 -07001614 // Determine whether to compute insets.
1615 // If there are no inset listeners remaining then we may still need to compute
1616 // insets in case the old insets were non-empty and must be reset.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 final boolean computesInternalInsets =
Chris Craikd36a81f2014-07-17 10:16:51 -07001618 mAttachInfo.mTreeObserver.hasComputeInternalInsetsListeners()
1619 || mAttachInfo.mHasNonEmptyGivenInternalInsets;
Romain Guy812ccbe2010-06-01 14:07:24 -07001620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 boolean insetsPending = false;
1622 int relayoutResult = 0;
Romain Guy812ccbe2010-06-01 14:07:24 -07001623
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -08001624 final boolean isViewVisible = viewVisibility == View.VISIBLE;
Romain Guy812ccbe2010-06-01 14:07:24 -07001625 if (mFirst || windowShouldResize || insetsChanged ||
Jorim Jaggia4a58ef2016-01-27 02:10:08 -08001626 viewVisibilityChanged || params != null || mForceNextWindowRelayout) {
1627 mForceNextWindowRelayout = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628
Alan Viverette64bf97a2015-09-18 16:42:00 -04001629 if (isViewVisible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001630 // If this window is giving internal insets to the window
1631 // manager, and it is being added or changing its visibility,
1632 // then we want to first give the window manager "fake"
1633 // insets to cause it to effectively ignore the content of
1634 // the window during layout. This avoids it briefly causing
1635 // other windows to resize/move based on the raw frame of the
1636 // window, waiting until we can finish laying out this window
1637 // and get back to the window manager with the ultimately
1638 // computed insets.
Romain Guy812ccbe2010-06-01 14:07:24 -07001639 insetsPending = computesInternalInsets && (mFirst || viewVisibilityChanged);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 }
1641
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07001642 if (mSurfaceHolder != null) {
1643 mSurfaceHolder.mSurfaceLock.lock();
1644 mDrawingAllowed = true;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07001645 }
Romain Guy812ccbe2010-06-01 14:07:24 -07001646
Romain Guyc361da82010-10-25 15:29:10 -07001647 boolean hwInitialized = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 boolean contentInsetsChanged = false;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07001649 boolean hadSurface = mSurface.isValid();
Romain Guy812ccbe2010-06-01 14:07:24 -07001650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 try {
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07001652 if (DEBUG_LAYOUT) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001653 Log.i(mTag, "host=w:" + host.getMeasuredWidth() + ", h:" +
Dianne Hackborn189ee182010-12-02 21:48:53 -08001654 host.getMeasuredHeight() + ", params=" + params);
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07001655 }
Romain Guy2a83f002011-01-18 18:28:21 -08001656
John Reckf7d9c1d2014-04-09 10:01:03 -07001657 if (mAttachInfo.mHardwareRenderer != null) {
1658 // relayoutWindow may decide to destroy mSurface. As that decision
1659 // happens in WindowManager service, we need to be defensive here
1660 // and stop using the surface in case it gets destroyed.
John Reck01a5ea32014-12-03 13:01:07 -08001661 if (mAttachInfo.mHardwareRenderer.pauseSurface(mSurface)) {
1662 // Animations were running so we need to push a frame
1663 // to resume them
1664 mDirty.set(0, 0, mWidth, mHeight);
1665 }
John Reckba6adf62015-02-19 14:36:50 -08001666 mChoreographer.mFrameInfo.addFlags(FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED);
John Reckf7d9c1d2014-04-09 10:01:03 -07001667 }
Romain Guy2a83f002011-01-18 18:28:21 -08001668 final int surfaceGenerationId = mSurface.getGenerationId();
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07001669 relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
1670
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001671 if (DEBUG_LAYOUT) Log.v(mTag, "relayout: frame=" + frame.toShortString()
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001672 + " overscan=" + mPendingOverscanInsets.toShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 + " content=" + mPendingContentInsets.toShortString()
1674 + " visible=" + mPendingVisibleInsets.toShortString()
Adrian Roosfa104232014-06-20 16:10:14 -07001675 + " visible=" + mPendingStableInsets.toShortString()
Filip Gruszczynski0ec13282015-06-25 11:26:01 -07001676 + " outsets=" + mPendingOutsets.toShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677 + " surface=" + mSurface);
Romain Guy8506ab42009-06-11 17:35:47 -07001678
Dianne Hackborn694f79b2010-03-17 19:44:59 -07001679 if (mPendingConfiguration.seq != 0) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001680 if (DEBUG_CONFIGURATION) Log.v(mTag, "Visible with new config: "
Dianne Hackborn694f79b2010-03-17 19:44:59 -07001681 + mPendingConfiguration);
riddle_hsu164725c2015-11-12 14:07:12 +08001682 updateConfiguration(new Configuration(mPendingConfiguration), !mFirst);
Dianne Hackborn694f79b2010-03-17 19:44:59 -07001683 mPendingConfiguration.seq = 0;
1684 }
Dianne Hackborn3556c9a2012-05-04 16:31:25 -07001685
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001686 final boolean overscanInsetsChanged = !mPendingOverscanInsets.equals(
1687 mAttachInfo.mOverscanInsets);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 contentInsetsChanged = !mPendingContentInsets.equals(
1689 mAttachInfo.mContentInsets);
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001690 final boolean visibleInsetsChanged = !mPendingVisibleInsets.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 mAttachInfo.mVisibleInsets);
Adrian Roosfa104232014-06-20 16:10:14 -07001692 final boolean stableInsetsChanged = !mPendingStableInsets.equals(
1693 mAttachInfo.mStableInsets);
Filip Gruszczynski2217f612015-05-26 11:32:08 -07001694 final boolean outsetsChanged = !mPendingOutsets.equals(mAttachInfo.mOutsets);
Chong Zhangf4abc2b2015-11-12 23:40:58 -08001695 final boolean surfaceSizeChanged = (relayoutResult
1696 & WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 if (contentInsetsChanged) {
1698 mAttachInfo.mContentInsets.set(mPendingContentInsets);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001699 if (DEBUG_LAYOUT) Log.v(mTag, "Content insets changing to: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 + mAttachInfo.mContentInsets);
1701 }
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001702 if (overscanInsetsChanged) {
1703 mAttachInfo.mOverscanInsets.set(mPendingOverscanInsets);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001704 if (DEBUG_LAYOUT) Log.v(mTag, "Overscan insets changing to: "
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001705 + mAttachInfo.mOverscanInsets);
1706 // Need to relayout with content insets.
1707 contentInsetsChanged = true;
1708 }
Adrian Roosfa104232014-06-20 16:10:14 -07001709 if (stableInsetsChanged) {
1710 mAttachInfo.mStableInsets.set(mPendingStableInsets);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001711 if (DEBUG_LAYOUT) Log.v(mTag, "Decor insets changing to: "
Adrian Roosfa104232014-06-20 16:10:14 -07001712 + mAttachInfo.mStableInsets);
1713 // Need to relayout with content insets.
1714 contentInsetsChanged = true;
1715 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001716 if (contentInsetsChanged || mLastSystemUiVisibility !=
Adrian Roosfa104232014-06-20 16:10:14 -07001717 mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested
Filip Gruszczynski2217f612015-05-26 11:32:08 -07001718 || mLastOverscanRequested != mAttachInfo.mOverscanRequested
1719 || outsetsChanged) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001720 mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001721 mLastOverscanRequested = mAttachInfo.mOverscanRequested;
Filip Gruszczynski2217f612015-05-26 11:32:08 -07001722 mAttachInfo.mOutsets.set(mPendingOutsets);
Adrian Roosfa104232014-06-20 16:10:14 -07001723 mApplyInsetsRequested = false;
Adam Powell2accbf92014-04-16 23:14:57 +00001724 dispatchApplyInsets(host);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726 if (visibleInsetsChanged) {
1727 mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001728 if (DEBUG_LAYOUT) Log.v(mTag, "Visible insets changing to: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 + mAttachInfo.mVisibleInsets);
1730 }
1731
1732 if (!hadSurface) {
1733 if (mSurface.isValid()) {
1734 // If we are creating a new surface, then we need to
1735 // completely redraw it. Also, when we get to the
1736 // point of drawing it we will hold off and schedule
1737 // a new traversal instead. This is so we can tell the
1738 // window manager about all of the windows being displayed
1739 // before actually drawing them, so it can display then
1740 // all at once.
1741 newSurface = true;
Jeff Brown96e942d2011-11-30 19:55:01 -08001742 mFullRedrawNeeded = true;
Jack Palevich61a6e682009-10-09 17:37:50 -07001743 mPreviousTransparentRegion.setEmpty();
Romain Guy8506ab42009-06-11 17:35:47 -07001744
John Reck63005e62015-05-19 15:00:13 -07001745 // Only initialize up-front if transparent regions are not
1746 // requested, otherwise defer to see if the entire window
1747 // will be transparent
Romain Guyb051e892010-09-28 19:09:36 -07001748 if (mAttachInfo.mHardwareRenderer != null) {
Dianne Hackborn64825172011-03-02 21:32:58 -08001749 try {
Romain Guy786fc932012-07-24 16:24:56 -07001750 hwInitialized = mAttachInfo.mHardwareRenderer.initialize(
John Reck79d81e62013-11-05 13:26:57 -08001751 mSurface);
John Reck63005e62015-05-19 15:00:13 -07001752 if (hwInitialized && (host.mPrivateFlags
1753 & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
1754 // Don't pre-allocate if transparent regions
1755 // are requested as they may not be needed
1756 mSurface.allocateBuffers();
1757 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07001758 } catch (OutOfResourcesException e) {
Romain Guy3696779b2013-01-28 14:04:07 -08001759 handleOutOfResourcesException(e);
Dianne Hackborn64825172011-03-02 21:32:58 -08001760 return;
1761 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 }
1763 }
1764 } else if (!mSurface.isValid()) {
1765 // If the surface has been removed, then reset the scroll
1766 // positions.
Svetoslav Ganov149567f2013-01-08 15:23:34 -08001767 if (mLastScrolledFocus != null) {
1768 mLastScrolledFocus.clear();
1769 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 mScrollY = mCurScrollY = 0;
Adrian Roos0e7ae4e2014-10-01 15:33:22 +02001771 if (mView instanceof RootViewSurfaceTaker) {
1772 ((RootViewSurfaceTaker) mView).onRootViewScrollYChanged(mCurScrollY);
1773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 if (mScroller != null) {
1775 mScroller.abortAnimation();
1776 }
Romain Guy1d0c7082011-08-03 16:22:24 -07001777 // Our surface is gone
1778 if (mAttachInfo.mHardwareRenderer != null &&
1779 mAttachInfo.mHardwareRenderer.isEnabled()) {
John Reckf47a5942014-06-30 16:20:04 -07001780 mAttachInfo.mHardwareRenderer.destroy();
Romain Guy1d0c7082011-08-03 16:22:24 -07001781 }
Chong Zhangf4abc2b2015-11-12 23:40:58 -08001782 } else if ((surfaceGenerationId != mSurface.getGenerationId()
1783 || surfaceSizeChanged)
1784 && mSurfaceHolder == null
1785 && mAttachInfo.mHardwareRenderer != null) {
Jeff Brown96e942d2011-11-30 19:55:01 -08001786 mFullRedrawNeeded = true;
Dianne Hackborn64825172011-03-02 21:32:58 -08001787 try {
Chong Zhangf4abc2b2015-11-12 23:40:58 -08001788 // Need to do updateSurface (which leads to CanvasContext::setSurface and
1789 // re-create the EGLSurface) if either the Surface changed (as indicated by
1790 // generation id), or WindowManager changed the surface size. The latter is
1791 // because on some chips, changing the consumer side's BufferQueue size may
1792 // not take effect immediately unless we create a new EGLSurface.
1793 // Note that frame size change doesn't always imply surface size change (eg.
1794 // drag resizing uses fullscreen surface), need to check surfaceSizeChanged
1795 // flag from WindowManager.
John Reck79d81e62013-11-05 13:26:57 -08001796 mAttachInfo.mHardwareRenderer.updateSurface(mSurface);
Igor Murashkina86ab6402013-08-30 12:58:36 -07001797 } catch (OutOfResourcesException e) {
Romain Guy3696779b2013-01-28 14:04:07 -08001798 handleOutOfResourcesException(e);
Dianne Hackborn64825172011-03-02 21:32:58 -08001799 return;
1800 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 }
Chong Zhang0275e392015-09-17 10:41:44 -07001802
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001803 final boolean freeformResizing = (relayoutResult
1804 & WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM) != 0;
1805 final boolean dockedResizing = (relayoutResult
1806 & WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED) != 0;
1807 final boolean dragResizing = freeformResizing || dockedResizing;
Chong Zhang0275e392015-09-17 10:41:44 -07001808 if (mDragResizing != dragResizing) {
Skuhneb8160872015-09-22 09:51:39 -07001809 if (dragResizing) {
Jorim Jaggi9511b0f2016-01-29 19:12:44 -08001810 startDragResizing(mPendingBackDropFrame,
1811 mWinFrame.equals(mPendingBackDropFrame), mPendingVisibleInsets,
1812 mPendingStableInsets);
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001813 mResizeMode = freeformResizing
1814 ? RESIZE_MODE_FREEFORM
1815 : RESIZE_MODE_DOCKED_DIVIDER;
Skuhneb8160872015-09-22 09:51:39 -07001816 } else {
1817 // We shouldn't come here, but if we come we should end the resize.
1818 endDragResizing();
1819 }
Chong Zhang0275e392015-09-17 10:41:44 -07001820 }
Skuhneb8160872015-09-22 09:51:39 -07001821 if (!USE_MT_RENDERER) {
1822 if (dragResizing) {
1823 mCanvasOffsetX = mWinFrame.left;
1824 mCanvasOffsetY = mWinFrame.top;
1825 } else {
1826 mCanvasOffsetX = mCanvasOffsetY = 0;
1827 }
Chong Zhang0275e392015-09-17 10:41:44 -07001828 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 } catch (RemoteException e) {
1830 }
Romain Guy1d0c7082011-08-03 16:22:24 -07001831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 if (DEBUG_ORIENTATION) Log.v(
Jeff Brownc5ed5912010-07-14 18:48:53 -07001833 TAG, "Relayout returned: frame=" + frame + ", surface=" + mSurface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001834
Chris Craikd36a81f2014-07-17 10:16:51 -07001835 mAttachInfo.mWindowLeft = frame.left;
1836 mAttachInfo.mWindowTop = frame.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837
1838 // !!FIXME!! This next section handles the case where we did not get the
1839 // window size we asked for. We should avoid this by getting a maximum size from
1840 // the window session beforehand.
Dianne Hackborn3556c9a2012-05-04 16:31:25 -07001841 if (mWidth != frame.width() || mHeight != frame.height()) {
Dianne Hackborn3556c9a2012-05-04 16:31:25 -07001842 mWidth = frame.width();
1843 mHeight = frame.height();
1844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001845
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07001846 if (mSurfaceHolder != null) {
1847 // The app owns the surface; tell it about what is going on.
1848 if (mSurface.isValid()) {
1849 // XXX .copyFrom() doesn't work!
1850 //mSurfaceHolder.mSurface.copyFrom(mSurface);
1851 mSurfaceHolder.mSurface = mSurface;
1852 }
Jeff Brown30bc34f2011-01-25 12:56:56 -08001853 mSurfaceHolder.setSurfaceFrameSize(mWidth, mHeight);
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07001854 mSurfaceHolder.mSurfaceLock.unlock();
1855 if (mSurface.isValid()) {
1856 if (!hadSurface) {
1857 mSurfaceHolder.ungetCallbacks();
1858
1859 mIsCreating = true;
1860 mSurfaceHolderCallback.surfaceCreated(mSurfaceHolder);
1861 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
1862 if (callbacks != null) {
1863 for (SurfaceHolder.Callback c : callbacks) {
1864 c.surfaceCreated(mSurfaceHolder);
1865 }
1866 }
1867 surfaceChanged = true;
1868 }
1869 if (surfaceChanged) {
1870 mSurfaceHolderCallback.surfaceChanged(mSurfaceHolder,
1871 lp.format, mWidth, mHeight);
1872 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
1873 if (callbacks != null) {
1874 for (SurfaceHolder.Callback c : callbacks) {
1875 c.surfaceChanged(mSurfaceHolder, lp.format,
1876 mWidth, mHeight);
1877 }
1878 }
1879 }
1880 mIsCreating = false;
1881 } else if (hadSurface) {
1882 mSurfaceHolder.ungetCallbacks();
1883 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
1884 mSurfaceHolderCallback.surfaceDestroyed(mSurfaceHolder);
1885 if (callbacks != null) {
1886 for (SurfaceHolder.Callback c : callbacks) {
1887 c.surfaceDestroyed(mSurfaceHolder);
1888 }
1889 }
1890 mSurfaceHolder.mSurfaceLock.lock();
Jozef BABJAK93c5b6a2011-02-22 09:33:19 +01001891 try {
1892 mSurfaceHolder.mSurface = new Surface();
1893 } finally {
1894 mSurfaceHolder.mSurfaceLock.unlock();
1895 }
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07001896 }
1897 }
Romain Guy53389bd2010-09-07 17:16:32 -07001898
John Reck51aaf902015-12-02 15:08:07 -08001899 final ThreadedRenderer hardwareRenderer = mAttachInfo.mHardwareRenderer;
Alan Viverette50210d92015-05-14 18:05:36 -07001900 if (hardwareRenderer != null && hardwareRenderer.isEnabled()) {
1901 if (hwInitialized
1902 || mWidth != hardwareRenderer.getWidth()
1903 || mHeight != hardwareRenderer.getHeight()) {
1904 hardwareRenderer.setup(mWidth, mHeight, mAttachInfo,
1905 mWindowAttributes.surfaceInsets);
Romain Guy03985752011-07-11 15:33:51 -07001906 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001907 }
1908
Craig Mautner72d6f212015-02-19 16:33:09 -08001909 if (!mStopped || mReportNextDraw) {
Dianne Hackbornce418e62011-03-01 14:31:38 -08001910 boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
Jeff Brown98365d72012-08-19 20:30:52 -07001911 (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
Dianne Hackbornce418e62011-03-01 14:31:38 -08001912 if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
1913 || mHeight != host.getMeasuredHeight() || contentInsetsChanged) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001914 int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
1915 int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
Igor Murashkina86ab6402013-08-30 12:58:36 -07001916
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001917 if (DEBUG_LAYOUT) Log.v(mTag, "Ooops, something changed! mWidth="
Dianne Hackbornce418e62011-03-01 14:31:38 -08001918 + mWidth + " measuredWidth=" + host.getMeasuredWidth()
1919 + " mHeight=" + mHeight
1920 + " measuredHeight=" + host.getMeasuredHeight()
1921 + " coveredInsetsChanged=" + contentInsetsChanged);
Igor Murashkina86ab6402013-08-30 12:58:36 -07001922
Dianne Hackbornce418e62011-03-01 14:31:38 -08001923 // Ask host how big it wants to be
Jeff Brownc8d2668b2012-05-16 17:23:59 -07001924 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
Igor Murashkina86ab6402013-08-30 12:58:36 -07001925
Dianne Hackbornce418e62011-03-01 14:31:38 -08001926 // Implementation of weights from WindowManager.LayoutParams
1927 // We just grow the dimensions as needed and re-measure if
1928 // needs be
1929 int width = host.getMeasuredWidth();
1930 int height = host.getMeasuredHeight();
1931 boolean measureAgain = false;
Igor Murashkina86ab6402013-08-30 12:58:36 -07001932
Dianne Hackbornce418e62011-03-01 14:31:38 -08001933 if (lp.horizontalWeight > 0.0f) {
1934 width += (int) ((mWidth - width) * lp.horizontalWeight);
1935 childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width,
1936 MeasureSpec.EXACTLY);
1937 measureAgain = true;
1938 }
1939 if (lp.verticalWeight > 0.0f) {
1940 height += (int) ((mHeight - height) * lp.verticalWeight);
1941 childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
1942 MeasureSpec.EXACTLY);
1943 measureAgain = true;
1944 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07001945
Dianne Hackbornce418e62011-03-01 14:31:38 -08001946 if (measureAgain) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001947 if (DEBUG_LAYOUT) Log.v(mTag,
Dianne Hackbornce418e62011-03-01 14:31:38 -08001948 "And hey let's measure once more: width=" + width
1949 + " height=" + height);
Jeff Brownc8d2668b2012-05-16 17:23:59 -07001950 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
Dianne Hackbornce418e62011-03-01 14:31:38 -08001951 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07001952
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001953 layoutRequested = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001955 }
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -07001956 } else {
1957 // Not the first pass and no window/insets/visibility change but the window
1958 // may have moved and we need check that and if so to update the left and right
1959 // in the attach info. We translate only the window frame since on window move
1960 // the window manager tells us only for the new frame but the insets are the
1961 // same and we do not want to translate them more than once.
Jorim Jaggi2e95a482016-01-14 17:36:55 -08001962 maybeHandleWindowMove(frame);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001963 }
1964
Craig Mautner72d6f212015-02-19 16:33:09 -08001965 final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001966 boolean triggerGlobalLayoutListener = didLayout
Chris Craikd36a81f2014-07-17 10:16:51 -07001967 || mAttachInfo.mRecomputeGlobalAttributes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001968 if (didLayout) {
Chet Haase3efa7b52012-12-03 08:33:17 -08001969 performLayout(lp, desiredWindowWidth, desiredWindowHeight);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001970
Mathias Agopian54e3d3842013-04-12 15:13:12 -07001971 // By this point all views have been sized and positioned
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001972 // We can compute the transparent area
1973
Dianne Hackborn4702a852012-08-17 15:18:29 -07001974 if ((host.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 // start out transparent
1976 // TODO: AVOID THAT CALL BY CACHING THE RESULT?
1977 host.getLocationInWindow(mTmpLocation);
1978 mTransparentRegion.set(mTmpLocation[0], mTmpLocation[1],
1979 mTmpLocation[0] + host.mRight - host.mLeft,
1980 mTmpLocation[1] + host.mBottom - host.mTop);
1981
1982 host.gatherTransparentRegion(mTransparentRegion);
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001983 if (mTranslator != null) {
1984 mTranslator.translateRegionInWindowToScreen(mTransparentRegion);
1985 }
1986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001987 if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {
1988 mPreviousTransparentRegion.set(mTransparentRegion);
Mathias Agopian54e3d3842013-04-12 15:13:12 -07001989 mFullRedrawNeeded = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 // reconfigure window manager
1991 try {
Jeff Brown98365d72012-08-19 20:30:52 -07001992 mWindowSession.setTransparentRegion(mWindow, mTransparentRegion);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 } catch (RemoteException e) {
1994 }
1995 }
1996 }
1997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001998 if (DBG) {
1999 System.out.println("======================================");
Chet Haase4610eef2015-12-03 07:38:11 -08002000 System.out.println("performTraversals -- after setFrame");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 host.debug();
2002 }
2003 }
2004
2005 if (triggerGlobalLayoutListener) {
Chris Craikd36a81f2014-07-17 10:16:51 -07002006 mAttachInfo.mRecomputeGlobalAttributes = false;
2007 mAttachInfo.mTreeObserver.dispatchOnGlobalLayout();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002008 }
2009
2010 if (computesInternalInsets) {
Jeff Brownfbf09772011-01-16 14:06:57 -08002011 // Clear the original insets.
Chris Craikd36a81f2014-07-17 10:16:51 -07002012 final ViewTreeObserver.InternalInsetsInfo insets = mAttachInfo.mGivenInternalInsets;
Jeff Brownfbf09772011-01-16 14:06:57 -08002013 insets.reset();
2014
2015 // Compute new insets in place.
Chris Craikd36a81f2014-07-17 10:16:51 -07002016 mAttachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets);
2017 mAttachInfo.mHasNonEmptyGivenInternalInsets = !insets.isEmpty();
Jeff Brownfbf09772011-01-16 14:06:57 -08002018
2019 // Tell the window manager.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020 if (insetsPending || !mLastGivenInsets.equals(insets)) {
2021 mLastGivenInsets.set(insets);
Jeff Brownfbf09772011-01-16 14:06:57 -08002022
2023 // Translate insets to screen coordinates if needed.
2024 final Rect contentInsets;
2025 final Rect visibleInsets;
2026 final Region touchableRegion;
2027 if (mTranslator != null) {
2028 contentInsets = mTranslator.getTranslatedContentInsets(insets.contentInsets);
2029 visibleInsets = mTranslator.getTranslatedVisibleInsets(insets.visibleInsets);
2030 touchableRegion = mTranslator.getTranslatedTouchableArea(insets.touchableRegion);
2031 } else {
2032 contentInsets = insets.contentInsets;
2033 visibleInsets = insets.visibleInsets;
2034 touchableRegion = insets.touchableRegion;
2035 }
2036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002037 try {
Jeff Brown98365d72012-08-19 20:30:52 -07002038 mWindowSession.setInsets(mWindow, insets.mTouchableInsets,
Jeff Brownfbf09772011-01-16 14:06:57 -08002039 contentInsets, visibleInsets, touchableRegion);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002040 } catch (RemoteException e) {
2041 }
2042 }
2043 }
Romain Guy8506ab42009-06-11 17:35:47 -07002044
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002045 if (mFirst) {
2046 // handle first focus request
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002047 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "First: mView.hasFocus()="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 + mView.hasFocus());
2049 if (mView != null) {
2050 if (!mView.hasFocus()) {
2051 mView.requestFocus(View.FOCUS_FORWARD);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002052 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "First: requested focused view="
Svetoslav Ganov149567f2013-01-08 15:23:34 -08002053 + mView.findFocus());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054 } else {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002055 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "First: existing focused view="
Svetoslav Ganov149567f2013-01-08 15:23:34 -08002056 + mView.findFocus());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 }
2058 }
2059 }
2060
Alan Viverette64bf97a2015-09-18 16:42:00 -04002061 final boolean changedVisibility = (viewVisibilityChanged || mFirst) && isViewVisible;
2062 final boolean hasWindowFocus = mAttachInfo.mHasWindowFocus && isViewVisible;
2063 final boolean regainedFocus = hasWindowFocus && mLostWindowFocus;
2064 if (regainedFocus) {
2065 mLostWindowFocus = false;
2066 } else if (!hasWindowFocus && mHadWindowFocus) {
2067 mLostWindowFocus = true;
2068 }
2069
2070 if (changedVisibility || regainedFocus) {
2071 host.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
2072 }
2073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002074 mFirst = false;
2075 mWillDrawSoon = false;
2076 mNewSurfaceNeeded = false;
Jorim Jaggi4846ee32016-01-07 17:39:12 +01002077 mActivityRelaunched = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078 mViewVisibility = viewVisibility;
Alan Viverette64bf97a2015-09-18 16:42:00 -04002079 mHadWindowFocus = hasWindowFocus;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002080
Alan Viverette64bf97a2015-09-18 16:42:00 -04002081 if (hasWindowFocus && !isInLocalFocusMode()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082 final boolean imTarget = WindowManager.LayoutParams
2083 .mayUseInputMethod(mWindowAttributes.flags);
2084 if (imTarget != mLastWasImTarget) {
2085 mLastWasImTarget = imTarget;
2086 InputMethodManager imm = InputMethodManager.peekInstance();
2087 if (imm != null && imTarget) {
Alan Viverette64bf97a2015-09-18 16:42:00 -04002088 imm.onPreWindowFocus(mView, hasWindowFocus);
Yohei Yukawa5f059652015-05-14 22:16:41 -07002089 imm.onPostWindowFocus(mView, mView.findFocus(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002090 mWindowAttributes.softInputMode,
2091 !mHasHadWindowFocus, mWindowAttributes.flags);
2092 }
2093 }
2094 }
Romain Guy8506ab42009-06-11 17:35:47 -07002095
Jeff Brown96e942d2011-11-30 19:55:01 -08002096 // Remember if we must report the next draw.
Jeff Brown98365d72012-08-19 20:30:52 -07002097 if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
Jeff Brown96e942d2011-11-30 19:55:01 -08002098 mReportNextDraw = true;
2099 }
2100
Alan Viverette64bf97a2015-09-18 16:42:00 -04002101 boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002102
Jorim Jaggi3127c2a42016-01-26 18:48:44 -08002103 if (!cancelDraw) {
Chet Haase9c450412015-10-01 13:25:58 -07002104 if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
2105 for (int i = 0; i < mPendingTransitions.size(); ++i) {
2106 mPendingTransitions.get(i).startChangingAnimations();
Chet Haased56c6952011-09-07 08:46:23 -07002107 }
Chet Haase9c450412015-10-01 13:25:58 -07002108 mPendingTransitions.clear();
Chet Haased56c6952011-09-07 08:46:23 -07002109 }
Chet Haase9c450412015-10-01 13:25:58 -07002110
2111 performDraw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002112 } else {
Alan Viverette64bf97a2015-09-18 16:42:00 -04002113 if (isViewVisible) {
Chris Wren78cb7cf2012-05-15 12:36:44 -04002114 // Try again
2115 scheduleTraversals();
2116 } else if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
Chet Haased56c6952011-09-07 08:46:23 -07002117 for (int i = 0; i < mPendingTransitions.size(); ++i) {
2118 mPendingTransitions.get(i).endChangingAnimations();
2119 }
2120 mPendingTransitions.clear();
2121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002122 }
Craig Mautnerdf2390a2012-08-29 20:59:22 -07002123
2124 mIsInTraversal = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002125 }
2126
Jorim Jaggi2e95a482016-01-14 17:36:55 -08002127 private void maybeHandleWindowMove(Rect frame) {
2128
2129 // TODO: Well, we are checking whether the frame has changed similarly
2130 // to how this is done for the insets. This is however incorrect since
2131 // the insets and the frame are translated. For example, the old frame
2132 // was (1, 1 - 1, 1) and was translated to say (2, 2 - 2, 2), now the new
2133 // reported frame is (2, 2 - 2, 2) which implies no change but this is not
2134 // true since we are comparing a not translated value to a translated one.
2135 // This scenario is rare but we may want to fix that.
2136
2137 final boolean windowMoved = mAttachInfo.mWindowLeft != frame.left
2138 || mAttachInfo.mWindowTop != frame.top;
2139 if (windowMoved) {
2140 if (mTranslator != null) {
2141 mTranslator.translateRectInScreenToAppWinFrame(frame);
2142 }
2143 mAttachInfo.mWindowLeft = frame.left;
2144 mAttachInfo.mWindowTop = frame.top;
2145
2146 // Update the light position for the new window offsets.
2147 if (mAttachInfo.mHardwareRenderer != null) {
2148 mAttachInfo.mHardwareRenderer.setLightCenter(mAttachInfo);
2149 }
2150 }
2151 }
Jorim Jaggi3127c2a42016-01-26 18:48:44 -08002152
Romain Guy3696779b2013-01-28 14:04:07 -08002153 private void handleOutOfResourcesException(Surface.OutOfResourcesException e) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002154 Log.e(mTag, "OutOfResourcesException initializing HW surface", e);
Romain Guy3696779b2013-01-28 14:04:07 -08002155 try {
2156 if (!mWindowSession.outOfMemory(mWindow) &&
2157 Process.myUid() != Process.SYSTEM_UID) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002158 Slog.w(mTag, "No processes killed for memory; killing self");
Romain Guy3696779b2013-01-28 14:04:07 -08002159 Process.killProcess(Process.myPid());
2160 }
2161 } catch (RemoteException ex) {
2162 }
2163 mLayoutRequested = true; // ask wm for a new surface next time.
2164 }
2165
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002166 private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
2167 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
2168 try {
2169 mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
2170 } finally {
2171 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
2172 }
2173 }
2174
Chet Haase97140572012-09-13 14:56:47 -07002175 /**
2176 * Called by {@link android.view.View#isInLayout()} to determine whether the view hierarchy
2177 * is currently undergoing a layout pass.
2178 *
2179 * @return whether the view hierarchy is currently undergoing a layout pass
2180 */
2181 boolean isInLayout() {
2182 return mInLayout;
2183 }
2184
2185 /**
Chet Haasecc699b42012-12-13 09:06:55 -08002186 * Called by {@link android.view.View#requestLayout()} if the view hierarchy is currently
2187 * undergoing a layout pass. requestLayout() should not generally be called during layout,
2188 * unless the container hierarchy knows what it is doing (i.e., it is fine as long as
2189 * all children in that container hierarchy are measured and laid out at the end of the layout
2190 * pass for that container). If requestLayout() is called anyway, we handle it correctly
2191 * by registering all requesters during a frame as it proceeds. At the end of the frame,
2192 * we check all of those views to see if any still have pending layout requests, which
2193 * indicates that they were not correctly handled by their container hierarchy. If that is
2194 * the case, we clear all such flags in the tree, to remove the buggy flag state that leads
2195 * to blank containers, and force a second request/measure/layout pass in this frame. If
Chet Haase97140572012-09-13 14:56:47 -07002196 * more requestLayout() calls are received during that second layout pass, we post those
Chet Haasecc699b42012-12-13 09:06:55 -08002197 * requests to the next frame to avoid possible infinite loops.
2198 *
2199 * <p>The return value from this method indicates whether the request should proceed
2200 * (if it is a request during the first layout pass) or should be skipped and posted to the
2201 * next frame (if it is a request during the second layout pass).</p>
Chet Haase97140572012-09-13 14:56:47 -07002202 *
2203 * @param view the view that requested the layout.
Chet Haasecc699b42012-12-13 09:06:55 -08002204 *
2205 * @return true if request should proceed, false otherwise.
Chet Haase97140572012-09-13 14:56:47 -07002206 */
Chet Haasecc699b42012-12-13 09:06:55 -08002207 boolean requestLayoutDuringLayout(final View view) {
2208 if (view.mParent == null || view.mAttachInfo == null) {
2209 // Would not normally trigger another layout, so just let it pass through as usual
2210 return true;
2211 }
Chet Haase107a4822013-03-13 06:46:50 -07002212 if (!mLayoutRequesters.contains(view)) {
2213 mLayoutRequesters.add(view);
2214 }
Chet Haase97140572012-09-13 14:56:47 -07002215 if (!mHandlingLayoutInLayoutRequest) {
Chet Haase107a4822013-03-13 06:46:50 -07002216 // Let the request proceed normally; it will be processed in a second layout pass
2217 // if necessary
Chet Haasecc699b42012-12-13 09:06:55 -08002218 return true;
Chet Haase97140572012-09-13 14:56:47 -07002219 } else {
Chet Haase107a4822013-03-13 06:46:50 -07002220 // Don't let the request proceed during the second layout pass.
2221 // It will post to the next frame instead.
Chet Haasecc699b42012-12-13 09:06:55 -08002222 return false;
Chet Haase97140572012-09-13 14:56:47 -07002223 }
2224 }
2225
Chet Haase3efa7b52012-12-03 08:33:17 -08002226 private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,
2227 int desiredWindowHeight) {
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002228 mLayoutRequested = false;
2229 mScrollMayChange = true;
Chet Haase97140572012-09-13 14:56:47 -07002230 mInLayout = true;
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002231
2232 final View host = mView;
2233 if (DEBUG_ORIENTATION || DEBUG_LAYOUT) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002234 Log.v(mTag, "Laying out " + host + " to (" +
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002235 host.getMeasuredWidth() + ", " + host.getMeasuredHeight() + ")");
2236 }
2237
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002238 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "layout");
2239 try {
2240 host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
Chet Haasecc699b42012-12-13 09:06:55 -08002241
Chet Haased5a83522012-11-21 16:24:44 -08002242 mInLayout = false;
Chet Haase97140572012-09-13 14:56:47 -07002243 int numViewsRequestingLayout = mLayoutRequesters.size();
2244 if (numViewsRequestingLayout > 0) {
Chet Haasecc699b42012-12-13 09:06:55 -08002245 // requestLayout() was called during layout.
2246 // If no layout-request flags are set on the requesting views, there is no problem.
2247 // If some requests are still pending, then we need to clear those flags and do
2248 // a full request/measure/layout pass to handle this situation.
Chet Haase107a4822013-03-13 06:46:50 -07002249 ArrayList<View> validLayoutRequesters = getValidLayoutRequesters(mLayoutRequesters,
2250 false);
2251 if (validLayoutRequesters != null) {
2252 // Set this flag to indicate that any further requests are happening during
2253 // the second pass, which may result in posting those requests to the next
2254 // frame instead
Chet Haasecc699b42012-12-13 09:06:55 -08002255 mHandlingLayoutInLayoutRequest = true;
Chet Haase107a4822013-03-13 06:46:50 -07002256
2257 // Process fresh layout requests, then measure and layout
2258 int numValidRequests = validLayoutRequesters.size();
Chet Haasecc699b42012-12-13 09:06:55 -08002259 for (int i = 0; i < numValidRequests; ++i) {
Chet Haase107a4822013-03-13 06:46:50 -07002260 final View view = validLayoutRequesters.get(i);
2261 Log.w("View", "requestLayout() improperly called by " + view +
2262 " during layout: running second layout pass");
2263 view.requestLayout();
Chet Haasecc699b42012-12-13 09:06:55 -08002264 }
2265 measureHierarchy(host, lp, mView.getContext().getResources(),
2266 desiredWindowWidth, desiredWindowHeight);
2267 mInLayout = true;
2268 host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
Chet Haase107a4822013-03-13 06:46:50 -07002269
Chet Haasecc699b42012-12-13 09:06:55 -08002270 mHandlingLayoutInLayoutRequest = false;
Chet Haase107a4822013-03-13 06:46:50 -07002271
2272 // Check the valid requests again, this time without checking/clearing the
2273 // layout flags, since requests happening during the second pass get noop'd
2274 validLayoutRequesters = getValidLayoutRequesters(mLayoutRequesters, true);
2275 if (validLayoutRequesters != null) {
2276 final ArrayList<View> finalRequesters = validLayoutRequesters;
2277 // Post second-pass requests to the next frame
2278 getRunQueue().post(new Runnable() {
2279 @Override
2280 public void run() {
2281 int numValidRequests = finalRequesters.size();
2282 for (int i = 0; i < numValidRequests; ++i) {
2283 final View view = finalRequesters.get(i);
2284 Log.w("View", "requestLayout() improperly called by " + view +
2285 " during second layout pass: posting in next frame");
2286 view.requestLayout();
2287 }
2288 }
2289 });
2290 }
Chet Haasecc699b42012-12-13 09:06:55 -08002291 }
Chet Haase107a4822013-03-13 06:46:50 -07002292
Chet Haase97140572012-09-13 14:56:47 -07002293 }
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002294 } finally {
2295 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
2296 }
Chet Haase97140572012-09-13 14:56:47 -07002297 mInLayout = false;
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002298 }
2299
Chet Haase107a4822013-03-13 06:46:50 -07002300 /**
2301 * This method is called during layout when there have been calls to requestLayout() during
2302 * layout. It walks through the list of views that requested layout to determine which ones
2303 * still need it, based on visibility in the hierarchy and whether they have already been
2304 * handled (as is usually the case with ListView children).
2305 *
2306 * @param layoutRequesters The list of views that requested layout during layout
2307 * @param secondLayoutRequests Whether the requests were issued during the second layout pass.
2308 * If so, the FORCE_LAYOUT flag was not set on requesters.
2309 * @return A list of the actual views that still need to be laid out.
2310 */
2311 private ArrayList<View> getValidLayoutRequesters(ArrayList<View> layoutRequesters,
2312 boolean secondLayoutRequests) {
2313
2314 int numViewsRequestingLayout = layoutRequesters.size();
2315 ArrayList<View> validLayoutRequesters = null;
2316 for (int i = 0; i < numViewsRequestingLayout; ++i) {
2317 View view = layoutRequesters.get(i);
2318 if (view != null && view.mAttachInfo != null && view.mParent != null &&
2319 (secondLayoutRequests || (view.mPrivateFlags & View.PFLAG_FORCE_LAYOUT) ==
2320 View.PFLAG_FORCE_LAYOUT)) {
2321 boolean gone = false;
2322 View parent = view;
2323 // Only trigger new requests for views in a non-GONE hierarchy
2324 while (parent != null) {
2325 if ((parent.mViewFlags & View.VISIBILITY_MASK) == View.GONE) {
2326 gone = true;
2327 break;
2328 }
2329 if (parent.mParent instanceof View) {
2330 parent = (View) parent.mParent;
2331 } else {
2332 parent = null;
2333 }
2334 }
2335 if (!gone) {
2336 if (validLayoutRequesters == null) {
2337 validLayoutRequesters = new ArrayList<View>();
2338 }
2339 validLayoutRequesters.add(view);
2340 }
2341 }
2342 }
2343 if (!secondLayoutRequests) {
2344 // If we're checking the layout flags, then we need to clean them up also
2345 for (int i = 0; i < numViewsRequestingLayout; ++i) {
2346 View view = layoutRequesters.get(i);
2347 while (view != null &&
2348 (view.mPrivateFlags & View.PFLAG_FORCE_LAYOUT) != 0) {
2349 view.mPrivateFlags &= ~View.PFLAG_FORCE_LAYOUT;
2350 if (view.mParent instanceof View) {
2351 view = (View) view.mParent;
2352 } else {
2353 view = null;
2354 }
2355 }
2356 }
2357 }
2358 layoutRequesters.clear();
2359 return validLayoutRequesters;
2360 }
2361
Igor Murashkina86ab6402013-08-30 12:58:36 -07002362 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 public void requestTransparentRegion(View child) {
2364 // the test below should not fail unless someone is messing with us
2365 checkThread();
2366 if (mView == child) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07002367 mView.mPrivateFlags |= View.PFLAG_REQUEST_TRANSPARENT_REGIONS;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002368 // Need to make sure we re-evaluate the window attributes next
2369 // time around, to ensure the window has the correct format.
2370 mWindowAttributesChanged = true;
Romain Guyf21c9b02011-09-06 16:56:54 -07002371 mWindowAttributesChangesFlag = 0;
Mathias Agopian1bd80ad2010-11-04 17:13:39 -07002372 requestLayout();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002373 }
2374 }
2375
2376 /**
2377 * Figures out the measure spec for the root view in a window based on it's
2378 * layout params.
2379 *
2380 * @param windowSize
2381 * The available width or height of the window
2382 *
2383 * @param rootDimension
2384 * The layout params for one dimension (width or height) of the
2385 * window.
2386 *
2387 * @return The measure spec to use to measure the root view.
2388 */
Romain Guya998dff2012-03-23 18:58:36 -07002389 private static int getRootMeasureSpec(int windowSize, int rootDimension) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 int measureSpec;
2391 switch (rootDimension) {
2392
Romain Guy980a9382010-01-08 15:06:28 -08002393 case ViewGroup.LayoutParams.MATCH_PARENT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002394 // Window can't resize. Force root view to be windowSize.
2395 measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY);
2396 break;
2397 case ViewGroup.LayoutParams.WRAP_CONTENT:
2398 // Window can resize. Set max size for root view.
2399 measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST);
2400 break;
2401 default:
2402 // Window wants to be an exact size. Force root view to be that size.
2403 measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);
2404 break;
2405 }
2406 return measureSpec;
2407 }
2408
Alan Viveretteccb11e12014-07-08 16:04:02 -07002409 int mHardwareXOffset;
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002410 int mHardwareYOffset;
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002411
Igor Murashkina86ab6402013-08-30 12:58:36 -07002412 @Override
Chris Craikf6829a02015-03-10 10:28:59 -07002413 public void onHardwarePreDraw(DisplayListCanvas canvas) {
Alan Viveretteccb11e12014-07-08 16:04:02 -07002414 canvas.translate(-mHardwareXOffset, -mHardwareYOffset);
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002415 }
2416
Igor Murashkina86ab6402013-08-30 12:58:36 -07002417 @Override
Chris Craikf6829a02015-03-10 10:28:59 -07002418 public void onHardwarePostDraw(DisplayListCanvas canvas) {
Alan Viverette632af842014-10-28 13:45:11 -07002419 drawAccessibilityFocusedDrawableIfNeeded(canvas);
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002420 }
2421
Chet Haaseed30fd82011-04-22 16:18:45 -07002422 /**
2423 * @hide
2424 */
2425 void outputDisplayList(View view) {
Chris Craik356b5fe2015-07-07 10:39:36 -07002426 view.mRenderNode.output();
John Recke248bd12015-08-05 13:53:53 -07002427 if (mAttachInfo.mHardwareRenderer != null) {
2428 ((ThreadedRenderer)mAttachInfo.mHardwareRenderer).serializeDisplayListTree();
2429 }
Romain Guy59a12ca2011-06-09 17:48:21 -07002430 }
2431
2432 /**
2433 * @see #PROPERTY_PROFILE_RENDERING
2434 */
2435 private void profileRendering(boolean enabled) {
2436 if (mProfileRendering) {
2437 mRenderProfilingEnabled = enabled;
Chris Craikae4f32042013-02-07 12:57:10 -08002438
2439 if (mRenderProfiler != null) {
2440 mChoreographer.removeFrameCallback(mRenderProfiler);
2441 }
2442 if (mRenderProfilingEnabled) {
2443 if (mRenderProfiler == null) {
2444 mRenderProfiler = new Choreographer.FrameCallback() {
2445 @Override
2446 public void doFrame(long frameTimeNanos) {
2447 mDirty.set(0, 0, mWidth, mHeight);
2448 scheduleTraversals();
2449 if (mRenderProfilingEnabled) {
2450 mChoreographer.postFrameCallback(mRenderProfiler);
2451 }
Romain Guy59a12ca2011-06-09 17:48:21 -07002452 }
Chris Craikae4f32042013-02-07 12:57:10 -08002453 };
2454 }
Romain Guy5bb3c732012-11-29 17:52:58 -08002455 mChoreographer.postFrameCallback(mRenderProfiler);
Romain Guy59a12ca2011-06-09 17:48:21 -07002456 } else {
Romain Guy59a12ca2011-06-09 17:48:21 -07002457 mRenderProfiler = null;
Chet Haaseed30fd82011-04-22 16:18:45 -07002458 }
2459 }
2460 }
2461
Chet Haase2f2022a2011-10-11 06:41:59 -07002462 /**
2463 * Called from draw() when DEBUG_FPS is enabled
2464 */
2465 private void trackFPS() {
2466 // Tracks frames per second drawn. First value in a series of draws may be bogus
2467 // because it down not account for the intervening idle time
2468 long nowTime = System.currentTimeMillis();
2469 if (mFpsStartTime < 0) {
2470 mFpsStartTime = mFpsPrevTime = nowTime;
2471 mFpsNumFrames = 0;
2472 } else {
2473 ++mFpsNumFrames;
2474 String thisHash = Integer.toHexString(System.identityHashCode(this));
2475 long frameTime = nowTime - mFpsPrevTime;
2476 long totalTime = nowTime - mFpsStartTime;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002477 Log.v(mTag, "0x" + thisHash + "\tFrame time:\t" + frameTime);
Chet Haase2f2022a2011-10-11 06:41:59 -07002478 mFpsPrevTime = nowTime;
2479 if (totalTime > 1000) {
2480 float fps = (float) mFpsNumFrames * 1000 / totalTime;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002481 Log.v(mTag, "0x" + thisHash + "\tFPS:\t" + fps);
Chet Haase2f2022a2011-10-11 06:41:59 -07002482 mFpsStartTime = nowTime;
2483 mFpsNumFrames = 0;
2484 }
2485 }
2486 }
2487
Jeff Brown96e942d2011-11-30 19:55:01 -08002488 private void performDraw() {
Jeff Brownd912e1f2014-04-11 18:46:22 -07002489 if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
Craig Mautner006f0e42012-03-21 11:00:32 -07002490 return;
2491 }
Romain Guy7e4e5612012-03-05 14:37:29 -08002492
Jeff Brown96e942d2011-11-30 19:55:01 -08002493 final boolean fullRedrawNeeded = mFullRedrawNeeded;
2494 mFullRedrawNeeded = false;
Jeff Brown481c1572012-03-09 14:41:15 -08002495
Romain Guy1f59e5c2012-05-06 14:11:16 -07002496 mIsDrawing = true;
Jeff Brown481c1572012-03-09 14:41:15 -08002497 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
2498 try {
2499 draw(fullRedrawNeeded);
2500 } finally {
Romain Guy1f59e5c2012-05-06 14:11:16 -07002501 mIsDrawing = false;
Jeff Brown481c1572012-03-09 14:41:15 -08002502 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
2503 }
Jeff Brown96e942d2011-11-30 19:55:01 -08002504
John Reck119907c2014-08-14 09:02:01 -07002505 // For whatever reason we didn't create a HardwareRenderer, end any
2506 // hardware animations that are now dangling
2507 if (mAttachInfo.mPendingAnimatingRenderNodes != null) {
2508 final int count = mAttachInfo.mPendingAnimatingRenderNodes.size();
2509 for (int i = 0; i < count; i++) {
2510 mAttachInfo.mPendingAnimatingRenderNodes.get(i).endAllAnimators();
2511 }
2512 mAttachInfo.mPendingAnimatingRenderNodes.clear();
2513 }
2514
Jeff Brown96e942d2011-11-30 19:55:01 -08002515 if (mReportNextDraw) {
2516 mReportNextDraw = false;
Chong Zhang8dbd9ad2015-10-09 10:06:11 -07002517
2518 // if we're using multi-thread renderer, wait for the window frame draws
2519 if (mWindowDrawCountDown != null) {
2520 try {
2521 mWindowDrawCountDown.await();
2522 } catch (InterruptedException e) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002523 Log.e(mTag, "Window redraw count down interruped!");
Chong Zhang8dbd9ad2015-10-09 10:06:11 -07002524 }
2525 mWindowDrawCountDown = null;
2526 }
2527
John Reck28ad7b52014-04-07 16:59:25 -07002528 if (mAttachInfo.mHardwareRenderer != null) {
2529 mAttachInfo.mHardwareRenderer.fence();
2530 }
Jeff Brown96e942d2011-11-30 19:55:01 -08002531
2532 if (LOCAL_LOGV) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002533 Log.v(mTag, "FINISHED DRAWING: " + mWindowAttributes.getTitle());
Jeff Brown96e942d2011-11-30 19:55:01 -08002534 }
2535 if (mSurfaceHolder != null && mSurface.isValid()) {
2536 mSurfaceHolderCallback.surfaceRedrawNeeded(mSurfaceHolder);
2537 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
2538 if (callbacks != null) {
2539 for (SurfaceHolder.Callback c : callbacks) {
2540 if (c instanceof SurfaceHolder.Callback2) {
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -08002541 ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(mSurfaceHolder);
Jeff Brown96e942d2011-11-30 19:55:01 -08002542 }
2543 }
2544 }
2545 }
2546 try {
Jeff Brown98365d72012-08-19 20:30:52 -07002547 mWindowSession.finishDrawing(mWindow);
Jeff Brown96e942d2011-11-30 19:55:01 -08002548 } catch (RemoteException e) {
2549 }
2550 }
2551 }
2552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002553 private void draw(boolean fullRedrawNeeded) {
2554 Surface surface = mSurface;
Romain Guyfbb93fa2012-12-03 18:50:35 -08002555 if (!surface.isValid()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002556 return;
2557 }
2558
Chet Haase2f2022a2011-10-11 06:41:59 -07002559 if (DEBUG_FPS) {
2560 trackFPS();
2561 }
2562
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002563 if (!sFirstDrawComplete) {
2564 synchronized (sFirstDrawHandlers) {
2565 sFirstDrawComplete = true;
Romain Guy812ccbe2010-06-01 14:07:24 -07002566 final int count = sFirstDrawHandlers.size();
2567 for (int i = 0; i< count; i++) {
Jeff Browna175a5b2012-02-15 19:18:31 -08002568 mHandler.post(sFirstDrawHandlers.get(i));
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002569 }
2570 }
2571 }
Romain Guy59a12ca2011-06-09 17:48:21 -07002572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002573 scrollToRectOrFocus(null, false);
2574
Chris Craikd36a81f2014-07-17 10:16:51 -07002575 if (mAttachInfo.mViewScrollChanged) {
2576 mAttachInfo.mViewScrollChanged = false;
2577 mAttachInfo.mTreeObserver.dispatchOnScrollChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002578 }
Romain Guy8506ab42009-06-11 17:35:47 -07002579
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002580 boolean animating = mScroller != null && mScroller.computeScrollOffset();
Alan Viveretteccb11e12014-07-08 16:04:02 -07002581 final int curScrollY;
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002582 if (animating) {
Alan Viveretteccb11e12014-07-08 16:04:02 -07002583 curScrollY = mScroller.getCurrY();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002584 } else {
Alan Viveretteccb11e12014-07-08 16:04:02 -07002585 curScrollY = mScrollY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 }
Alan Viveretteccb11e12014-07-08 16:04:02 -07002587 if (mCurScrollY != curScrollY) {
2588 mCurScrollY = curScrollY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002589 fullRedrawNeeded = true;
Adrian Roos0e7ae4e2014-10-01 15:33:22 +02002590 if (mView instanceof RootViewSurfaceTaker) {
2591 ((RootViewSurfaceTaker) mView).onRootViewScrollYChanged(mCurScrollY);
2592 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 }
Jeff Brown96e942d2011-11-30 19:55:01 -08002594
Chris Craikd36a81f2014-07-17 10:16:51 -07002595 final float appScale = mAttachInfo.mApplicationScale;
2596 final boolean scalingRequired = mAttachInfo.mScalingRequired;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002597
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002598 int resizeAlpha = 0;
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002599
Jeff Brown96e942d2011-11-30 19:55:01 -08002600 final Rect dirty = mDirty;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07002601 if (mSurfaceHolder != null) {
2602 // The app owns the surface, we won't draw.
2603 dirty.setEmpty();
Derek Sollenberger8d948352015-07-16 09:27:59 -04002604 if (animating && mScroller != null) {
2605 mScroller.abortAnimation();
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002606 }
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07002607 return;
2608 }
Romain Guy58ef7fb2010-09-13 12:52:37 -07002609
2610 if (fullRedrawNeeded) {
Chris Craikd36a81f2014-07-17 10:16:51 -07002611 mAttachInfo.mIgnoreDirtyState = true;
Romain Guyc3166e12011-08-08 15:00:03 -07002612 dirty.set(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
Romain Guy58ef7fb2010-09-13 12:52:37 -07002613 }
Chet Haasead4f7032011-06-22 09:18:31 -07002614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 if (DEBUG_ORIENTATION || DEBUG_DRAW) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002616 Log.v(mTag, "Draw " + mView + "/"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002617 + mWindowAttributes.getTitle()
2618 + ": dirty={" + dirty.left + "," + dirty.top
2619 + "," + dirty.right + "," + dirty.bottom + "} surface="
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002620 + surface + " surface.isValid()=" + surface.isValid() + ", appScale:" +
2621 appScale + ", width=" + mWidth + ", height=" + mHeight);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 }
2623
Chris Craikd36a81f2014-07-17 10:16:51 -07002624 mAttachInfo.mTreeObserver.dispatchOnDraw();
Romain Guy25eba5c2012-04-04 17:29:03 -07002625
Chong Zhang0275e392015-09-17 10:41:44 -07002626 int xOffset = -mCanvasOffsetX;
2627 int yOffset = -mCanvasOffsetY + curScrollY;
Alan Viverettea51cab92014-07-16 15:15:49 -07002628 final WindowManager.LayoutParams params = mWindowAttributes;
2629 final Rect surfaceInsets = params != null ? params.surfaceInsets : null;
2630 if (surfaceInsets != null) {
2631 xOffset -= surfaceInsets.left;
2632 yOffset -= surfaceInsets.top;
2633
2634 // Offset dirty rect for surface insets.
2635 dirty.offset(surfaceInsets.left, surfaceInsets.right);
2636 }
2637
Alan Viverette632af842014-10-28 13:45:11 -07002638 boolean accessibilityFocusDirty = false;
2639 final Drawable drawable = mAttachInfo.mAccessibilityFocusDrawable;
2640 if (drawable != null) {
2641 final Rect bounds = mAttachInfo.mTmpInvalRect;
2642 final boolean hasFocus = getAccessibilityFocusedRect(bounds);
2643 if (!hasFocus) {
2644 bounds.setEmpty();
2645 }
2646 if (!bounds.equals(drawable.getBounds())) {
2647 accessibilityFocusDirty = true;
2648 }
2649 }
2650
John Reckba6adf62015-02-19 14:36:50 -08002651 mAttachInfo.mDrawingTime =
2652 mChoreographer.getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;
2653
Alan Viverette632af842014-10-28 13:45:11 -07002654 if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
Chris Craikd36a81f2014-07-17 10:16:51 -07002655 if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
Alan Viverette632af842014-10-28 13:45:11 -07002656 // If accessibility focus moved, always invalidate the root.
2657 boolean invalidateRoot = accessibilityFocusDirty;
2658
Jeff Brown96e942d2011-11-30 19:55:01 -08002659 // Draw with hardware renderer.
2660 mIsAnimating = false;
Alan Viverette632af842014-10-28 13:45:11 -07002661
John Reck0a973302014-07-16 13:29:45 -07002662 if (mHardwareYOffset != yOffset || mHardwareXOffset != xOffset) {
2663 mHardwareYOffset = yOffset;
2664 mHardwareXOffset = xOffset;
Alan Viverette632af842014-10-28 13:45:11 -07002665 invalidateRoot = true;
Alan Viverettef6cf1a02014-08-11 14:13:02 -07002666 }
2667
Alan Viverette632af842014-10-28 13:45:11 -07002668 if (invalidateRoot) {
2669 mAttachInfo.mHardwareRenderer.invalidateRoot();
2670 }
2671
Jeff Brown96e942d2011-11-30 19:55:01 -08002672 dirty.setEmpty();
2673
Skuhne980ee472015-10-06 11:31:31 -07002674 // Stage the content drawn size now. It will be transferred to the renderer
2675 // shortly before the draw commands get send to the renderer.
Chong Zhang8dbd9ad2015-10-09 10:06:11 -07002676 final boolean updated = updateContentDrawBounds();
2677
John Reck61375a82014-09-18 19:27:48 +00002678 mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
Chong Zhang8dbd9ad2015-10-09 10:06:11 -07002679
2680 if (updated) {
2681 requestDrawWindow();
2682 }
Romain Guy3696779b2013-01-28 14:04:07 -08002683 } else {
2684 // If we get here with a disabled & requested hardware renderer, something went
2685 // wrong (an invalidate posted right before we destroyed the hardware surface
2686 // for instance) so we should just bail out. Locking the surface with software
2687 // rendering at this point would lock it forever and prevent hardware renderer
2688 // from doing its job when it comes back.
2689 // Before we request a new frame we must however attempt to reinitiliaze the
2690 // hardware renderer if it's in requested state. This would happen after an
2691 // eglTerminate() for instance.
Chris Craikd36a81f2014-07-17 10:16:51 -07002692 if (mAttachInfo.mHardwareRenderer != null &&
2693 !mAttachInfo.mHardwareRenderer.isEnabled() &&
2694 mAttachInfo.mHardwareRenderer.isRequested()) {
Romain Guy3696779b2013-01-28 14:04:07 -08002695
2696 try {
Chris Craikd36a81f2014-07-17 10:16:51 -07002697 mAttachInfo.mHardwareRenderer.initializeIfNeeded(
Alan Viverette50210d92015-05-14 18:05:36 -07002698 mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets);
Igor Murashkina86ab6402013-08-30 12:58:36 -07002699 } catch (OutOfResourcesException e) {
Romain Guy3696779b2013-01-28 14:04:07 -08002700 handleOutOfResourcesException(e);
2701 return;
2702 }
2703
2704 mFullRedrawNeeded = true;
2705 scheduleTraversals();
2706 return;
2707 }
2708
Chris Craikd36a81f2014-07-17 10:16:51 -07002709 if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
Romain Guy3696779b2013-01-28 14:04:07 -08002710 return;
2711 }
Jeff Brown95db2b22011-11-30 19:54:41 -08002712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002713 }
Romain Guy8506ab42009-06-11 17:35:47 -07002714
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002715 if (animating) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002716 mFullRedrawNeeded = true;
2717 scheduleTraversals();
2718 }
2719 }
2720
Romain Guy25eba5c2012-04-04 17:29:03 -07002721 /**
Alan Viveretteccb11e12014-07-08 16:04:02 -07002722 * @return true if drawing was successful, false if an error occurred
Romain Guy25eba5c2012-04-04 17:29:03 -07002723 */
Alan Viveretteccb11e12014-07-08 16:04:02 -07002724 private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
Romain Guy25eba5c2012-04-04 17:29:03 -07002725 boolean scalingRequired, Rect dirty) {
2726
2727 // Draw with software renderer.
Alan Viverettea51cab92014-07-16 15:15:49 -07002728 final Canvas canvas;
Romain Guy25eba5c2012-04-04 17:29:03 -07002729 try {
Alan Viverettea51cab92014-07-16 15:15:49 -07002730 final int left = dirty.left;
2731 final int top = dirty.top;
2732 final int right = dirty.right;
2733 final int bottom = dirty.bottom;
Romain Guy25eba5c2012-04-04 17:29:03 -07002734
Romain Guy25eba5c2012-04-04 17:29:03 -07002735 canvas = mSurface.lockCanvas(dirty);
2736
Romain Guye55945e2013-04-04 15:26:04 -07002737 // The dirty rectangle can be modified by Surface.lockCanvas()
2738 //noinspection ConstantConditions
Alan Viverettea51cab92014-07-16 15:15:49 -07002739 if (left != dirty.left || top != dirty.top || right != dirty.right
2740 || bottom != dirty.bottom) {
Romain Guy25eba5c2012-04-04 17:29:03 -07002741 attachInfo.mIgnoreDirtyState = true;
2742 }
2743
2744 // TODO: Do this in native
2745 canvas.setDensity(mDensity);
2746 } catch (Surface.OutOfResourcesException e) {
Romain Guy3696779b2013-01-28 14:04:07 -08002747 handleOutOfResourcesException(e);
Romain Guy25eba5c2012-04-04 17:29:03 -07002748 return false;
2749 } catch (IllegalArgumentException e) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002750 Log.e(mTag, "Could not lock surface", e);
Romain Guy25eba5c2012-04-04 17:29:03 -07002751 // Don't assume this is due to out of memory, it could be
2752 // something else, and if it is something else then we could
2753 // kill stuff (or ourself) for no reason.
2754 mLayoutRequested = true; // ask wm for a new surface next time.
2755 return false;
2756 }
2757
2758 try {
2759 if (DEBUG_ORIENTATION || DEBUG_DRAW) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002760 Log.v(mTag, "Surface " + surface + " drawing to bitmap w="
Romain Guy25eba5c2012-04-04 17:29:03 -07002761 + canvas.getWidth() + ", h=" + canvas.getHeight());
2762 //canvas.drawARGB(255, 255, 0, 0);
2763 }
2764
Romain Guy25eba5c2012-04-04 17:29:03 -07002765 // If this bitmap's format includes an alpha channel, we
2766 // need to clear it before drawing so that the child will
2767 // properly re-composite its drawing on a transparent
2768 // background. This automatically respects the clip/dirty region
2769 // or
2770 // If we are applying an offset, we need to clear the area
2771 // where the offset doesn't appear to avoid having garbage
2772 // left in the blank areas.
Alan Viveretteccb11e12014-07-08 16:04:02 -07002773 if (!canvas.isOpaque() || yoff != 0 || xoff != 0) {
Romain Guy25eba5c2012-04-04 17:29:03 -07002774 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
2775 }
2776
2777 dirty.setEmpty();
2778 mIsAnimating = false;
Dianne Hackborn4702a852012-08-17 15:18:29 -07002779 mView.mPrivateFlags |= View.PFLAG_DRAWN;
Romain Guy25eba5c2012-04-04 17:29:03 -07002780
2781 if (DEBUG_DRAW) {
2782 Context cxt = mView.getContext();
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002783 Log.i(mTag, "Drawing: package:" + cxt.getPackageName() +
Romain Guy25eba5c2012-04-04 17:29:03 -07002784 ", metrics=" + cxt.getResources().getDisplayMetrics() +
2785 ", compatibilityInfo=" + cxt.getResources().getCompatibilityInfo());
2786 }
2787 try {
Alan Viveretteccb11e12014-07-08 16:04:02 -07002788 canvas.translate(-xoff, -yoff);
Romain Guy25eba5c2012-04-04 17:29:03 -07002789 if (mTranslator != null) {
2790 mTranslator.translateCanvas(canvas);
2791 }
Dianne Hackborn908aecc2012-07-31 16:37:34 -07002792 canvas.setScreenDensity(scalingRequired ? mNoncompatDensity : 0);
Romain Guy25eba5c2012-04-04 17:29:03 -07002793 attachInfo.mSetIgnoreDirtyState = false;
2794
Romain Guy25eba5c2012-04-04 17:29:03 -07002795 mView.draw(canvas);
Alan Viverette632af842014-10-28 13:45:11 -07002796
2797 drawAccessibilityFocusedDrawableIfNeeded(canvas);
Romain Guy25eba5c2012-04-04 17:29:03 -07002798 } finally {
2799 if (!attachInfo.mSetIgnoreDirtyState) {
2800 // Only clear the flag if it was not set during the mView.draw() call
2801 attachInfo.mIgnoreDirtyState = false;
2802 }
2803 }
Romain Guy25eba5c2012-04-04 17:29:03 -07002804 } finally {
Romain Guydddcd222012-05-18 15:33:57 -07002805 try {
2806 surface.unlockCanvasAndPost(canvas);
2807 } catch (IllegalArgumentException e) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002808 Log.e(mTag, "Could not unlock surface", e);
Romain Guydddcd222012-05-18 15:33:57 -07002809 mLayoutRequested = true; // ask wm for a new surface next time.
2810 //noinspection ReturnInsideFinallyBlock
2811 return false;
2812 }
Romain Guy25eba5c2012-04-04 17:29:03 -07002813
Romain Guy25eba5c2012-04-04 17:29:03 -07002814 if (LOCAL_LOGV) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002815 Log.v(mTag, "Surface " + surface + " unlockCanvasAndPost");
Romain Guy25eba5c2012-04-04 17:29:03 -07002816 }
2817 }
2818 return true;
2819 }
2820
Alan Viverette632af842014-10-28 13:45:11 -07002821 /**
2822 * We want to draw a highlight around the current accessibility focused.
2823 * Since adding a style for all possible view is not a viable option we
2824 * have this specialized drawing method.
2825 *
2826 * Note: We are doing this here to be able to draw the highlight for
2827 * virtual views in addition to real ones.
2828 *
2829 * @param canvas The canvas on which to draw.
2830 */
2831 private void drawAccessibilityFocusedDrawableIfNeeded(Canvas canvas) {
2832 final Rect bounds = mAttachInfo.mTmpInvalRect;
2833 if (getAccessibilityFocusedRect(bounds)) {
2834 final Drawable drawable = getAccessibilityFocusedDrawable();
2835 if (drawable != null) {
2836 drawable.setBounds(bounds);
2837 drawable.draw(canvas);
2838 }
2839 } else if (mAttachInfo.mAccessibilityFocusDrawable != null) {
2840 mAttachInfo.mAccessibilityFocusDrawable.setBounds(0, 0, 0, 0);
2841 }
2842 }
2843
2844 private boolean getAccessibilityFocusedRect(Rect bounds) {
2845 final AccessibilityManager manager = AccessibilityManager.getInstance(mView.mContext);
2846 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
2847 return false;
2848 }
2849
2850 final View host = mAccessibilityFocusedHost;
2851 if (host == null || host.mAttachInfo == null) {
2852 return false;
2853 }
2854
2855 final AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
2856 if (provider == null) {
Svetoslavded133c2015-01-30 20:28:41 -08002857 host.getBoundsOnScreen(bounds, true);
Alan Viverette632af842014-10-28 13:45:11 -07002858 } else if (mAccessibilityFocusedVirtualView != null) {
2859 mAccessibilityFocusedVirtualView.getBoundsInScreen(bounds);
2860 } else {
2861 return false;
2862 }
2863
Alan Viverette2232add2015-05-26 15:24:18 -07002864 // Transform the rect into window-relative coordinates.
Alan Viverette632af842014-10-28 13:45:11 -07002865 final AttachInfo attachInfo = mAttachInfo;
Alan Viverette2232add2015-05-26 15:24:18 -07002866 bounds.offset(0, attachInfo.mViewRootImpl.mScrollY);
Alan Viverette632af842014-10-28 13:45:11 -07002867 bounds.offset(-attachInfo.mWindowLeft, -attachInfo.mWindowTop);
Doris Liu9607fbe2015-05-28 17:17:28 -07002868 if (!bounds.intersect(0, 0, attachInfo.mViewRootImpl.mWidth,
2869 attachInfo.mViewRootImpl.mHeight)) {
2870 // If no intersection, set bounds to empty.
2871 bounds.setEmpty();
2872 }
Alan Viverette632af842014-10-28 13:45:11 -07002873 return !bounds.isEmpty();
2874 }
2875
2876 private Drawable getAccessibilityFocusedDrawable() {
Chris Craikd36a81f2014-07-17 10:16:51 -07002877 // Lazily load the accessibility focus drawable.
2878 if (mAttachInfo.mAccessibilityFocusDrawable == null) {
Alan Viverettef6cf1a02014-08-11 14:13:02 -07002879 final TypedValue value = new TypedValue();
Chris Craikd36a81f2014-07-17 10:16:51 -07002880 final boolean resolved = mView.mContext.getTheme().resolveAttribute(
2881 R.attr.accessibilityFocusedDrawable, value, true);
2882 if (resolved) {
2883 mAttachInfo.mAccessibilityFocusDrawable =
Alan Viverette8eea3ea2014-02-03 18:40:20 -08002884 mView.mContext.getDrawable(value.resourceId);
Svetoslav Ganov42138042012-03-20 11:51:39 -07002885 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07002886 }
Chris Craikd36a81f2014-07-17 10:16:51 -07002887 return mAttachInfo.mAccessibilityFocusDrawable;
Svetoslav Ganov42138042012-03-20 11:51:39 -07002888 }
2889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002890 boolean scrollToRectOrFocus(Rect rectangle, boolean immediate) {
Chris Craikd36a81f2014-07-17 10:16:51 -07002891 final Rect ci = mAttachInfo.mContentInsets;
2892 final Rect vi = mAttachInfo.mVisibleInsets;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002893 int scrollY = 0;
2894 boolean handled = false;
Romain Guy8506ab42009-06-11 17:35:47 -07002895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002896 if (vi.left > ci.left || vi.top > ci.top
2897 || vi.right > ci.right || vi.bottom > ci.bottom) {
2898 // We'll assume that we aren't going to change the scroll
2899 // offset, since we want to avoid that unless it is actually
2900 // going to make the focus visible... otherwise we scroll
2901 // all over the place.
2902 scrollY = mScrollY;
2903 // We can be called for two different situations: during a draw,
2904 // to update the scroll position if the focus has changed (in which
2905 // case 'rectangle' is null), or in response to a
2906 // requestChildRectangleOnScreen() call (in which case 'rectangle'
2907 // is non-null and we just want to scroll to whatever that
2908 // rectangle is).
Craig Mautner26a84df2013-04-11 19:09:05 -07002909 final View focus = mView.findFocus();
Svetoslav Ganov149567f2013-01-08 15:23:34 -08002910 if (focus == null) {
Romain Guye8b16522009-07-14 13:06:42 -07002911 return false;
2912 }
Svetoslav Ganov149567f2013-01-08 15:23:34 -08002913 View lastScrolledFocus = (mLastScrolledFocus != null) ? mLastScrolledFocus.get() : null;
Craig Mautner26a84df2013-04-11 19:09:05 -07002914 if (focus != lastScrolledFocus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002915 // If the focus has changed, then ignore any requests to scroll
2916 // to a rectangle; first we want to make sure the entire focus
2917 // view is visible.
2918 rectangle = null;
2919 }
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002920 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "Eval scroll: focus=" + focus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002921 + " rectangle=" + rectangle + " ci=" + ci
2922 + " vi=" + vi);
Svetoslav Ganov149567f2013-01-08 15:23:34 -08002923 if (focus == lastScrolledFocus && !mScrollMayChange && rectangle == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002924 // Optimization: if the focus hasn't changed since last
2925 // time, and no layout has happened, then just leave things
2926 // as they are.
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002927 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "Keeping scroll y="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002928 + mScrollY + " vi=" + vi.toShortString());
Craig Mautner26a84df2013-04-11 19:09:05 -07002929 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002930 // We need to determine if the currently focused view is
2931 // within the visible part of the window and, if not, apply
2932 // a pan so it can be seen.
Svetoslav Ganov149567f2013-01-08 15:23:34 -08002933 mLastScrolledFocus = new WeakReference<View>(focus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002934 mScrollMayChange = false;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002935 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "Need to scroll?");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 // Try to find the rectangle from the focus view.
2937 if (focus.getGlobalVisibleRect(mVisRect, null)) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002938 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "Root w="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002939 + mView.getWidth() + " h=" + mView.getHeight()
2940 + " ci=" + ci.toShortString()
2941 + " vi=" + vi.toShortString());
2942 if (rectangle == null) {
2943 focus.getFocusedRect(mTempRect);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002944 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "Focus " + focus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002945 + ": focusRect=" + mTempRect.toShortString());
Dianne Hackborn1c6a8942010-03-23 16:34:20 -07002946 if (mView instanceof ViewGroup) {
2947 ((ViewGroup) mView).offsetDescendantRectToMyCoords(
2948 focus, mTempRect);
2949 }
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002950 if (DEBUG_INPUT_RESIZE) Log.v(mTag,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 "Focus in window: focusRect="
2952 + mTempRect.toShortString()
2953 + " visRect=" + mVisRect.toShortString());
2954 } else {
2955 mTempRect.set(rectangle);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002956 if (DEBUG_INPUT_RESIZE) Log.v(mTag,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002957 "Request scroll to rect: "
2958 + mTempRect.toShortString()
2959 + " visRect=" + mVisRect.toShortString());
2960 }
2961 if (mTempRect.intersect(mVisRect)) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002962 if (DEBUG_INPUT_RESIZE) Log.v(mTag,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002963 "Focus window visible rect: "
2964 + mTempRect.toShortString());
2965 if (mTempRect.height() >
2966 (mView.getHeight()-vi.top-vi.bottom)) {
2967 // If the focus simply is not going to fit, then
2968 // best is probably just to leave things as-is.
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002969 if (DEBUG_INPUT_RESIZE) Log.v(mTag,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002970 "Too tall; leaving scrollY=" + scrollY);
2971 } else if ((mTempRect.top-scrollY) < vi.top) {
2972 scrollY -= vi.top - (mTempRect.top-scrollY);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002973 if (DEBUG_INPUT_RESIZE) Log.v(mTag,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002974 "Top covered; scrollY=" + scrollY);
2975 } else if ((mTempRect.bottom-scrollY)
2976 > (mView.getHeight()-vi.bottom)) {
2977 scrollY += (mTempRect.bottom-scrollY)
2978 - (mView.getHeight()-vi.bottom);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002979 if (DEBUG_INPUT_RESIZE) Log.v(mTag,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980 "Bottom covered; scrollY=" + scrollY);
2981 }
2982 handled = true;
2983 }
2984 }
2985 }
2986 }
Romain Guy8506ab42009-06-11 17:35:47 -07002987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002988 if (scrollY != mScrollY) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002989 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "Pan scroll changed: old="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 + mScrollY + " , new=" + scrollY);
Derek Sollenberger8d948352015-07-16 09:27:59 -04002991 if (!immediate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002992 if (mScroller == null) {
2993 mScroller = new Scroller(mView.getContext());
2994 }
2995 mScroller.startScroll(0, mScrollY, 0, scrollY-mScrollY);
2996 } else if (mScroller != null) {
2997 mScroller.abortAnimation();
2998 }
2999 mScrollY = scrollY;
3000 }
Romain Guy8506ab42009-06-11 17:35:47 -07003001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003002 return handled;
3003 }
Romain Guy8506ab42009-06-11 17:35:47 -07003004
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07003005 /**
3006 * @hide
3007 */
3008 public View getAccessibilityFocusedHost() {
3009 return mAccessibilityFocusedHost;
3010 }
3011
3012 /**
3013 * @hide
3014 */
3015 public AccessibilityNodeInfo getAccessibilityFocusedVirtualView() {
3016 return mAccessibilityFocusedVirtualView;
3017 }
3018
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07003019 void setAccessibilityFocus(View view, AccessibilityNodeInfo node) {
Svetoslav Ganov791fd312012-05-14 15:12:30 -07003020 // If we have a virtual view with accessibility focus we need
3021 // to clear the focus and invalidate the virtual view bounds.
3022 if (mAccessibilityFocusedVirtualView != null) {
3023
3024 AccessibilityNodeInfo focusNode = mAccessibilityFocusedVirtualView;
3025 View focusHost = mAccessibilityFocusedHost;
Svetoslav Ganov791fd312012-05-14 15:12:30 -07003026
3027 // Wipe the state of the current accessibility focus since
3028 // the call into the provider to clear accessibility focus
3029 // will fire an accessibility event which will end up calling
3030 // this method and we want to have clean state when this
3031 // invocation happens.
3032 mAccessibilityFocusedHost = null;
3033 mAccessibilityFocusedVirtualView = null;
3034
Alan Viverette239a0c02013-05-07 17:17:35 -07003035 // Clear accessibility focus on the host after clearing state since
3036 // this method may be reentrant.
3037 focusHost.clearAccessibilityFocusNoCallbacks();
3038
Svetoslav Ganov791fd312012-05-14 15:12:30 -07003039 AccessibilityNodeProvider provider = focusHost.getAccessibilityNodeProvider();
3040 if (provider != null) {
3041 // Invalidate the area of the cleared accessibility focus.
3042 focusNode.getBoundsInParent(mTempRect);
3043 focusHost.invalidate(mTempRect);
3044 // Clear accessibility focus in the virtual node.
3045 final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
3046 focusNode.getSourceNodeId());
3047 provider.performAction(virtualNodeId,
3048 AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
3049 }
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07003050 focusNode.recycle();
Svetoslav Ganov791fd312012-05-14 15:12:30 -07003051 }
3052 if (mAccessibilityFocusedHost != null) {
3053 // Clear accessibility focus in the view.
Svetoslav Ganov42138042012-03-20 11:51:39 -07003054 mAccessibilityFocusedHost.clearAccessibilityFocusNoCallbacks();
3055 }
Svetoslav Ganov791fd312012-05-14 15:12:30 -07003056
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07003057 // Set the new focus host and node.
3058 mAccessibilityFocusedHost = view;
3059 mAccessibilityFocusedVirtualView = node;
John Reck0a973302014-07-16 13:29:45 -07003060
3061 if (mAttachInfo.mHardwareRenderer != null) {
3062 mAttachInfo.mHardwareRenderer.invalidateRoot();
3063 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07003064 }
3065
Jun Mukai347e5d42015-12-03 01:13:31 -08003066 void setPointerCapture(View view) {
3067 if (!mAttachInfo.mHasWindowFocus) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003068 Log.w(mTag, "Can't set capture if it's not focused.");
Jun Mukai347e5d42015-12-03 01:13:31 -08003069 return;
3070 }
3071 if (mCapturingView == view) {
3072 return;
3073 }
3074 mCapturingView = view;
3075 InputManager.getInstance().setPointerIconDetached(true);
3076 }
3077
3078 void releasePointerCapture(View view) {
3079 if (mCapturingView != view || mCapturingView == null) {
3080 return;
3081 }
3082
3083 mCapturingView = null;
3084 InputManager.getInstance().setPointerIconDetached(false);
3085 }
3086
3087 boolean hasPointerCapture(View view) {
3088 return view != null && mCapturingView == view;
3089 }
3090
Igor Murashkina86ab6402013-08-30 12:58:36 -07003091 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003092 public void requestChildFocus(View child, View focused) {
Svetoslav Ganovb36a0ac2012-02-14 17:46:47 -08003093 if (DEBUG_INPUT_RESIZE) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003094 Log.v(mTag, "Request child focus: focus now " + focused);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003095 }
Svetoslav Ganov149567f2013-01-08 15:23:34 -08003096 checkThread();
Svetoslav Ganovb36a0ac2012-02-14 17:46:47 -08003097 scheduleTraversals();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003098 }
3099
Igor Murashkina86ab6402013-08-30 12:58:36 -07003100 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 public void clearChildFocus(View child) {
Svetoslav Ganovb36a0ac2012-02-14 17:46:47 -08003102 if (DEBUG_INPUT_RESIZE) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003103 Log.v(mTag, "Clearing child focus");
Amith Yamasani73eb97f2012-02-14 15:45:15 -08003104 }
Svetoslav Ganov149567f2013-01-08 15:23:34 -08003105 checkThread();
3106 scheduleTraversals();
Svetoslav Ganovb36a0ac2012-02-14 17:46:47 -08003107 }
Amith Yamasani73eb97f2012-02-14 15:45:15 -08003108
Svetoslav Ganov42138042012-03-20 11:51:39 -07003109 @Override
3110 public ViewParent getParentForAccessibility() {
3111 return null;
3112 }
3113
Igor Murashkina86ab6402013-08-30 12:58:36 -07003114 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003115 public void focusableViewAvailable(View v) {
3116 checkThread();
Romain Guy1c90f032011-05-24 14:59:50 -07003117 if (mView != null) {
3118 if (!mView.hasFocus()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003119 v.requestFocus();
Romain Guy1c90f032011-05-24 14:59:50 -07003120 } else {
3121 // the one case where will transfer focus away from the current one
3122 // is if the current view is a view group that prefers to give focus
3123 // to its children first AND the view is a descendant of it.
Svetoslav Ganov149567f2013-01-08 15:23:34 -08003124 View focused = mView.findFocus();
3125 if (focused instanceof ViewGroup) {
3126 ViewGroup group = (ViewGroup) focused;
3127 if (group.getDescendantFocusability() == ViewGroup.FOCUS_AFTER_DESCENDANTS
3128 && isViewDescendantOf(v, focused)) {
3129 v.requestFocus();
3130 }
Romain Guy1c90f032011-05-24 14:59:50 -07003131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003132 }
3133 }
3134 }
3135
Igor Murashkina86ab6402013-08-30 12:58:36 -07003136 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003137 public void recomputeViewAttributes(View child) {
3138 checkThread();
3139 if (mView == child) {
3140 mAttachInfo.mRecomputeGlobalAttributes = true;
3141 if (!mWillDrawSoon) {
3142 scheduleTraversals();
3143 }
3144 }
3145 }
3146
3147 void dispatchDetachedFromWindow() {
Romain Guy90fc03b2011-01-16 13:07:15 -08003148 if (mView != null && mView.mAttachInfo != null) {
Dianne Hackborn961cae92013-03-20 14:59:43 -07003149 mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003150 mView.dispatchDetachedFromWindow();
3151 }
3152
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003153 mAccessibilityInteractionConnectionManager.ensureNoConnection();
3154 mAccessibilityManager.removeAccessibilityStateChangeListener(
3155 mAccessibilityInteractionConnectionManager);
Chris Craikcce47eb2014-07-16 15:12:15 -07003156 mAccessibilityManager.removeHighTextContrastStateChangeListener(
3157 mHighContrastTextManager);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003158 removeSendWindowContentChangedCallback();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003159
Romain Guya998dff2012-03-23 18:58:36 -07003160 destroyHardwareRenderer();
3161
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07003162 setAccessibilityFocus(null, null);
Svetoslav Ganov791fd312012-05-14 15:12:30 -07003163
Craig Mautner8f303ad2013-06-14 11:32:22 -07003164 mView.assignParent(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003165 mView = null;
3166 mAttachInfo.mRootView = null;
3167
Jun Mukai347e5d42015-12-03 01:13:31 -08003168 if (mCapturingView != null) {
3169 releasePointerCapture(mCapturingView);
3170 }
3171
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07003172 mSurface.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003173
Jeff Browncc4f7db2011-08-30 20:34:48 -07003174 if (mInputQueueCallback != null && mInputQueue != null) {
3175 mInputQueueCallback.onInputQueueDestroyed(mInputQueue);
Michael Wrighta44dd262013-04-10 21:12:00 -07003176 mInputQueue.dispose();
Jeff Browncc4f7db2011-08-30 20:34:48 -07003177 mInputQueueCallback = null;
3178 mInputQueue = null;
Michael Wrighta44dd262013-04-10 21:12:00 -07003179 }
3180 if (mInputEventReceiver != null) {
Jeff Brown32cbc38552011-12-01 14:01:49 -08003181 mInputEventReceiver.dispose();
3182 mInputEventReceiver = null;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003184 try {
Jeff Brown98365d72012-08-19 20:30:52 -07003185 mWindowSession.remove(mWindow);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003186 } catch (RemoteException e) {
3187 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07003188
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003189 // Dispose the input channel after removing the window so the Window Manager
3190 // doesn't interpret the input channel being closed as an abnormal termination.
3191 if (mInputChannel != null) {
3192 mInputChannel.dispose();
3193 mInputChannel = null;
Jeff Brown349703e2010-06-22 01:27:15 -07003194 }
Jeff Brown96e942d2011-11-30 19:55:01 -08003195
Jeff Brownd912e1f2014-04-11 18:46:22 -07003196 mDisplayManager.unregisterDisplayListener(mDisplayListener);
3197
Jeff Brownebb2d8d2012-03-23 17:14:34 -07003198 unscheduleTraversals();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003199 }
Romain Guy8506ab42009-06-11 17:35:47 -07003200
Dianne Hackborn694f79b2010-03-17 19:44:59 -07003201 void updateConfiguration(Configuration config, boolean force) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003202 if (DEBUG_CONFIGURATION) Log.v(mTag,
Dianne Hackborn694f79b2010-03-17 19:44:59 -07003203 "Applying new config to window "
3204 + mWindowAttributes.getTitle()
3205 + ": " + config);
Dianne Hackborn5fd21692011-06-07 14:09:47 -07003206
Craig Mautner48d0d182013-06-11 07:53:06 -07003207 CompatibilityInfo ci = mDisplayAdjustments.getCompatibilityInfo();
3208 if (!ci.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
Dianne Hackborn5fd21692011-06-07 14:09:47 -07003209 config = new Configuration(config);
Dianne Hackborn908aecc2012-07-31 16:37:34 -07003210 ci.applyToConfiguration(mNoncompatDensity, config);
Dianne Hackborn5fd21692011-06-07 14:09:47 -07003211 }
3212
Dianne Hackborn694f79b2010-03-17 19:44:59 -07003213 synchronized (sConfigCallbacks) {
3214 for (int i=sConfigCallbacks.size()-1; i>=0; i--) {
3215 sConfigCallbacks.get(i).onConfigurationChanged(config);
3216 }
3217 }
3218 if (mView != null) {
3219 // At this point the resources have been updated to
3220 // have the most recent config, whatever that is. Use
Dianne Hackborn908aecc2012-07-31 16:37:34 -07003221 // the one in them which may be newer.
Romain Guy1c90f032011-05-24 14:59:50 -07003222 config = mView.getResources().getConfiguration();
Dianne Hackborn694f79b2010-03-17 19:44:59 -07003223 if (force || mLastConfiguration.diff(config) != 0) {
Fabrice Di Megliocf128972012-10-16 20:51:12 -07003224 final int lastLayoutDirection = mLastConfiguration.getLayoutDirection();
3225 final int currentLayoutDirection = config.getLayoutDirection();
Dianne Hackborn694f79b2010-03-17 19:44:59 -07003226 mLastConfiguration.setTo(config);
Fabrice Di Megliob003e282012-10-17 17:20:19 -07003227 if (lastLayoutDirection != currentLayoutDirection &&
3228 mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
Fabrice Di Megliocf128972012-10-16 20:51:12 -07003229 mView.setLayoutDirection(currentLayoutDirection);
3230 }
Dianne Hackborn694f79b2010-03-17 19:44:59 -07003231 mView.dispatchConfigurationChanged(config);
3232 }
3233 }
3234 }
John Reck05e85842014-04-23 14:48:28 -07003235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003236 /**
3237 * Return true if child is an ancestor of parent, (or equal to the parent).
3238 */
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07003239 public static boolean isViewDescendantOf(View child, View parent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003240 if (child == parent) {
3241 return true;
3242 }
3243
3244 final ViewParent theParent = child.getParent();
3245 return (theParent instanceof ViewGroup) && isViewDescendantOf((View) theParent, parent);
3246 }
3247
Yohei Yukawad2e56472015-07-28 17:00:33 -07003248 private static void forceLayout(View view) {
3249 view.forceLayout();
3250 if (view instanceof ViewGroup) {
3251 ViewGroup group = (ViewGroup) view;
3252 final int count = group.getChildCount();
3253 for (int i = 0; i < count; i++) {
3254 forceLayout(group.getChildAt(i));
3255 }
3256 }
3257 }
3258
Jeff Browna175a5b2012-02-15 19:18:31 -08003259 private final static int MSG_INVALIDATE = 1;
3260 private final static int MSG_INVALIDATE_RECT = 2;
3261 private final static int MSG_DIE = 3;
3262 private final static int MSG_RESIZED = 4;
3263 private final static int MSG_RESIZED_REPORT = 5;
3264 private final static int MSG_WINDOW_FOCUS_CHANGED = 6;
keunyoung30f420f2013-08-02 14:23:10 -07003265 private final static int MSG_DISPATCH_INPUT_EVENT = 7;
Jeff Browna175a5b2012-02-15 19:18:31 -08003266 private final static int MSG_DISPATCH_APP_VISIBILITY = 8;
3267 private final static int MSG_DISPATCH_GET_NEW_SURFACE = 9;
Jeff Browna175a5b2012-02-15 19:18:31 -08003268 private final static int MSG_DISPATCH_KEY_FROM_IME = 11;
3269 private final static int MSG_FINISH_INPUT_CONNECTION = 12;
3270 private final static int MSG_CHECK_FOCUS = 13;
3271 private final static int MSG_CLOSE_SYSTEM_DIALOGS = 14;
3272 private final static int MSG_DISPATCH_DRAG_EVENT = 15;
3273 private final static int MSG_DISPATCH_DRAG_LOCATION_EVENT = 16;
3274 private final static int MSG_DISPATCH_SYSTEM_UI_VISIBILITY = 17;
3275 private final static int MSG_UPDATE_CONFIGURATION = 18;
Svetoslav Ganov42138042012-03-20 11:51:39 -07003276 private final static int MSG_PROCESS_INPUT_EVENTS = 19;
Romain Guyfbb93fa2012-12-03 18:50:35 -08003277 private final static int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 21;
Jorim Jaggi827e0fa2015-05-07 11:41:41 -07003278 private final static int MSG_INVALIDATE_WORLD = 22;
3279 private final static int MSG_WINDOW_MOVED = 23;
3280 private final static int MSG_SYNTHESIZE_INPUT_EVENT = 24;
3281 private final static int MSG_DISPATCH_WINDOW_SHOWN = 25;
Clara Bayarri75e09792015-07-29 16:20:40 +01003282 private final static int MSG_REQUEST_KEYBOARD_SHORTCUTS = 26;
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08003283 private final static int MSG_UPDATE_POINTER_ICON = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003284
Jeff Browna175a5b2012-02-15 19:18:31 -08003285 final class ViewRootHandler extends Handler {
3286 @Override
3287 public String getMessageName(Message message) {
3288 switch (message.what) {
3289 case MSG_INVALIDATE:
3290 return "MSG_INVALIDATE";
3291 case MSG_INVALIDATE_RECT:
3292 return "MSG_INVALIDATE_RECT";
3293 case MSG_DIE:
3294 return "MSG_DIE";
3295 case MSG_RESIZED:
3296 return "MSG_RESIZED";
3297 case MSG_RESIZED_REPORT:
3298 return "MSG_RESIZED_REPORT";
3299 case MSG_WINDOW_FOCUS_CHANGED:
3300 return "MSG_WINDOW_FOCUS_CHANGED";
keunyoung30f420f2013-08-02 14:23:10 -07003301 case MSG_DISPATCH_INPUT_EVENT:
3302 return "MSG_DISPATCH_INPUT_EVENT";
Jeff Browna175a5b2012-02-15 19:18:31 -08003303 case MSG_DISPATCH_APP_VISIBILITY:
3304 return "MSG_DISPATCH_APP_VISIBILITY";
3305 case MSG_DISPATCH_GET_NEW_SURFACE:
3306 return "MSG_DISPATCH_GET_NEW_SURFACE";
Jeff Browna175a5b2012-02-15 19:18:31 -08003307 case MSG_DISPATCH_KEY_FROM_IME:
3308 return "MSG_DISPATCH_KEY_FROM_IME";
3309 case MSG_FINISH_INPUT_CONNECTION:
3310 return "MSG_FINISH_INPUT_CONNECTION";
3311 case MSG_CHECK_FOCUS:
3312 return "MSG_CHECK_FOCUS";
3313 case MSG_CLOSE_SYSTEM_DIALOGS:
3314 return "MSG_CLOSE_SYSTEM_DIALOGS";
3315 case MSG_DISPATCH_DRAG_EVENT:
3316 return "MSG_DISPATCH_DRAG_EVENT";
3317 case MSG_DISPATCH_DRAG_LOCATION_EVENT:
3318 return "MSG_DISPATCH_DRAG_LOCATION_EVENT";
3319 case MSG_DISPATCH_SYSTEM_UI_VISIBILITY:
3320 return "MSG_DISPATCH_SYSTEM_UI_VISIBILITY";
3321 case MSG_UPDATE_CONFIGURATION:
3322 return "MSG_UPDATE_CONFIGURATION";
Jeff Browna175a5b2012-02-15 19:18:31 -08003323 case MSG_PROCESS_INPUT_EVENTS:
3324 return "MSG_PROCESS_INPUT_EVENTS";
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07003325 case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST:
3326 return "MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST";
Craig Mautner5702d4d2012-06-30 14:10:16 -07003327 case MSG_WINDOW_MOVED:
3328 return "MSG_WINDOW_MOVED";
Michael Wright899d7052014-04-23 17:23:39 -07003329 case MSG_SYNTHESIZE_INPUT_EVENT:
3330 return "MSG_SYNTHESIZE_INPUT_EVENT";
Craig Mautner9c795042014-10-28 19:59:59 -07003331 case MSG_DISPATCH_WINDOW_SHOWN:
3332 return "MSG_DISPATCH_WINDOW_SHOWN";
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08003333 case MSG_UPDATE_POINTER_ICON:
3334 return "MSG_UPDATE_POINTER_ICON";
Jeff Browna175a5b2012-02-15 19:18:31 -08003335 }
3336 return super.getMessageName(message);
Romain Guyf9284692011-07-13 18:46:21 -07003337 }
Romain Guyf9284692011-07-13 18:46:21 -07003338
Jeff Browna175a5b2012-02-15 19:18:31 -08003339 @Override
3340 public void handleMessage(Message msg) {
3341 switch (msg.what) {
3342 case MSG_INVALIDATE:
3343 ((View) msg.obj).invalidate();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 break;
Jeff Browna175a5b2012-02-15 19:18:31 -08003345 case MSG_INVALIDATE_RECT:
3346 final View.AttachInfo.InvalidateInfo info = (View.AttachInfo.InvalidateInfo) msg.obj;
3347 info.target.invalidate(info.left, info.top, info.right, info.bottom);
Svetoslav Ganovabae2a12012-11-27 16:59:37 -08003348 info.recycle();
Jeff Browna175a5b2012-02-15 19:18:31 -08003349 break;
Jeff Browna175a5b2012-02-15 19:18:31 -08003350 case MSG_PROCESS_INPUT_EVENTS:
3351 mProcessInputEventsScheduled = false;
3352 doProcessInputEvents();
3353 break;
3354 case MSG_DISPATCH_APP_VISIBILITY:
3355 handleAppVisibility(msg.arg1 != 0);
3356 break;
3357 case MSG_DISPATCH_GET_NEW_SURFACE:
3358 handleGetNewSurface();
3359 break;
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003360 case MSG_RESIZED: {
3361 // Recycled in the fall through...
3362 SomeArgs args = (SomeArgs) msg.obj;
Romain Guydfab3632012-10-03 14:53:25 -07003363 if (mWinFrame.equals(args.arg1)
Dianne Hackbornc4aad012013-02-22 15:05:25 -08003364 && mPendingOverscanInsets.equals(args.arg5)
Romain Guydfab3632012-10-03 14:53:25 -07003365 && mPendingContentInsets.equals(args.arg2)
Adrian Roosfa104232014-06-20 16:10:14 -07003366 && mPendingStableInsets.equals(args.arg6)
Romain Guydfab3632012-10-03 14:53:25 -07003367 && mPendingVisibleInsets.equals(args.arg3)
Filip Gruszczynski2217f612015-05-26 11:32:08 -07003368 && mPendingOutsets.equals(args.arg7)
Jorim Jaggi0fe356e2016-01-05 14:43:25 +01003369 && mPendingBackDropFrame.equals(args.arg8)
Jorim Jaggia4a58ef2016-01-27 02:10:08 -08003370 && args.arg4 == null
3371 && args.argi1 == 0) {
Jeff Browna175a5b2012-02-15 19:18:31 -08003372 break;
Romain Guycdb86672010-03-18 18:54:50 -07003373 }
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003374 } // fall through...
Jeff Browna175a5b2012-02-15 19:18:31 -08003375 case MSG_RESIZED_REPORT:
3376 if (mAdded) {
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003377 SomeArgs args = (SomeArgs) msg.obj;
3378
3379 Configuration config = (Configuration) args.arg4;
Jeff Browna175a5b2012-02-15 19:18:31 -08003380 if (config != null) {
3381 updateConfiguration(config, false);
3382 }
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003383
3384 mWinFrame.set((Rect) args.arg1);
Dianne Hackbornc4aad012013-02-22 15:05:25 -08003385 mPendingOverscanInsets.set((Rect) args.arg5);
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003386 mPendingContentInsets.set((Rect) args.arg2);
Adrian Roosfa104232014-06-20 16:10:14 -07003387 mPendingStableInsets.set((Rect) args.arg6);
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003388 mPendingVisibleInsets.set((Rect) args.arg3);
Filip Gruszczynski2217f612015-05-26 11:32:08 -07003389 mPendingOutsets.set((Rect) args.arg7);
Jorim Jaggia7262a82015-11-03 15:15:40 +01003390 mPendingBackDropFrame.set((Rect) args.arg8);
Jorim Jaggia4a58ef2016-01-27 02:10:08 -08003391 mForceNextWindowRelayout = args.argi1 != 0;
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003392
3393 args.recycle();
3394
Jeff Browna175a5b2012-02-15 19:18:31 -08003395 if (msg.what == MSG_RESIZED_REPORT) {
3396 mReportNextDraw = true;
3397 }
Romain Guy59a12ca2011-06-09 17:48:21 -07003398
Yohei Yukawad2e56472015-07-28 17:00:33 -07003399 if (mView != null) {
3400 forceLayout(mView);
3401 }
3402
Jeff Browna175a5b2012-02-15 19:18:31 -08003403 requestLayout();
3404 }
3405 break;
Craig Mautner5702d4d2012-06-30 14:10:16 -07003406 case MSG_WINDOW_MOVED:
3407 if (mAdded) {
3408 final int w = mWinFrame.width();
3409 final int h = mWinFrame.height();
3410 final int l = msg.arg1;
3411 final int t = msg.arg2;
3412 mWinFrame.left = l;
3413 mWinFrame.right = l + w;
3414 mWinFrame.top = t;
3415 mWinFrame.bottom = t + h;
3416
Jorim Jaggia7262a82015-11-03 15:15:40 +01003417 mPendingBackDropFrame.set(mWinFrame);
3418
Jorim Jaggi844e1712016-01-13 17:39:25 -08003419 // Suppress layouts during resizing - a correct layout will happen when resizing
3420 // is done, and this just increases system load.
Jorim Jaggi2e95a482016-01-14 17:36:55 -08003421 boolean isDockedDivider = mWindowAttributes.type == TYPE_DOCK_DIVIDER;
3422 boolean suppress = (mDragResizing && mResizeMode == RESIZE_MODE_DOCKED_DIVIDER)
3423 || isDockedDivider;
Jorim Jaggi844e1712016-01-13 17:39:25 -08003424 if (!suppress) {
3425 if (mView != null) {
3426 forceLayout(mView);
3427 }
3428 requestLayout();
Jorim Jaggi2e95a482016-01-14 17:36:55 -08003429 } else {
3430 maybeHandleWindowMove(mWinFrame);
Yohei Yukawad2e56472015-07-28 17:00:33 -07003431 }
Craig Mautner5702d4d2012-06-30 14:10:16 -07003432 }
3433 break;
Jeff Browna175a5b2012-02-15 19:18:31 -08003434 case MSG_WINDOW_FOCUS_CHANGED: {
3435 if (mAdded) {
3436 boolean hasWindowFocus = msg.arg1 != 0;
3437 mAttachInfo.mHasWindowFocus = hasWindowFocus;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003438
Jeff Browna175a5b2012-02-15 19:18:31 -08003439 profileRendering(hasWindowFocus);
3440
3441 if (hasWindowFocus) {
3442 boolean inTouchMode = msg.arg2 != 0;
3443 ensureTouchModeLocally(inTouchMode);
3444
Romain Guye55945e2013-04-04 15:26:04 -07003445 if (mAttachInfo.mHardwareRenderer != null && mSurface.isValid()){
Jeff Browna175a5b2012-02-15 19:18:31 -08003446 mFullRedrawNeeded = true;
Dianne Hackborn64825172011-03-02 21:32:58 -08003447 try {
Alan Viveretteccb11e12014-07-08 16:04:02 -07003448 final WindowManager.LayoutParams lp = mWindowAttributes;
Alan Viverette49a22e82014-07-12 20:01:27 -07003449 final Rect surfaceInsets = lp != null ? lp.surfaceInsets : null;
Romain Guy3696779b2013-01-28 14:04:07 -08003450 mAttachInfo.mHardwareRenderer.initializeIfNeeded(
Alan Viverette50210d92015-05-14 18:05:36 -07003451 mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets);
Igor Murashkina86ab6402013-08-30 12:58:36 -07003452 } catch (OutOfResourcesException e) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003453 Log.e(mTag, "OutOfResourcesException locking surface", e);
Jeff Browna175a5b2012-02-15 19:18:31 -08003454 try {
Jeff Brown98365d72012-08-19 20:30:52 -07003455 if (!mWindowSession.outOfMemory(mWindow)) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003456 Slog.w(mTag, "No processes killed for memory; killing self");
Jeff Browna175a5b2012-02-15 19:18:31 -08003457 Process.killProcess(Process.myPid());
3458 }
3459 } catch (RemoteException ex) {
Dianne Hackborn64825172011-03-02 21:32:58 -08003460 }
Jeff Browna175a5b2012-02-15 19:18:31 -08003461 // Retry in a bit.
3462 sendMessageDelayed(obtainMessage(msg.what, msg.arg1, msg.arg2), 500);
3463 return;
Dianne Hackborn64825172011-03-02 21:32:58 -08003464 }
Dianne Hackborn64825172011-03-02 21:32:58 -08003465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003466 }
Romain Guy8506ab42009-06-11 17:35:47 -07003467
Jeff Browna175a5b2012-02-15 19:18:31 -08003468 mLastWasImTarget = WindowManager.LayoutParams
3469 .mayUseInputMethod(mWindowAttributes.flags);
Romain Guy8506ab42009-06-11 17:35:47 -07003470
Jeff Browna175a5b2012-02-15 19:18:31 -08003471 InputMethodManager imm = InputMethodManager.peekInstance();
Yohei Yukawa5f059652015-05-14 22:16:41 -07003472 if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) {
3473 imm.onPreWindowFocus(mView, hasWindowFocus);
3474 }
Jeff Browna175a5b2012-02-15 19:18:31 -08003475 if (mView != null) {
Jeff Browna175a5b2012-02-15 19:18:31 -08003476 mAttachInfo.mKeyDispatchState.reset();
3477 mView.dispatchWindowFocusChanged(hasWindowFocus);
Dianne Hackborn961cae92013-03-20 14:59:43 -07003478 mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 }
svetoslavganov75986cf2009-05-14 22:28:01 -07003480
Jeff Browna175a5b2012-02-15 19:18:31 -08003481 // Note: must be done after the focus change callbacks,
3482 // so all of the view state is set up correctly.
3483 if (hasWindowFocus) {
keunyoung30f420f2013-08-02 14:23:10 -07003484 if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) {
Yohei Yukawa5f059652015-05-14 22:16:41 -07003485 imm.onPostWindowFocus(mView, mView.findFocus(),
Jeff Browna175a5b2012-02-15 19:18:31 -08003486 mWindowAttributes.softInputMode,
3487 !mHasHadWindowFocus, mWindowAttributes.flags);
3488 }
3489 // Clear the forward bit. We can just do this directly, since
3490 // the window manager doesn't care about it.
3491 mWindowAttributes.softInputMode &=
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
Jeff Browna175a5b2012-02-15 19:18:31 -08003493 ((WindowManager.LayoutParams)mView.getLayoutParams())
3494 .softInputMode &=
3495 ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
3496 mHasHadWindowFocus = true;
Jun Mukai347e5d42015-12-03 01:13:31 -08003497 } else if (mCapturingView != null) {
3498 releasePointerCapture(mCapturingView);
Jeff Browna175a5b2012-02-15 19:18:31 -08003499 }
svetoslavganov75986cf2009-05-14 22:28:01 -07003500 }
Jeff Browna175a5b2012-02-15 19:18:31 -08003501 } break;
3502 case MSG_DIE:
3503 doDie();
3504 break;
keunyoung30f420f2013-08-02 14:23:10 -07003505 case MSG_DISPATCH_INPUT_EVENT: {
Jae Seo6a6059a2014-04-17 21:35:29 -07003506 SomeArgs args = (SomeArgs)msg.obj;
3507 InputEvent event = (InputEvent)args.arg1;
3508 InputEventReceiver receiver = (InputEventReceiver)args.arg2;
3509 enqueueInputEvent(event, receiver, 0, true);
3510 args.recycle();
Jeff Browna175a5b2012-02-15 19:18:31 -08003511 } break;
Michael Wright899d7052014-04-23 17:23:39 -07003512 case MSG_SYNTHESIZE_INPUT_EVENT: {
3513 InputEvent event = (InputEvent)msg.obj;
3514 enqueueInputEvent(event, null, QueuedInputEvent.FLAG_UNHANDLED, true);
3515 } break;
Jeff Browna175a5b2012-02-15 19:18:31 -08003516 case MSG_DISPATCH_KEY_FROM_IME: {
3517 if (LOCAL_LOGV) Log.v(
3518 TAG, "Dispatching key "
3519 + msg.obj + " from IME to " + mView);
3520 KeyEvent event = (KeyEvent)msg.obj;
3521 if ((event.getFlags()&KeyEvent.FLAG_FROM_SYSTEM) != 0) {
3522 // The IME is trying to say this event is from the
3523 // system! Bad bad bad!
3524 //noinspection UnusedAssignment
Michael Wright899d7052014-04-23 17:23:39 -07003525 event = KeyEvent.changeFlags(event, event.getFlags() &
3526 ~KeyEvent.FLAG_FROM_SYSTEM);
Jeff Browna175a5b2012-02-15 19:18:31 -08003527 }
3528 enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true);
3529 } break;
3530 case MSG_FINISH_INPUT_CONNECTION: {
3531 InputMethodManager imm = InputMethodManager.peekInstance();
3532 if (imm != null) {
3533 imm.reportFinishInputConnection((InputConnection)msg.obj);
3534 }
3535 } break;
3536 case MSG_CHECK_FOCUS: {
3537 InputMethodManager imm = InputMethodManager.peekInstance();
3538 if (imm != null) {
3539 imm.checkFocus();
3540 }
3541 } break;
3542 case MSG_CLOSE_SYSTEM_DIALOGS: {
3543 if (mView != null) {
3544 mView.onCloseSystemDialogs((String)msg.obj);
3545 }
3546 } break;
3547 case MSG_DISPATCH_DRAG_EVENT:
3548 case MSG_DISPATCH_DRAG_LOCATION_EVENT: {
3549 DragEvent event = (DragEvent)msg.obj;
3550 event.mLocalState = mLocalDragState; // only present when this app called startDrag()
3551 handleDragEvent(event);
3552 } break;
3553 case MSG_DISPATCH_SYSTEM_UI_VISIBILITY: {
Romain Guyfbb93fa2012-12-03 18:50:35 -08003554 handleDispatchSystemUiVisibilityChanged((SystemUiVisibilityInfo) msg.obj);
Jeff Browna175a5b2012-02-15 19:18:31 -08003555 } break;
3556 case MSG_UPDATE_CONFIGURATION: {
3557 Configuration config = (Configuration)msg.obj;
3558 if (config.isOtherSeqNewer(mLastConfiguration)) {
3559 config = mLastConfiguration;
3560 }
3561 updateConfiguration(config, false);
3562 } break;
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07003563 case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST: {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07003564 setAccessibilityFocus(null, null);
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07003565 } break;
Dianne Hackborna53de062012-05-08 18:53:51 -07003566 case MSG_INVALIDATE_WORLD: {
Romain Guyf84208f2012-09-13 22:50:18 -07003567 if (mView != null) {
3568 invalidateWorld(mView);
3569 }
Dianne Hackborna53de062012-05-08 18:53:51 -07003570 } break;
Craig Mautner9c795042014-10-28 19:59:59 -07003571 case MSG_DISPATCH_WINDOW_SHOWN: {
3572 handleDispatchWindowShown();
Clara Bayarri75e09792015-07-29 16:20:40 +01003573 } break;
3574 case MSG_REQUEST_KEYBOARD_SHORTCUTS: {
3575 IResultReceiver receiver = (IResultReceiver) msg.obj;
3576 handleRequestKeyboardShortcuts(receiver);
3577 } break;
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08003578 case MSG_UPDATE_POINTER_ICON: {
3579 MotionEvent event = (MotionEvent) msg.obj;
3580 resetPointerIcon(event);
3581 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003582 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 }
3584 }
Romain Guy51e4d4d2012-03-15 18:30:47 -07003585
Jeff Browna175a5b2012-02-15 19:18:31 -08003586 final ViewRootHandler mHandler = new ViewRootHandler();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003588 /**
3589 * Something in the current window tells us we need to change the touch mode. For
3590 * example, we are not in touch mode, and the user touches the screen.
3591 *
3592 * If the touch mode has changed, tell the window manager, and handle it locally.
3593 *
3594 * @param inTouchMode Whether we want to be in touch mode.
3595 * @return True if the touch mode changed and focus changed was changed as a result
3596 */
3597 boolean ensureTouchMode(boolean inTouchMode) {
3598 if (DBG) Log.d("touchmode", "ensureTouchMode(" + inTouchMode + "), current "
3599 + "touch mode is " + mAttachInfo.mInTouchMode);
3600 if (mAttachInfo.mInTouchMode == inTouchMode) return false;
3601
3602 // tell the window manager
3603 try {
Matt Wud6bc96d2016-01-14 12:59:24 -08003604 mWindowSession.setInTouchMode(inTouchMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003605 } catch (RemoteException e) {
3606 throw new RuntimeException(e);
3607 }
3608
3609 // handle the change
Romain Guy2d4cff62010-04-09 15:39:00 -07003610 return ensureTouchModeLocally(inTouchMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003611 }
3612
3613 /**
3614 * Ensure that the touch mode for this window is set, and if it is changing,
3615 * take the appropriate action.
3616 * @param inTouchMode Whether we want to be in touch mode.
3617 * @return True if the touch mode changed and focus changed was changed as a result
3618 */
Romain Guy2d4cff62010-04-09 15:39:00 -07003619 private boolean ensureTouchModeLocally(boolean inTouchMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003620 if (DBG) Log.d("touchmode", "ensureTouchModeLocally(" + inTouchMode + "), current "
3621 + "touch mode is " + mAttachInfo.mInTouchMode);
3622
3623 if (mAttachInfo.mInTouchMode == inTouchMode) return false;
3624
3625 mAttachInfo.mInTouchMode = inTouchMode;
3626 mAttachInfo.mTreeObserver.dispatchOnTouchModeChanged(inTouchMode);
3627
Romain Guy2d4cff62010-04-09 15:39:00 -07003628 return (inTouchMode) ? enterTouchMode() : leaveTouchMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003629 }
3630
3631 private boolean enterTouchMode() {
Alan Viveretteed7821a2013-07-24 15:49:23 -07003632 if (mView != null && mView.hasFocus()) {
3633 // note: not relying on mFocusedView here because this could
3634 // be when the window is first being added, and mFocused isn't
3635 // set yet.
3636 final View focused = mView.findFocus();
3637 if (focused != null && !focused.isFocusableInTouchMode()) {
3638 final ViewGroup ancestorToTakeFocus = findAncestorToTakeFocusInTouchMode(focused);
3639 if (ancestorToTakeFocus != null) {
3640 // there is an ancestor that wants focus after its
3641 // descendants that is focusable in touch mode.. give it
3642 // focus
3643 return ancestorToTakeFocus.requestFocus();
3644 } else {
Alan Viverette973f3b42013-08-13 16:57:28 -07003645 // There's nothing to focus. Clear and propagate through the
3646 // hierarchy, but don't attempt to place new focus.
Alan Viverette223622a2013-12-17 13:29:02 -08003647 focused.clearFocusInternal(null, true, false);
Alan Viveretteed7821a2013-07-24 15:49:23 -07003648 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003649 }
3650 }
3651 }
3652 return false;
3653 }
3654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003655 /**
3656 * Find an ancestor of focused that wants focus after its descendants and is
3657 * focusable in touch mode.
3658 * @param focused The currently focused view.
3659 * @return An appropriate view, or null if no such view exists.
3660 */
Romain Guya998dff2012-03-23 18:58:36 -07003661 private static ViewGroup findAncestorToTakeFocusInTouchMode(View focused) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 ViewParent parent = focused.getParent();
3663 while (parent instanceof ViewGroup) {
3664 final ViewGroup vgParent = (ViewGroup) parent;
3665 if (vgParent.getDescendantFocusability() == ViewGroup.FOCUS_AFTER_DESCENDANTS
3666 && vgParent.isFocusableInTouchMode()) {
3667 return vgParent;
3668 }
3669 if (vgParent.isRootNamespace()) {
3670 return null;
3671 } else {
3672 parent = vgParent.getParent();
3673 }
3674 }
3675 return null;
3676 }
3677
3678 private boolean leaveTouchMode() {
3679 if (mView != null) {
3680 if (mView.hasFocus()) {
Svetoslav Ganov149567f2013-01-08 15:23:34 -08003681 View focusedView = mView.findFocus();
3682 if (!(focusedView instanceof ViewGroup)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003683 // some view has focus, let it keep it
Svetoslav Ganovcf8a3b82012-04-30 16:49:59 -07003684 return false;
Svetoslav Ganov149567f2013-01-08 15:23:34 -08003685 } else if (((ViewGroup) focusedView).getDescendantFocusability() !=
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003686 ViewGroup.FOCUS_AFTER_DESCENDANTS) {
3687 // some view group has focus, and doesn't prefer its children
3688 // over itself for focus, so let them keep it.
Svetoslav Ganovcf8a3b82012-04-30 16:49:59 -07003689 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003690 }
3691 }
Svetoslav Ganovcf8a3b82012-04-30 16:49:59 -07003692
3693 // find the best view to give focus to in this brave new non-touch-mode
3694 // world
3695 final View focused = focusSearch(null, View.FOCUS_DOWN);
3696 if (focused != null) {
3697 return focused.requestFocus(View.FOCUS_DOWN);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003698 }
3699 }
3700 return false;
3701 }
3702
Jeff Brownf9e989d2013-04-04 23:04:03 -07003703 /**
3704 * Base class for implementing a stage in the chain of responsibility
3705 * for processing input events.
3706 * <p>
3707 * Events are delivered to the stage by the {@link #deliver} method. The stage
3708 * then has the choice of finishing the event or forwarding it to the next stage.
3709 * </p>
3710 */
3711 abstract class InputStage {
3712 private final InputStage mNext;
3713
3714 protected static final int FORWARD = 0;
3715 protected static final int FINISH_HANDLED = 1;
3716 protected static final int FINISH_NOT_HANDLED = 2;
3717
3718 /**
3719 * Creates an input stage.
3720 * @param next The next stage to which events should be forwarded.
3721 */
3722 public InputStage(InputStage next) {
3723 mNext = next;
3724 }
3725
3726 /**
3727 * Delivers an event to be processed.
3728 */
3729 public final void deliver(QueuedInputEvent q) {
3730 if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
3731 forward(q);
Michael Wright17d28ca2013-10-31 17:47:45 -07003732 } else if (shouldDropInputEvent(q)) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07003733 finish(q, false);
3734 } else {
3735 apply(q, onProcess(q));
3736 }
3737 }
3738
3739 /**
3740 * Marks the the input event as finished then forwards it to the next stage.
3741 */
3742 protected void finish(QueuedInputEvent q, boolean handled) {
3743 q.mFlags |= QueuedInputEvent.FLAG_FINISHED;
3744 if (handled) {
3745 q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;
3746 }
3747 forward(q);
3748 }
3749
3750 /**
3751 * Forwards the event to the next stage.
3752 */
3753 protected void forward(QueuedInputEvent q) {
3754 onDeliverToNext(q);
3755 }
3756
3757 /**
3758 * Applies a result code from {@link #onProcess} to the specified event.
3759 */
3760 protected void apply(QueuedInputEvent q, int result) {
3761 if (result == FORWARD) {
3762 forward(q);
3763 } else if (result == FINISH_HANDLED) {
3764 finish(q, true);
3765 } else if (result == FINISH_NOT_HANDLED) {
3766 finish(q, false);
3767 } else {
3768 throw new IllegalArgumentException("Invalid result: " + result);
3769 }
3770 }
3771
3772 /**
3773 * Called when an event is ready to be processed.
3774 * @return A result code indicating how the event was handled.
3775 */
3776 protected int onProcess(QueuedInputEvent q) {
3777 return FORWARD;
3778 }
3779
3780 /**
3781 * Called when an event is being delivered to the next stage.
3782 */
3783 protected void onDeliverToNext(QueuedInputEvent q) {
Michael Wright06a79252014-05-05 17:45:29 -07003784 if (DEBUG_INPUT_STAGES) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003785 Log.v(mTag, "Done with " + getClass().getSimpleName() + ". " + q);
Michael Wright06a79252014-05-05 17:45:29 -07003786 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07003787 if (mNext != null) {
3788 mNext.deliver(q);
3789 } else {
3790 finishInputEvent(q);
3791 }
3792 }
Jeff Brown5182c782013-10-15 20:31:52 -07003793
Michael Wright17d28ca2013-10-31 17:47:45 -07003794 protected boolean shouldDropInputEvent(QueuedInputEvent q) {
3795 if (mView == null || !mAdded) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003796 Slog.w(mTag, "Dropping event due to root view being removed: " + q.mEvent);
Michael Wright17d28ca2013-10-31 17:47:45 -07003797 return true;
George Mount41725de2015-04-09 08:23:05 -07003798 } else if ((!mAttachInfo.mHasWindowFocus
3799 && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) || mStopped
Joe LaPenna90776de2016-01-22 07:11:49 -08003800 || (mIsAmbientMode && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_BUTTON))
3801 || (mPausedForTransition && !isBack(q.mEvent))) {
Wale Ogunwalec3672cd2014-11-05 15:17:35 -08003802 // This is a focus event and the window doesn't currently have input focus or
3803 // has stopped. This could be an event that came back from the previous stage
3804 // but the window has lost focus or stopped in the meantime.
3805 if (isTerminalInputEvent(q.mEvent)) {
3806 // Don't drop terminal input events, however mark them as canceled.
3807 q.mEvent.cancel();
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003808 Slog.w(mTag, "Cancelling event due to no window focus: " + q.mEvent);
Wale Ogunwalec3672cd2014-11-05 15:17:35 -08003809 return false;
3810 }
3811
3812 // Drop non-terminal input events.
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003813 Slog.w(mTag, "Dropping event due to no window focus: " + q.mEvent);
Michael Wright17d28ca2013-10-31 17:47:45 -07003814 return true;
3815 }
3816 return false;
3817 }
3818
Jeff Brown5182c782013-10-15 20:31:52 -07003819 void dump(String prefix, PrintWriter writer) {
3820 if (mNext != null) {
3821 mNext.dump(prefix, writer);
3822 }
3823 }
George Mount41725de2015-04-09 08:23:05 -07003824
3825 private boolean isBack(InputEvent event) {
3826 if (event instanceof KeyEvent) {
3827 return ((KeyEvent) event).getKeyCode() == KeyEvent.KEYCODE_BACK;
3828 } else {
3829 return false;
3830 }
3831 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07003832 }
3833
3834 /**
3835 * Base class for implementing an input pipeline stage that supports
3836 * asynchronous and out-of-order processing of input events.
3837 * <p>
3838 * In addition to what a normal input stage can do, an asynchronous
3839 * input stage may also defer an input event that has been delivered to it
3840 * and finish or forward it later.
3841 * </p>
3842 */
3843 abstract class AsyncInputStage extends InputStage {
3844 private final String mTraceCounter;
3845
3846 private QueuedInputEvent mQueueHead;
3847 private QueuedInputEvent mQueueTail;
3848 private int mQueueLength;
3849
3850 protected static final int DEFER = 3;
3851
3852 /**
3853 * Creates an asynchronous input stage.
3854 * @param next The next stage to which events should be forwarded.
3855 * @param traceCounter The name of a counter to record the size of
3856 * the queue of pending events.
3857 */
3858 public AsyncInputStage(InputStage next, String traceCounter) {
3859 super(next);
3860 mTraceCounter = traceCounter;
3861 }
3862
3863 /**
3864 * Marks the event as deferred, which is to say that it will be handled
3865 * asynchronously. The caller is responsible for calling {@link #forward}
3866 * or {@link #finish} later when it is done handling the event.
3867 */
3868 protected void defer(QueuedInputEvent q) {
3869 q.mFlags |= QueuedInputEvent.FLAG_DEFERRED;
3870 enqueue(q);
3871 }
3872
3873 @Override
3874 protected void forward(QueuedInputEvent q) {
3875 // Clear the deferred flag.
3876 q.mFlags &= ~QueuedInputEvent.FLAG_DEFERRED;
3877
3878 // Fast path if the queue is empty.
3879 QueuedInputEvent curr = mQueueHead;
3880 if (curr == null) {
3881 super.forward(q);
3882 return;
3883 }
3884
3885 // Determine whether the event must be serialized behind any others
3886 // before it can be delivered to the next stage. This is done because
3887 // deferred events might be handled out of order by the stage.
3888 final int deviceId = q.mEvent.getDeviceId();
3889 QueuedInputEvent prev = null;
3890 boolean blocked = false;
3891 while (curr != null && curr != q) {
3892 if (!blocked && deviceId == curr.mEvent.getDeviceId()) {
3893 blocked = true;
3894 }
3895 prev = curr;
3896 curr = curr.mNext;
3897 }
3898
3899 // If the event is blocked, then leave it in the queue to be delivered later.
3900 // Note that the event might not yet be in the queue if it was not previously
3901 // deferred so we will enqueue it if needed.
3902 if (blocked) {
3903 if (curr == null) {
3904 enqueue(q);
3905 }
3906 return;
3907 }
3908
3909 // The event is not blocked. Deliver it immediately.
3910 if (curr != null) {
3911 curr = curr.mNext;
3912 dequeue(q, prev);
3913 }
3914 super.forward(q);
3915
3916 // Dequeuing this event may have unblocked successors. Deliver them.
3917 while (curr != null) {
3918 if (deviceId == curr.mEvent.getDeviceId()) {
3919 if ((curr.mFlags & QueuedInputEvent.FLAG_DEFERRED) != 0) {
3920 break;
3921 }
3922 QueuedInputEvent next = curr.mNext;
3923 dequeue(curr, prev);
3924 super.forward(curr);
3925 curr = next;
3926 } else {
3927 prev = curr;
3928 curr = curr.mNext;
3929 }
3930 }
3931 }
3932
3933 @Override
3934 protected void apply(QueuedInputEvent q, int result) {
3935 if (result == DEFER) {
3936 defer(q);
3937 } else {
3938 super.apply(q, result);
3939 }
3940 }
3941
3942 private void enqueue(QueuedInputEvent q) {
3943 if (mQueueTail == null) {
3944 mQueueHead = q;
3945 mQueueTail = q;
3946 } else {
3947 mQueueTail.mNext = q;
3948 mQueueTail = q;
3949 }
3950
3951 mQueueLength += 1;
3952 Trace.traceCounter(Trace.TRACE_TAG_INPUT, mTraceCounter, mQueueLength);
3953 }
3954
3955 private void dequeue(QueuedInputEvent q, QueuedInputEvent prev) {
3956 if (prev == null) {
3957 mQueueHead = q.mNext;
3958 } else {
3959 prev.mNext = q.mNext;
3960 }
3961 if (mQueueTail == q) {
3962 mQueueTail = prev;
3963 }
3964 q.mNext = null;
3965
3966 mQueueLength -= 1;
3967 Trace.traceCounter(Trace.TRACE_TAG_INPUT, mTraceCounter, mQueueLength);
3968 }
Jeff Brown5182c782013-10-15 20:31:52 -07003969
3970 @Override
3971 void dump(String prefix, PrintWriter writer) {
3972 writer.print(prefix);
3973 writer.print(getClass().getName());
3974 writer.print(": mQueueLength=");
3975 writer.println(mQueueLength);
3976
3977 super.dump(prefix, writer);
3978 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07003979 }
3980
3981 /**
3982 * Delivers pre-ime input events to a native activity.
3983 * Does not support pointer events.
3984 */
Michael Wrighta44dd262013-04-10 21:12:00 -07003985 final class NativePreImeInputStage extends AsyncInputStage
3986 implements InputQueue.FinishedInputEventCallback {
Jeff Brownf9e989d2013-04-04 23:04:03 -07003987 public NativePreImeInputStage(InputStage next, String traceCounter) {
3988 super(next, traceCounter);
3989 }
3990
3991 @Override
3992 protected int onProcess(QueuedInputEvent q) {
Michael Wrighta44dd262013-04-10 21:12:00 -07003993 if (mInputQueue != null && q.mEvent instanceof KeyEvent) {
3994 mInputQueue.sendInputEvent(q.mEvent, q, true, this);
3995 return DEFER;
3996 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07003997 return FORWARD;
3998 }
Michael Wrighta44dd262013-04-10 21:12:00 -07003999
4000 @Override
4001 public void onFinishedInputEvent(Object token, boolean handled) {
4002 QueuedInputEvent q = (QueuedInputEvent)token;
4003 if (handled) {
4004 finish(q, true);
4005 return;
4006 }
4007 forward(q);
4008 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004009 }
4010
4011 /**
4012 * Delivers pre-ime input events to the view hierarchy.
4013 * Does not support pointer events.
4014 */
4015 final class ViewPreImeInputStage extends InputStage {
4016 public ViewPreImeInputStage(InputStage next) {
4017 super(next);
4018 }
4019
4020 @Override
4021 protected int onProcess(QueuedInputEvent q) {
Jeff Brown481c1572012-03-09 14:41:15 -08004022 if (q.mEvent instanceof KeyEvent) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004023 return processKeyEvent(q);
4024 }
4025 return FORWARD;
4026 }
4027
4028 private int processKeyEvent(QueuedInputEvent q) {
4029 final KeyEvent event = (KeyEvent)q.mEvent;
4030 if (mView.dispatchKeyEventPreIme(event)) {
4031 return FINISH_HANDLED;
4032 }
4033 return FORWARD;
4034 }
4035 }
4036
4037 /**
4038 * Delivers input events to the ime.
4039 * Does not support pointer events.
4040 */
4041 final class ImeInputStage extends AsyncInputStage
4042 implements InputMethodManager.FinishedInputEventCallback {
4043 public ImeInputStage(InputStage next, String traceCounter) {
4044 super(next, traceCounter);
4045 }
4046
4047 @Override
4048 protected int onProcess(QueuedInputEvent q) {
keunyoung30f420f2013-08-02 14:23:10 -07004049 if (mLastWasImTarget && !isInLocalFocusMode()) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004050 InputMethodManager imm = InputMethodManager.peekInstance();
4051 if (imm != null) {
4052 final InputEvent event = q.mEvent;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004053 if (DEBUG_IMF) Log.v(mTag, "Sending input event to IME: " + event);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004054 int result = imm.dispatchInputEvent(event, q, this, mHandler);
4055 if (result == InputMethodManager.DISPATCH_HANDLED) {
4056 return FINISH_HANDLED;
4057 } else if (result == InputMethodManager.DISPATCH_NOT_HANDLED) {
Adam Lesinskic0f6eed2013-10-28 16:03:19 -07004058 // The IME could not handle it, so skip along to the next InputStage
4059 return FORWARD;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004060 } else {
4061 return DEFER; // callback will be invoked later
4062 }
4063 }
4064 }
4065 return FORWARD;
4066 }
4067
4068 @Override
4069 public void onFinishedInputEvent(Object token, boolean handled) {
4070 QueuedInputEvent q = (QueuedInputEvent)token;
4071 if (handled) {
4072 finish(q, true);
4073 return;
4074 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004075 forward(q);
4076 }
4077 }
4078
4079 /**
4080 * Performs early processing of post-ime input events.
4081 */
4082 final class EarlyPostImeInputStage extends InputStage {
4083 public EarlyPostImeInputStage(InputStage next) {
4084 super(next);
4085 }
4086
4087 @Override
4088 protected int onProcess(QueuedInputEvent q) {
4089 if (q.mEvent instanceof KeyEvent) {
4090 return processKeyEvent(q);
Jeff Brown4952dfd2011-11-30 19:23:22 -08004091 } else {
Jeff Brown481c1572012-03-09 14:41:15 -08004092 final int source = q.mEvent.getSource();
4093 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004094 return processPointerEvent(q);
Jeff Brown481c1572012-03-09 14:41:15 -08004095 }
Jeff Brown4952dfd2011-11-30 19:23:22 -08004096 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004097 return FORWARD;
4098 }
4099
4100 private int processKeyEvent(QueuedInputEvent q) {
4101 final KeyEvent event = (KeyEvent)q.mEvent;
4102
4103 // If the key's purpose is to exit touch mode then we consume it
4104 // and consider it handled.
4105 if (checkForLeavingTouchModeAndConsume(event)) {
4106 return FINISH_HANDLED;
4107 }
4108
4109 // Make sure the fallback event policy sees all keys that will be
4110 // delivered to the view hierarchy.
4111 mFallbackEventHandler.preDispatchKeyEvent(event);
4112 return FORWARD;
4113 }
4114
4115 private int processPointerEvent(QueuedInputEvent q) {
4116 final MotionEvent event = (MotionEvent)q.mEvent;
4117
4118 // Translate the pointer event for compatibility, if needed.
4119 if (mTranslator != null) {
4120 mTranslator.translateEventInScreenToAppWindow(event);
4121 }
4122
4123 // Enter touch mode on down or scroll.
4124 final int action = event.getAction();
4125 if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL) {
4126 ensureTouchMode(true);
4127 }
4128
4129 // Offset the scroll position.
4130 if (mCurScrollY != 0) {
4131 event.offsetLocation(0, mCurScrollY);
4132 }
4133
4134 // Remember the touch position for possible drag-initiation.
4135 if (event.isTouchEvent()) {
4136 mLastTouchPoint.x = event.getRawX();
4137 mLastTouchPoint.y = event.getRawY();
Vladislav Kaznacheevba761122016-01-22 12:09:45 -08004138 mLastTouchSource = event.getSource();
Jeff Brownf9e989d2013-04-04 23:04:03 -07004139 }
4140 return FORWARD;
Jeff Brown4952dfd2011-11-30 19:23:22 -08004141 }
4142 }
4143
Jeff Brownf9e989d2013-04-04 23:04:03 -07004144 /**
4145 * Delivers post-ime input events to a native activity.
4146 */
Michael Wrighta44dd262013-04-10 21:12:00 -07004147 final class NativePostImeInputStage extends AsyncInputStage
4148 implements InputQueue.FinishedInputEventCallback {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004149 public NativePostImeInputStage(InputStage next, String traceCounter) {
4150 super(next, traceCounter);
4151 }
4152
4153 @Override
4154 protected int onProcess(QueuedInputEvent q) {
Michael Wrighta44dd262013-04-10 21:12:00 -07004155 if (mInputQueue != null) {
4156 mInputQueue.sendInputEvent(q.mEvent, q, false, this);
4157 return DEFER;
4158 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004159 return FORWARD;
4160 }
Michael Wrighta44dd262013-04-10 21:12:00 -07004161
4162 @Override
4163 public void onFinishedInputEvent(Object token, boolean handled) {
4164 QueuedInputEvent q = (QueuedInputEvent)token;
4165 if (handled) {
4166 finish(q, true);
4167 return;
4168 }
4169 forward(q);
4170 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004171 }
4172
4173 /**
4174 * Delivers post-ime input events to the view hierarchy.
4175 */
4176 final class ViewPostImeInputStage extends InputStage {
4177 public ViewPostImeInputStage(InputStage next) {
4178 super(next);
4179 }
4180
4181 @Override
4182 protected int onProcess(QueuedInputEvent q) {
Jeff Brown29c0ed22013-01-14 13:50:37 -08004183 if (q.mEvent instanceof KeyEvent) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004184 return processKeyEvent(q);
Jeff Brown29c0ed22013-01-14 13:50:37 -08004185 } else {
4186 final int source = q.mEvent.getSource();
Jeff Brownf9e989d2013-04-04 23:04:03 -07004187 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
4188 return processPointerEvent(q);
4189 } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
4190 return processTrackballEvent(q);
Jeff Brown29c0ed22013-01-14 13:50:37 -08004191 } else {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004192 return processGenericMotionEvent(q);
Jeff Brown29c0ed22013-01-14 13:50:37 -08004193 }
4194 }
Jeff Brown29c0ed22013-01-14 13:50:37 -08004195 }
Jeff Brown29c0ed22013-01-14 13:50:37 -08004196
Michael Wright9d744c72014-02-18 21:27:42 -08004197 @Override
4198 protected void onDeliverToNext(QueuedInputEvent q) {
4199 if (mUnbufferedInputDispatch
4200 && q.mEvent instanceof MotionEvent
4201 && ((MotionEvent)q.mEvent).isTouchEvent()
4202 && isTerminalInputEvent(q.mEvent)) {
4203 mUnbufferedInputDispatch = false;
4204 scheduleConsumeBatchedInput();
4205 }
4206 super.onDeliverToNext(q);
4207 }
4208
Jeff Brownf9e989d2013-04-04 23:04:03 -07004209 private int processKeyEvent(QueuedInputEvent q) {
4210 final KeyEvent event = (KeyEvent)q.mEvent;
4211
4212 // Deliver the key to the view hierarchy.
4213 if (mView.dispatchKeyEvent(event)) {
4214 return FINISH_HANDLED;
Jeff Brown21bc5c92011-02-28 18:27:14 -08004215 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004216
Michael Wright17d28ca2013-10-31 17:47:45 -07004217 if (shouldDropInputEvent(q)) {
4218 return FINISH_NOT_HANDLED;
4219 }
4220
Jeff Brownf9e989d2013-04-04 23:04:03 -07004221 // If the Control modifier is held, try to interpret the key as a shortcut.
4222 if (event.getAction() == KeyEvent.ACTION_DOWN
4223 && event.isCtrlPressed()
4224 && event.getRepeatCount() == 0
4225 && !KeyEvent.isModifierKey(event.getKeyCode())) {
4226 if (mView.dispatchKeyShortcutEvent(event)) {
4227 return FINISH_HANDLED;
4228 }
Michael Wright17d28ca2013-10-31 17:47:45 -07004229 if (shouldDropInputEvent(q)) {
4230 return FINISH_NOT_HANDLED;
4231 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004232 }
4233
4234 // Apply the fallback event policy.
4235 if (mFallbackEventHandler.dispatchKeyEvent(event)) {
4236 return FINISH_HANDLED;
4237 }
Michael Wright17d28ca2013-10-31 17:47:45 -07004238 if (shouldDropInputEvent(q)) {
4239 return FINISH_NOT_HANDLED;
4240 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004241
4242 // Handle automatic focus changes.
4243 if (event.getAction() == KeyEvent.ACTION_DOWN) {
4244 int direction = 0;
4245 switch (event.getKeyCode()) {
4246 case KeyEvent.KEYCODE_DPAD_LEFT:
4247 if (event.hasNoModifiers()) {
4248 direction = View.FOCUS_LEFT;
4249 }
4250 break;
4251 case KeyEvent.KEYCODE_DPAD_RIGHT:
4252 if (event.hasNoModifiers()) {
4253 direction = View.FOCUS_RIGHT;
4254 }
4255 break;
4256 case KeyEvent.KEYCODE_DPAD_UP:
4257 if (event.hasNoModifiers()) {
4258 direction = View.FOCUS_UP;
4259 }
4260 break;
4261 case KeyEvent.KEYCODE_DPAD_DOWN:
4262 if (event.hasNoModifiers()) {
4263 direction = View.FOCUS_DOWN;
4264 }
4265 break;
4266 case KeyEvent.KEYCODE_TAB:
4267 if (event.hasNoModifiers()) {
4268 direction = View.FOCUS_FORWARD;
4269 } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
4270 direction = View.FOCUS_BACKWARD;
4271 }
4272 break;
4273 }
4274 if (direction != 0) {
4275 View focused = mView.findFocus();
4276 if (focused != null) {
4277 View v = focused.focusSearch(direction);
4278 if (v != null && v != focused) {
4279 // do the math the get the interesting rect
4280 // of previous focused into the coord system of
4281 // newly focused view
4282 focused.getFocusedRect(mTempRect);
4283 if (mView instanceof ViewGroup) {
4284 ((ViewGroup) mView).offsetDescendantRectToMyCoords(
4285 focused, mTempRect);
4286 ((ViewGroup) mView).offsetRectIntoDescendantCoords(
4287 v, mTempRect);
4288 }
4289 if (v.requestFocus(direction, mTempRect)) {
4290 playSoundEffect(SoundEffectConstants
4291 .getContantForFocusDirection(direction));
4292 return FINISH_HANDLED;
4293 }
4294 }
4295
4296 // Give the focused view a last chance to handle the dpad key.
4297 if (mView.dispatchUnhandledMove(focused, direction)) {
4298 return FINISH_HANDLED;
4299 }
4300 } else {
4301 // find the best view to give focus to in this non-touch-mode with no-focus
4302 View v = focusSearch(null, direction);
4303 if (v != null && v.requestFocus(direction)) {
4304 return FINISH_HANDLED;
4305 }
4306 }
4307 }
4308 }
4309 return FORWARD;
Jeff Brown21bc5c92011-02-28 18:27:14 -08004310 }
4311
Jeff Brownf9e989d2013-04-04 23:04:03 -07004312 private int processPointerEvent(QueuedInputEvent q) {
4313 final MotionEvent event = (MotionEvent)q.mEvent;
4314
Vladislav Kaznacheev527905e2016-02-16 16:20:56 -08004315 mAttachInfo.mUnbufferedDispatchRequested = false;
4316 final View eventTarget =
4317 (event.isFromSource(InputDevice.SOURCE_MOUSE) && mCapturingView != null) ?
4318 mCapturingView : mView;
4319 mAttachInfo.mHandlingPointerEvent = true;
4320 boolean handled = eventTarget.dispatchPointerEvent(event);
4321 maybeUpdatePointerIcon(event);
4322 mAttachInfo.mHandlingPointerEvent = false;
4323 if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {
4324 mUnbufferedInputDispatch = true;
4325 if (mConsumeBatchedInputScheduled) {
4326 scheduleConsumeBatchedInputImmediately();
4327 }
4328 }
4329 return handled ? FINISH_HANDLED : FORWARD;
4330 }
4331
4332 private void maybeUpdatePointerIcon(MotionEvent event) {
Jun Mukai1db53972015-09-11 18:08:31 -07004333 if (event.getPointerCount() == 1
4334 && event.isFromSource(InputDevice.SOURCE_MOUSE)) {
4335 if (event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER
4336 || event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
4337 // Other apps or the window manager may change the icon shape outside of
4338 // this app, therefore the icon shape has to be reset on enter/exit event.
4339 mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
4340 }
4341
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08004342 if (event.getActionMasked() != MotionEvent.ACTION_HOVER_EXIT) {
4343 if (!updatePointerIcon(event) &&
4344 event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE) {
4345 mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
Jun Mukai1db53972015-09-11 18:08:31 -07004346 }
4347 }
4348 }
Jeff Brown3915bb82010-11-05 15:02:16 -07004349 }
4350
Jeff Brownf9e989d2013-04-04 23:04:03 -07004351 private int processTrackballEvent(QueuedInputEvent q) {
4352 final MotionEvent event = (MotionEvent)q.mEvent;
4353
4354 if (mView.dispatchTrackballEvent(event)) {
4355 return FINISH_HANDLED;
4356 }
4357 return FORWARD;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004358 }
4359
Jeff Brownf9e989d2013-04-04 23:04:03 -07004360 private int processGenericMotionEvent(QueuedInputEvent q) {
4361 final MotionEvent event = (MotionEvent)q.mEvent;
Jeff Brown00fa7bd2010-07-02 15:37:36 -07004362
Jeff Brownf9e989d2013-04-04 23:04:03 -07004363 // Deliver the event to the view.
4364 if (mView.dispatchGenericMotionEvent(event)) {
4365 return FINISH_HANDLED;
4366 }
4367 return FORWARD;
Jeff Brown3915bb82010-11-05 15:02:16 -07004368 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07004369 }
4370
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08004371 private void resetPointerIcon(MotionEvent event) {
4372 mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
4373 updatePointerIcon(event);
4374 }
4375
4376 private boolean updatePointerIcon(MotionEvent event) {
4377 final float x = event.getX();
4378 final float y = event.getY();
4379 if (x < 0 || x >= mView.getWidth() || y < 0 || y >= mView.getHeight()) {
4380 Slog.e(mTag, "updatePointerIcon called with position out of bounds");
4381 return false;
4382 }
4383 final PointerIcon pointerIcon = mView.getPointerIcon(event, x, y);
4384 final int pointerShape = (pointerIcon != null) ?
4385 pointerIcon.getStyle() : PointerIcon.STYLE_DEFAULT;
4386
4387 if (mPointerIconShape != pointerShape) {
4388 mPointerIconShape = pointerShape;
4389 if (mPointerIconShape != PointerIcon.STYLE_CUSTOM) {
4390 mCustomPointerIcon = null;
4391 InputManager.getInstance().setPointerIconShape(pointerShape);
4392 return true;
4393 }
4394 }
4395 if (mPointerIconShape == PointerIcon.STYLE_CUSTOM &&
4396 !pointerIcon.equals(mCustomPointerIcon)) {
4397 mCustomPointerIcon = pointerIcon;
4398 InputManager.getInstance().setCustomPointerIcon(mCustomPointerIcon);
4399 }
4400 return true;
4401 }
4402
Jeff Brownf9e989d2013-04-04 23:04:03 -07004403 /**
Jeff Brown678a1252013-04-09 17:46:25 -07004404 * Performs synthesis of new input events from unhandled input events.
Jeff Brownf9e989d2013-04-04 23:04:03 -07004405 */
4406 final class SyntheticInputStage extends InputStage {
Jeff Brown678a1252013-04-09 17:46:25 -07004407 private final SyntheticTrackballHandler mTrackball = new SyntheticTrackballHandler();
4408 private final SyntheticJoystickHandler mJoystick = new SyntheticJoystickHandler();
4409 private final SyntheticTouchNavigationHandler mTouchNavigation =
4410 new SyntheticTouchNavigationHandler();
Michael Wright899d7052014-04-23 17:23:39 -07004411 private final SyntheticKeyboardHandler mKeyboard = new SyntheticKeyboardHandler();
Jeff Brownf9e989d2013-04-04 23:04:03 -07004412
4413 public SyntheticInputStage() {
4414 super(null);
Jeff Brown21bc5c92011-02-28 18:27:14 -08004415 }
4416
Jeff Brownf9e989d2013-04-04 23:04:03 -07004417 @Override
4418 protected int onProcess(QueuedInputEvent q) {
4419 q.mFlags |= QueuedInputEvent.FLAG_RESYNTHESIZED;
4420 if (q.mEvent instanceof MotionEvent) {
Jeff Brown678a1252013-04-09 17:46:25 -07004421 final MotionEvent event = (MotionEvent)q.mEvent;
4422 final int source = event.getSource();
Jeff Brownf9e989d2013-04-04 23:04:03 -07004423 if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
Jeff Brown678a1252013-04-09 17:46:25 -07004424 mTrackball.process(event);
4425 return FINISH_HANDLED;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004426 } else if ((source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
Jeff Brown678a1252013-04-09 17:46:25 -07004427 mJoystick.process(event);
4428 return FINISH_HANDLED;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004429 } else if ((source & InputDevice.SOURCE_TOUCH_NAVIGATION)
4430 == InputDevice.SOURCE_TOUCH_NAVIGATION) {
Jeff Brown678a1252013-04-09 17:46:25 -07004431 mTouchNavigation.process(event);
4432 return FINISH_HANDLED;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004433 }
Michael Wright899d7052014-04-23 17:23:39 -07004434 } else if ((q.mFlags & QueuedInputEvent.FLAG_UNHANDLED) != 0) {
4435 mKeyboard.process((KeyEvent)q.mEvent);
4436 return FINISH_HANDLED;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004437 }
Michael Wright899d7052014-04-23 17:23:39 -07004438
Jeff Brownf9e989d2013-04-04 23:04:03 -07004439 return FORWARD;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004440 }
4441
Jeff Brownf9e989d2013-04-04 23:04:03 -07004442 @Override
4443 protected void onDeliverToNext(QueuedInputEvent q) {
4444 if ((q.mFlags & QueuedInputEvent.FLAG_RESYNTHESIZED) == 0) {
4445 // Cancel related synthetic events if any prior stage has handled the event.
4446 if (q.mEvent instanceof MotionEvent) {
Jeff Brown678a1252013-04-09 17:46:25 -07004447 final MotionEvent event = (MotionEvent)q.mEvent;
4448 final int source = event.getSource();
Jeff Brownf9e989d2013-04-04 23:04:03 -07004449 if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
Jeff Brown678a1252013-04-09 17:46:25 -07004450 mTrackball.cancel(event);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004451 } else if ((source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
Jeff Brown678a1252013-04-09 17:46:25 -07004452 mJoystick.cancel(event);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004453 } else if ((source & InputDevice.SOURCE_TOUCH_NAVIGATION)
4454 == InputDevice.SOURCE_TOUCH_NAVIGATION) {
Jeff Brown678a1252013-04-09 17:46:25 -07004455 mTouchNavigation.cancel(event);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004456 }
4457 }
4458 }
4459 super.onDeliverToNext(q);
4460 }
Jeff Brown678a1252013-04-09 17:46:25 -07004461 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004462
Jeff Brown678a1252013-04-09 17:46:25 -07004463 /**
4464 * Creates dpad events from unhandled trackball movements.
4465 */
4466 final class SyntheticTrackballHandler {
4467 private final TrackballAxis mX = new TrackballAxis();
4468 private final TrackballAxis mY = new TrackballAxis();
4469 private long mLastTime;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004470
Jeff Brown678a1252013-04-09 17:46:25 -07004471 public void process(MotionEvent event) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004472 // Translate the trackball event into DPAD keys and try to deliver those.
Jeff Brownf9e989d2013-04-04 23:04:03 -07004473 long curTime = SystemClock.uptimeMillis();
Jeff Brown678a1252013-04-09 17:46:25 -07004474 if ((mLastTime + MAX_TRACKBALL_DELAY) < curTime) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004475 // It has been too long since the last movement,
4476 // so restart at the beginning.
Jeff Brown678a1252013-04-09 17:46:25 -07004477 mX.reset(0);
4478 mY.reset(0);
4479 mLastTime = curTime;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004480 }
4481
4482 final int action = event.getAction();
4483 final int metaState = event.getMetaState();
4484 switch (action) {
4485 case MotionEvent.ACTION_DOWN:
Jeff Brown678a1252013-04-09 17:46:25 -07004486 mX.reset(2);
4487 mY.reset(2);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004488 enqueueInputEvent(new KeyEvent(curTime, curTime,
4489 KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, 0, metaState,
4490 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
4491 InputDevice.SOURCE_KEYBOARD));
4492 break;
4493 case MotionEvent.ACTION_UP:
Jeff Brown678a1252013-04-09 17:46:25 -07004494 mX.reset(2);
4495 mY.reset(2);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004496 enqueueInputEvent(new KeyEvent(curTime, curTime,
4497 KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, 0, metaState,
4498 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
4499 InputDevice.SOURCE_KEYBOARD));
4500 break;
4501 }
4502
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004503 if (DEBUG_TRACKBALL) Log.v(mTag, "TB X=" + mX.position + " step="
Jeff Brown678a1252013-04-09 17:46:25 -07004504 + mX.step + " dir=" + mX.dir + " acc=" + mX.acceleration
Jeff Brownf9e989d2013-04-04 23:04:03 -07004505 + " move=" + event.getX()
Jeff Brown678a1252013-04-09 17:46:25 -07004506 + " / Y=" + mY.position + " step="
4507 + mY.step + " dir=" + mY.dir + " acc=" + mY.acceleration
Jeff Brownf9e989d2013-04-04 23:04:03 -07004508 + " move=" + event.getY());
Jeff Brown678a1252013-04-09 17:46:25 -07004509 final float xOff = mX.collect(event.getX(), event.getEventTime(), "X");
4510 final float yOff = mY.collect(event.getY(), event.getEventTime(), "Y");
Jeff Brownf9e989d2013-04-04 23:04:03 -07004511
4512 // Generate DPAD events based on the trackball movement.
4513 // We pick the axis that has moved the most as the direction of
4514 // the DPAD. When we generate DPAD events for one axis, then the
4515 // other axis is reset -- we don't want to perform DPAD jumps due
4516 // to slight movements in the trackball when making major movements
4517 // along the other axis.
4518 int keycode = 0;
4519 int movement = 0;
4520 float accel = 1;
4521 if (xOff > yOff) {
Jeff Brown678a1252013-04-09 17:46:25 -07004522 movement = mX.generate();
Jeff Brownf9e989d2013-04-04 23:04:03 -07004523 if (movement != 0) {
4524 keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_RIGHT
4525 : KeyEvent.KEYCODE_DPAD_LEFT;
Jeff Brown678a1252013-04-09 17:46:25 -07004526 accel = mX.acceleration;
4527 mY.reset(2);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004528 }
4529 } else if (yOff > 0) {
Jeff Brown678a1252013-04-09 17:46:25 -07004530 movement = mY.generate();
Jeff Brownf9e989d2013-04-04 23:04:03 -07004531 if (movement != 0) {
4532 keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_DOWN
4533 : KeyEvent.KEYCODE_DPAD_UP;
Jeff Brown678a1252013-04-09 17:46:25 -07004534 accel = mY.acceleration;
4535 mX.reset(2);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004536 }
4537 }
4538
4539 if (keycode != 0) {
4540 if (movement < 0) movement = -movement;
4541 int accelMovement = (int)(movement * accel);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004542 if (DEBUG_TRACKBALL) Log.v(mTag, "Move: movement=" + movement
Jeff Brownf9e989d2013-04-04 23:04:03 -07004543 + " accelMovement=" + accelMovement
4544 + " accel=" + accel);
4545 if (accelMovement > movement) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004546 if (DEBUG_TRACKBALL) Log.v(mTag, "Delivering fake DPAD: "
Jeff Brownf9e989d2013-04-04 23:04:03 -07004547 + keycode);
4548 movement--;
4549 int repeatCount = accelMovement - movement;
4550 enqueueInputEvent(new KeyEvent(curTime, curTime,
4551 KeyEvent.ACTION_MULTIPLE, keycode, repeatCount, metaState,
4552 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
4553 InputDevice.SOURCE_KEYBOARD));
4554 }
4555 while (movement > 0) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004556 if (DEBUG_TRACKBALL) Log.v(mTag, "Delivering fake DPAD: "
Jeff Brownf9e989d2013-04-04 23:04:03 -07004557 + keycode);
4558 movement--;
4559 curTime = SystemClock.uptimeMillis();
4560 enqueueInputEvent(new KeyEvent(curTime, curTime,
4561 KeyEvent.ACTION_DOWN, keycode, 0, metaState,
4562 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
4563 InputDevice.SOURCE_KEYBOARD));
4564 enqueueInputEvent(new KeyEvent(curTime, curTime,
4565 KeyEvent.ACTION_UP, keycode, 0, metaState,
4566 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
4567 InputDevice.SOURCE_KEYBOARD));
4568 }
Jeff Brown678a1252013-04-09 17:46:25 -07004569 mLastTime = curTime;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004570 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004571 }
4572
Jeff Brown678a1252013-04-09 17:46:25 -07004573 public void cancel(MotionEvent event) {
4574 mLastTime = Integer.MIN_VALUE;
Jeff Brown3915bb82010-11-05 15:02:16 -07004575
Jeff Brownf9e989d2013-04-04 23:04:03 -07004576 // If we reach this, we consumed a trackball event.
4577 // Because we will not translate the trackball event into a key event,
4578 // touch mode will not exit, so we exit touch mode here.
4579 if (mView != null && mAdded) {
4580 ensureTouchMode(false);
Jeff Brown00fa7bd2010-07-02 15:37:36 -07004581 }
4582 }
Jeff Brown678a1252013-04-09 17:46:25 -07004583 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004584
Jeff Brown678a1252013-04-09 17:46:25 -07004585 /**
4586 * Maintains state information for a single trackball axis, generating
4587 * discrete (DPAD) movements based on raw trackball motion.
4588 */
4589 static final class TrackballAxis {
4590 /**
4591 * The maximum amount of acceleration we will apply.
4592 */
4593 static final float MAX_ACCELERATION = 20;
4594
4595 /**
4596 * The maximum amount of time (in milliseconds) between events in order
4597 * for us to consider the user to be doing fast trackball movements,
4598 * and thus apply an acceleration.
4599 */
4600 static final long FAST_MOVE_TIME = 150;
4601
4602 /**
4603 * Scaling factor to the time (in milliseconds) between events to how
4604 * much to multiple/divide the current acceleration. When movement
4605 * is < FAST_MOVE_TIME this multiplies the acceleration; when >
4606 * FAST_MOVE_TIME it divides it.
4607 */
4608 static final float ACCEL_MOVE_SCALING_FACTOR = (1.0f/40);
4609
4610 static final float FIRST_MOVEMENT_THRESHOLD = 0.5f;
4611 static final float SECOND_CUMULATIVE_MOVEMENT_THRESHOLD = 2.0f;
4612 static final float SUBSEQUENT_INCREMENTAL_MOVEMENT_THRESHOLD = 1.0f;
4613
4614 float position;
4615 float acceleration = 1;
4616 long lastMoveTime = 0;
4617 int step;
4618 int dir;
4619 int nonAccelMovement;
4620
4621 void reset(int _step) {
4622 position = 0;
4623 acceleration = 1;
4624 lastMoveTime = 0;
4625 step = _step;
4626 dir = 0;
Jeff Brown6f2fba42011-02-19 01:08:02 -08004627 }
4628
Jeff Brown678a1252013-04-09 17:46:25 -07004629 /**
4630 * Add trackball movement into the state. If the direction of movement
4631 * has been reversed, the state is reset before adding the
4632 * movement (so that you don't have to compensate for any previously
4633 * collected movement before see the result of the movement in the
4634 * new direction).
4635 *
4636 * @return Returns the absolute value of the amount of movement
4637 * collected so far.
4638 */
4639 float collect(float off, long time, String axis) {
4640 long normTime;
4641 if (off > 0) {
4642 normTime = (long)(off * FAST_MOVE_TIME);
4643 if (dir < 0) {
4644 if (DEBUG_TRACKBALL) Log.v(TAG, axis + " reversed to positive!");
4645 position = 0;
4646 step = 0;
4647 acceleration = 1;
4648 lastMoveTime = 0;
4649 }
4650 dir = 1;
4651 } else if (off < 0) {
4652 normTime = (long)((-off) * FAST_MOVE_TIME);
4653 if (dir > 0) {
4654 if (DEBUG_TRACKBALL) Log.v(TAG, axis + " reversed to negative!");
4655 position = 0;
4656 step = 0;
4657 acceleration = 1;
4658 lastMoveTime = 0;
4659 }
4660 dir = -1;
4661 } else {
4662 normTime = 0;
4663 }
4664
4665 // The number of milliseconds between each movement that is
4666 // considered "normal" and will not result in any acceleration
4667 // or deceleration, scaled by the offset we have here.
4668 if (normTime > 0) {
4669 long delta = time - lastMoveTime;
4670 lastMoveTime = time;
4671 float acc = acceleration;
4672 if (delta < normTime) {
4673 // The user is scrolling rapidly, so increase acceleration.
4674 float scale = (normTime-delta) * ACCEL_MOVE_SCALING_FACTOR;
4675 if (scale > 1) acc *= scale;
4676 if (DEBUG_TRACKBALL) Log.v(TAG, axis + " accelerate: off="
4677 + off + " normTime=" + normTime + " delta=" + delta
4678 + " scale=" + scale + " acc=" + acc);
4679 acceleration = acc < MAX_ACCELERATION ? acc : MAX_ACCELERATION;
4680 } else {
4681 // The user is scrolling slowly, so decrease acceleration.
4682 float scale = (delta-normTime) * ACCEL_MOVE_SCALING_FACTOR;
4683 if (scale > 1) acc /= scale;
4684 if (DEBUG_TRACKBALL) Log.v(TAG, axis + " deccelerate: off="
4685 + off + " normTime=" + normTime + " delta=" + delta
4686 + " scale=" + scale + " acc=" + acc);
4687 acceleration = acc > 1 ? acc : 1;
4688 }
4689 }
4690 position += off;
4691 return Math.abs(position);
Jeff Brown6f2fba42011-02-19 01:08:02 -08004692 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004693
Jeff Brown678a1252013-04-09 17:46:25 -07004694 /**
4695 * Generate the number of discrete movement events appropriate for
4696 * the currently collected trackball movement.
4697 *
4698 * @return Returns the number of discrete movements, either positive
4699 * or negative, or 0 if there is not enough trackball movement yet
4700 * for a discrete movement.
4701 */
4702 int generate() {
4703 int movement = 0;
4704 nonAccelMovement = 0;
4705 do {
4706 final int dir = position >= 0 ? 1 : -1;
4707 switch (step) {
4708 // If we are going to execute the first step, then we want
4709 // to do this as soon as possible instead of waiting for
4710 // a full movement, in order to make things look responsive.
4711 case 0:
4712 if (Math.abs(position) < FIRST_MOVEMENT_THRESHOLD) {
4713 return movement;
4714 }
4715 movement += dir;
4716 nonAccelMovement += dir;
4717 step = 1;
4718 break;
4719 // If we have generated the first movement, then we need
4720 // to wait for the second complete trackball motion before
4721 // generating the second discrete movement.
4722 case 1:
4723 if (Math.abs(position) < SECOND_CUMULATIVE_MOVEMENT_THRESHOLD) {
4724 return movement;
4725 }
4726 movement += dir;
4727 nonAccelMovement += dir;
4728 position -= SECOND_CUMULATIVE_MOVEMENT_THRESHOLD * dir;
4729 step = 2;
4730 break;
4731 // After the first two, we generate discrete movements
4732 // consistently with the trackball, applying an acceleration
4733 // if the trackball is moving quickly. This is a simple
4734 // acceleration on top of what we already compute based
4735 // on how quickly the wheel is being turned, to apply
4736 // a longer increasing acceleration to continuous movement
4737 // in one direction.
4738 default:
4739 if (Math.abs(position) < SUBSEQUENT_INCREMENTAL_MOVEMENT_THRESHOLD) {
4740 return movement;
4741 }
4742 movement += dir;
4743 position -= dir * SUBSEQUENT_INCREMENTAL_MOVEMENT_THRESHOLD;
4744 float acc = acceleration;
4745 acc *= 1.1f;
4746 acceleration = acc < MAX_ACCELERATION ? acc : acceleration;
4747 break;
4748 }
4749 } while (true);
4750 }
4751 }
4752
4753 /**
4754 * Creates dpad events from unhandled joystick movements.
4755 */
4756 final class SyntheticJoystickHandler extends Handler {
Michael Wright9adca062014-03-19 11:51:26 -07004757 private final static String TAG = "SyntheticJoystickHandler";
Jeff Brown678a1252013-04-09 17:46:25 -07004758 private final static int MSG_ENQUEUE_X_AXIS_KEY_REPEAT = 1;
4759 private final static int MSG_ENQUEUE_Y_AXIS_KEY_REPEAT = 2;
4760
4761 private int mLastXDirection;
4762 private int mLastYDirection;
4763 private int mLastXKeyCode;
4764 private int mLastYKeyCode;
4765
4766 public SyntheticJoystickHandler() {
4767 super(true);
4768 }
4769
4770 @Override
4771 public void handleMessage(Message msg) {
4772 switch (msg.what) {
4773 case MSG_ENQUEUE_X_AXIS_KEY_REPEAT:
4774 case MSG_ENQUEUE_Y_AXIS_KEY_REPEAT: {
4775 KeyEvent oldEvent = (KeyEvent)msg.obj;
4776 KeyEvent e = KeyEvent.changeTimeRepeat(oldEvent,
4777 SystemClock.uptimeMillis(),
4778 oldEvent.getRepeatCount() + 1);
4779 if (mAttachInfo.mHasWindowFocus) {
4780 enqueueInputEvent(e);
4781 Message m = obtainMessage(msg.what, e);
4782 m.setAsynchronous(true);
4783 sendMessageDelayed(m, ViewConfiguration.getKeyRepeatDelay());
4784 }
4785 } break;
4786 }
4787 }
4788
4789 public void process(MotionEvent event) {
Michael Wright9adca062014-03-19 11:51:26 -07004790 switch(event.getActionMasked()) {
4791 case MotionEvent.ACTION_CANCEL:
4792 cancel(event);
4793 break;
4794 case MotionEvent.ACTION_MOVE:
4795 update(event, true);
4796 break;
4797 default:
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004798 Log.w(mTag, "Unexpected action: " + event.getActionMasked());
Michael Wright9adca062014-03-19 11:51:26 -07004799 }
Jeff Brown678a1252013-04-09 17:46:25 -07004800 }
4801
Michael Wright9adca062014-03-19 11:51:26 -07004802 private void cancel(MotionEvent event) {
4803 removeMessages(MSG_ENQUEUE_X_AXIS_KEY_REPEAT);
4804 removeMessages(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT);
Jeff Brown678a1252013-04-09 17:46:25 -07004805 update(event, false);
4806 }
4807
4808 private void update(MotionEvent event, boolean synthesizeNewKeys) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004809 final long time = event.getEventTime();
4810 final int metaState = event.getMetaState();
4811 final int deviceId = event.getDeviceId();
4812 final int source = event.getSource();
4813
4814 int xDirection = joystickAxisValueToDirection(
4815 event.getAxisValue(MotionEvent.AXIS_HAT_X));
4816 if (xDirection == 0) {
4817 xDirection = joystickAxisValueToDirection(event.getX());
Jeff Browncb1404e2011-01-15 18:14:15 -08004818 }
4819
Jeff Brownf9e989d2013-04-04 23:04:03 -07004820 int yDirection = joystickAxisValueToDirection(
4821 event.getAxisValue(MotionEvent.AXIS_HAT_Y));
4822 if (yDirection == 0) {
4823 yDirection = joystickAxisValueToDirection(event.getY());
4824 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004825
Jeff Brown678a1252013-04-09 17:46:25 -07004826 if (xDirection != mLastXDirection) {
4827 if (mLastXKeyCode != 0) {
4828 removeMessages(MSG_ENQUEUE_X_AXIS_KEY_REPEAT);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004829 enqueueInputEvent(new KeyEvent(time, time,
Jeff Brown678a1252013-04-09 17:46:25 -07004830 KeyEvent.ACTION_UP, mLastXKeyCode, 0, metaState,
Jeff Brownf9e989d2013-04-04 23:04:03 -07004831 deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
Jeff Brown678a1252013-04-09 17:46:25 -07004832 mLastXKeyCode = 0;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004833 }
4834
Jeff Brown678a1252013-04-09 17:46:25 -07004835 mLastXDirection = xDirection;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004836
4837 if (xDirection != 0 && synthesizeNewKeys) {
Jeff Brown678a1252013-04-09 17:46:25 -07004838 mLastXKeyCode = xDirection > 0
Jeff Brownf9e989d2013-04-04 23:04:03 -07004839 ? KeyEvent.KEYCODE_DPAD_RIGHT : KeyEvent.KEYCODE_DPAD_LEFT;
4840 final KeyEvent e = new KeyEvent(time, time,
Jeff Brown678a1252013-04-09 17:46:25 -07004841 KeyEvent.ACTION_DOWN, mLastXKeyCode, 0, metaState,
Jeff Brownf9e989d2013-04-04 23:04:03 -07004842 deviceId, 0, KeyEvent.FLAG_FALLBACK, source);
4843 enqueueInputEvent(e);
Jeff Brown678a1252013-04-09 17:46:25 -07004844 Message m = obtainMessage(MSG_ENQUEUE_X_AXIS_KEY_REPEAT, e);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004845 m.setAsynchronous(true);
Michael Wrightb9618522013-04-10 15:20:56 -07004846 sendMessageDelayed(m, ViewConfiguration.getKeyRepeatTimeout());
Jeff Brownf9e989d2013-04-04 23:04:03 -07004847 }
4848 }
4849
Jeff Brown678a1252013-04-09 17:46:25 -07004850 if (yDirection != mLastYDirection) {
4851 if (mLastYKeyCode != 0) {
4852 removeMessages(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004853 enqueueInputEvent(new KeyEvent(time, time,
Jeff Brown678a1252013-04-09 17:46:25 -07004854 KeyEvent.ACTION_UP, mLastYKeyCode, 0, metaState,
Jeff Brownf9e989d2013-04-04 23:04:03 -07004855 deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
Jeff Brown678a1252013-04-09 17:46:25 -07004856 mLastYKeyCode = 0;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004857 }
4858
Jeff Brown678a1252013-04-09 17:46:25 -07004859 mLastYDirection = yDirection;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004860
4861 if (yDirection != 0 && synthesizeNewKeys) {
Jeff Brown678a1252013-04-09 17:46:25 -07004862 mLastYKeyCode = yDirection > 0
Jeff Brownf9e989d2013-04-04 23:04:03 -07004863 ? KeyEvent.KEYCODE_DPAD_DOWN : KeyEvent.KEYCODE_DPAD_UP;
4864 final KeyEvent e = new KeyEvent(time, time,
Jeff Brown678a1252013-04-09 17:46:25 -07004865 KeyEvent.ACTION_DOWN, mLastYKeyCode, 0, metaState,
Jeff Brownf9e989d2013-04-04 23:04:03 -07004866 deviceId, 0, KeyEvent.FLAG_FALLBACK, source);
4867 enqueueInputEvent(e);
Jeff Brown678a1252013-04-09 17:46:25 -07004868 Message m = obtainMessage(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT, e);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004869 m.setAsynchronous(true);
Jeff Brown678a1252013-04-09 17:46:25 -07004870 sendMessageDelayed(m, ViewConfiguration.getKeyRepeatTimeout());
Jeff Brownf9e989d2013-04-04 23:04:03 -07004871 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004872 }
4873 }
4874
Jeff Brownf9e989d2013-04-04 23:04:03 -07004875 private int joystickAxisValueToDirection(float value) {
4876 if (value >= 0.5f) {
4877 return 1;
4878 } else if (value <= -0.5f) {
4879 return -1;
4880 } else {
4881 return 0;
Jeff Browncb1404e2011-01-15 18:14:15 -08004882 }
4883 }
Jeff Brown678a1252013-04-09 17:46:25 -07004884 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004885
Jeff Brown678a1252013-04-09 17:46:25 -07004886 /**
4887 * Creates dpad events from unhandled touch navigation movements.
4888 */
4889 final class SyntheticTouchNavigationHandler extends Handler {
Jeff Brown4dac9012013-04-10 01:03:19 -07004890 private static final String LOCAL_TAG = "SyntheticTouchNavigationHandler";
4891 private static final boolean LOCAL_DEBUG = false;
Jeff Brown678a1252013-04-09 17:46:25 -07004892
Jeff Brown4dac9012013-04-10 01:03:19 -07004893 // Assumed nominal width and height in millimeters of a touch navigation pad,
4894 // if no resolution information is available from the input system.
4895 private static final float DEFAULT_WIDTH_MILLIMETERS = 48;
4896 private static final float DEFAULT_HEIGHT_MILLIMETERS = 48;
Jeff Brown678a1252013-04-09 17:46:25 -07004897
Jeff Brown4dac9012013-04-10 01:03:19 -07004898 /* TODO: These constants should eventually be moved to ViewConfiguration. */
Jeff Brown678a1252013-04-09 17:46:25 -07004899
Jeff Brown4dac9012013-04-10 01:03:19 -07004900 // The nominal distance traveled to move by one unit.
4901 private static final int TICK_DISTANCE_MILLIMETERS = 12;
4902
4903 // Minimum and maximum fling velocity in ticks per second.
4904 // The minimum velocity should be set such that we perform enough ticks per
4905 // second that the fling appears to be fluid. For example, if we set the minimum
4906 // to 2 ticks per second, then there may be up to half a second delay between the next
4907 // to last and last ticks which is noticeably discrete and jerky. This value should
4908 // probably not be set to anything less than about 4.
4909 // If fling accuracy is a problem then consider tuning the tick distance instead.
4910 private static final float MIN_FLING_VELOCITY_TICKS_PER_SECOND = 6f;
4911 private static final float MAX_FLING_VELOCITY_TICKS_PER_SECOND = 20f;
4912
4913 // Fling velocity decay factor applied after each new key is emitted.
4914 // This parameter controls the deceleration and overall duration of the fling.
4915 // The fling stops automatically when its velocity drops below the minimum
4916 // fling velocity defined above.
4917 private static final float FLING_TICK_DECAY = 0.8f;
4918
4919 /* The input device that we are tracking. */
4920
4921 private int mCurrentDeviceId = -1;
4922 private int mCurrentSource;
4923 private boolean mCurrentDeviceSupported;
4924
4925 /* Configuration for the current input device. */
4926
Jeff Brown4dac9012013-04-10 01:03:19 -07004927 // The scaled tick distance. A movement of this amount should generally translate
4928 // into a single dpad event in a given direction.
4929 private float mConfigTickDistance;
4930
4931 // The minimum and maximum scaled fling velocity.
4932 private float mConfigMinFlingVelocity;
4933 private float mConfigMaxFlingVelocity;
4934
4935 /* Tracking state. */
4936
4937 // The velocity tracker for detecting flings.
4938 private VelocityTracker mVelocityTracker;
4939
4940 // The active pointer id, or -1 if none.
4941 private int mActivePointerId = -1;
4942
John Reck79d81e62013-11-05 13:26:57 -08004943 // Location where tracking started.
Jeff Brown4dac9012013-04-10 01:03:19 -07004944 private float mStartX;
4945 private float mStartY;
4946
4947 // Most recently observed position.
4948 private float mLastX;
4949 private float mLastY;
4950
4951 // Accumulated movement delta since the last direction key was sent.
Jeff Brown678a1252013-04-09 17:46:25 -07004952 private float mAccumulatedX;
4953 private float mAccumulatedY;
4954
Jeff Brown4dac9012013-04-10 01:03:19 -07004955 // Set to true if any movement was delivered to the app.
4956 // Implies that tap slop was exceeded.
4957 private boolean mConsumedMovement;
Jeff Brown678a1252013-04-09 17:46:25 -07004958
Jeff Brown4dac9012013-04-10 01:03:19 -07004959 // The most recently sent key down event.
4960 // The keycode remains set until the direction changes or a fling ends
4961 // so that repeated key events may be generated as required.
4962 private long mPendingKeyDownTime;
4963 private int mPendingKeyCode = KeyEvent.KEYCODE_UNKNOWN;
4964 private int mPendingKeyRepeatCount;
4965 private int mPendingKeyMetaState;
Jeff Brown678a1252013-04-09 17:46:25 -07004966
Jeff Brown4dac9012013-04-10 01:03:19 -07004967 // The current fling velocity while a fling is in progress.
4968 private boolean mFlinging;
4969 private float mFlingVelocity;
Jeff Brown678a1252013-04-09 17:46:25 -07004970
4971 public SyntheticTouchNavigationHandler() {
4972 super(true);
Jeff Brown678a1252013-04-09 17:46:25 -07004973 }
4974
4975 public void process(MotionEvent event) {
Jeff Brown4dac9012013-04-10 01:03:19 -07004976 // Update the current device information.
4977 final long time = event.getEventTime();
4978 final int deviceId = event.getDeviceId();
4979 final int source = event.getSource();
4980 if (mCurrentDeviceId != deviceId || mCurrentSource != source) {
4981 finishKeys(time);
4982 finishTracking(time);
4983 mCurrentDeviceId = deviceId;
4984 mCurrentSource = source;
4985 mCurrentDeviceSupported = false;
4986 InputDevice device = event.getDevice();
4987 if (device != null) {
4988 // In order to support an input device, we must know certain
4989 // characteristics about it, such as its size and resolution.
4990 InputDevice.MotionRange xRange = device.getMotionRange(MotionEvent.AXIS_X);
4991 InputDevice.MotionRange yRange = device.getMotionRange(MotionEvent.AXIS_Y);
4992 if (xRange != null && yRange != null) {
4993 mCurrentDeviceSupported = true;
Jeff Brown678a1252013-04-09 17:46:25 -07004994
Jeff Brown4dac9012013-04-10 01:03:19 -07004995 // Infer the resolution if it not actually known.
4996 float xRes = xRange.getResolution();
4997 if (xRes <= 0) {
4998 xRes = xRange.getRange() / DEFAULT_WIDTH_MILLIMETERS;
4999 }
5000 float yRes = yRange.getResolution();
5001 if (yRes <= 0) {
5002 yRes = yRange.getRange() / DEFAULT_HEIGHT_MILLIMETERS;
5003 }
5004 float nominalRes = (xRes + yRes) * 0.5f;
Jeff Brown678a1252013-04-09 17:46:25 -07005005
Jeff Brown4dac9012013-04-10 01:03:19 -07005006 // Precompute all of the configuration thresholds we will need.
Jeff Brown4dac9012013-04-10 01:03:19 -07005007 mConfigTickDistance = TICK_DISTANCE_MILLIMETERS * nominalRes;
5008 mConfigMinFlingVelocity =
5009 MIN_FLING_VELOCITY_TICKS_PER_SECOND * mConfigTickDistance;
5010 mConfigMaxFlingVelocity =
5011 MAX_FLING_VELOCITY_TICKS_PER_SECOND * mConfigTickDistance;
5012
5013 if (LOCAL_DEBUG) {
5014 Log.d(LOCAL_TAG, "Configured device " + mCurrentDeviceId
5015 + " (" + Integer.toHexString(mCurrentSource) + "): "
Jeff Brown4dac9012013-04-10 01:03:19 -07005016 + ", mConfigTickDistance=" + mConfigTickDistance
5017 + ", mConfigMinFlingVelocity=" + mConfigMinFlingVelocity
5018 + ", mConfigMaxFlingVelocity=" + mConfigMaxFlingVelocity);
5019 }
5020 }
5021 }
Jeff Brown678a1252013-04-09 17:46:25 -07005022 }
Jeff Brown4dac9012013-04-10 01:03:19 -07005023 if (!mCurrentDeviceSupported) {
Jeff Brown678a1252013-04-09 17:46:25 -07005024 return;
5025 }
5026
Jeff Brown4dac9012013-04-10 01:03:19 -07005027 // Handle the event.
5028 final int action = event.getActionMasked();
5029 switch (action) {
Jeff Brown678a1252013-04-09 17:46:25 -07005030 case MotionEvent.ACTION_DOWN: {
Jeff Brown4dac9012013-04-10 01:03:19 -07005031 boolean caughtFling = mFlinging;
5032 finishKeys(time);
5033 finishTracking(time);
5034 mActivePointerId = event.getPointerId(0);
5035 mVelocityTracker = VelocityTracker.obtain();
5036 mVelocityTracker.addMovement(event);
Jeff Brown4dac9012013-04-10 01:03:19 -07005037 mStartX = event.getX();
5038 mStartY = event.getY();
5039 mLastX = mStartX;
5040 mLastY = mStartY;
Jeff Brown678a1252013-04-09 17:46:25 -07005041 mAccumulatedX = 0;
5042 mAccumulatedY = 0;
Jeff Brown4dac9012013-04-10 01:03:19 -07005043
5044 // If we caught a fling, then pretend that the tap slop has already
5045 // been exceeded to suppress taps whose only purpose is to stop the fling.
5046 mConsumedMovement = caughtFling;
Jeff Brown678a1252013-04-09 17:46:25 -07005047 break;
5048 }
5049
Jeff Brown4dac9012013-04-10 01:03:19 -07005050 case MotionEvent.ACTION_MOVE:
Jeff Brown678a1252013-04-09 17:46:25 -07005051 case MotionEvent.ACTION_UP: {
Jeff Brown4dac9012013-04-10 01:03:19 -07005052 if (mActivePointerId < 0) {
5053 break;
5054 }
5055 final int index = event.findPointerIndex(mActivePointerId);
5056 if (index < 0) {
5057 finishKeys(time);
5058 finishTracking(time);
5059 break;
5060 }
Jeff Brown678a1252013-04-09 17:46:25 -07005061
Jeff Brown4dac9012013-04-10 01:03:19 -07005062 mVelocityTracker.addMovement(event);
5063 final float x = event.getX(index);
5064 final float y = event.getY(index);
5065 mAccumulatedX += x - mLastX;
5066 mAccumulatedY += y - mLastY;
5067 mLastX = x;
5068 mLastY = y;
5069
5070 // Consume any accumulated movement so far.
5071 final int metaState = event.getMetaState();
5072 consumeAccumulatedMovement(time, metaState);
5073
5074 // Detect taps and flings.
5075 if (action == MotionEvent.ACTION_UP) {
Michael Wright88d7f792013-08-27 15:45:42 -07005076 if (mConsumedMovement && mPendingKeyCode != KeyEvent.KEYCODE_UNKNOWN) {
Jeff Brown4dac9012013-04-10 01:03:19 -07005077 // It might be a fling.
5078 mVelocityTracker.computeCurrentVelocity(1000, mConfigMaxFlingVelocity);
5079 final float vx = mVelocityTracker.getXVelocity(mActivePointerId);
5080 final float vy = mVelocityTracker.getYVelocity(mActivePointerId);
5081 if (!startFling(time, vx, vy)) {
5082 finishKeys(time);
Jeff Brown678a1252013-04-09 17:46:25 -07005083 }
5084 }
Jeff Brown4dac9012013-04-10 01:03:19 -07005085 finishTracking(time);
Jeff Brown678a1252013-04-09 17:46:25 -07005086 }
Jeff Brown4dac9012013-04-10 01:03:19 -07005087 break;
5088 }
5089
5090 case MotionEvent.ACTION_CANCEL: {
5091 finishKeys(time);
5092 finishTracking(time);
Jeff Brown678a1252013-04-09 17:46:25 -07005093 break;
5094 }
5095 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005096 }
Jeff Brown4dac9012013-04-10 01:03:19 -07005097
5098 public void cancel(MotionEvent event) {
5099 if (mCurrentDeviceId == event.getDeviceId()
5100 && mCurrentSource == event.getSource()) {
5101 final long time = event.getEventTime();
5102 finishKeys(time);
5103 finishTracking(time);
5104 }
5105 }
5106
5107 private void finishKeys(long time) {
5108 cancelFling();
5109 sendKeyUp(time);
5110 }
5111
5112 private void finishTracking(long time) {
5113 if (mActivePointerId >= 0) {
5114 mActivePointerId = -1;
5115 mVelocityTracker.recycle();
5116 mVelocityTracker = null;
5117 }
5118 }
5119
5120 private void consumeAccumulatedMovement(long time, int metaState) {
5121 final float absX = Math.abs(mAccumulatedX);
5122 final float absY = Math.abs(mAccumulatedY);
5123 if (absX >= absY) {
5124 if (absX >= mConfigTickDistance) {
5125 mAccumulatedX = consumeAccumulatedMovement(time, metaState, mAccumulatedX,
5126 KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT);
5127 mAccumulatedY = 0;
5128 mConsumedMovement = true;
5129 }
5130 } else {
5131 if (absY >= mConfigTickDistance) {
5132 mAccumulatedY = consumeAccumulatedMovement(time, metaState, mAccumulatedY,
5133 KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN);
5134 mAccumulatedX = 0;
5135 mConsumedMovement = true;
5136 }
5137 }
5138 }
5139
5140 private float consumeAccumulatedMovement(long time, int metaState,
5141 float accumulator, int negativeKeyCode, int positiveKeyCode) {
5142 while (accumulator <= -mConfigTickDistance) {
5143 sendKeyDownOrRepeat(time, negativeKeyCode, metaState);
5144 accumulator += mConfigTickDistance;
5145 }
5146 while (accumulator >= mConfigTickDistance) {
5147 sendKeyDownOrRepeat(time, positiveKeyCode, metaState);
5148 accumulator -= mConfigTickDistance;
5149 }
5150 return accumulator;
5151 }
5152
5153 private void sendKeyDownOrRepeat(long time, int keyCode, int metaState) {
5154 if (mPendingKeyCode != keyCode) {
5155 sendKeyUp(time);
5156 mPendingKeyDownTime = time;
5157 mPendingKeyCode = keyCode;
5158 mPendingKeyRepeatCount = 0;
5159 } else {
5160 mPendingKeyRepeatCount += 1;
5161 }
5162 mPendingKeyMetaState = metaState;
5163
5164 // Note: Normally we would pass FLAG_LONG_PRESS when the repeat count is 1
5165 // but it doesn't quite make sense when simulating the events in this way.
5166 if (LOCAL_DEBUG) {
5167 Log.d(LOCAL_TAG, "Sending key down: keyCode=" + mPendingKeyCode
5168 + ", repeatCount=" + mPendingKeyRepeatCount
5169 + ", metaState=" + Integer.toHexString(mPendingKeyMetaState));
5170 }
5171 enqueueInputEvent(new KeyEvent(mPendingKeyDownTime, time,
5172 KeyEvent.ACTION_DOWN, mPendingKeyCode, mPendingKeyRepeatCount,
5173 mPendingKeyMetaState, mCurrentDeviceId,
5174 KeyEvent.FLAG_FALLBACK, mCurrentSource));
5175 }
5176
5177 private void sendKeyUp(long time) {
5178 if (mPendingKeyCode != KeyEvent.KEYCODE_UNKNOWN) {
5179 if (LOCAL_DEBUG) {
5180 Log.d(LOCAL_TAG, "Sending key up: keyCode=" + mPendingKeyCode
5181 + ", metaState=" + Integer.toHexString(mPendingKeyMetaState));
5182 }
5183 enqueueInputEvent(new KeyEvent(mPendingKeyDownTime, time,
5184 KeyEvent.ACTION_UP, mPendingKeyCode, 0, mPendingKeyMetaState,
5185 mCurrentDeviceId, 0, KeyEvent.FLAG_FALLBACK,
5186 mCurrentSource));
5187 mPendingKeyCode = KeyEvent.KEYCODE_UNKNOWN;
5188 }
5189 }
5190
5191 private boolean startFling(long time, float vx, float vy) {
5192 if (LOCAL_DEBUG) {
5193 Log.d(LOCAL_TAG, "Considering fling: vx=" + vx + ", vy=" + vy
5194 + ", min=" + mConfigMinFlingVelocity);
5195 }
5196
5197 // Flings must be oriented in the same direction as the preceding movements.
5198 switch (mPendingKeyCode) {
5199 case KeyEvent.KEYCODE_DPAD_LEFT:
5200 if (-vx >= mConfigMinFlingVelocity
5201 && Math.abs(vy) < mConfigMinFlingVelocity) {
5202 mFlingVelocity = -vx;
5203 break;
5204 }
5205 return false;
5206
5207 case KeyEvent.KEYCODE_DPAD_RIGHT:
5208 if (vx >= mConfigMinFlingVelocity
5209 && Math.abs(vy) < mConfigMinFlingVelocity) {
5210 mFlingVelocity = vx;
5211 break;
5212 }
5213 return false;
5214
5215 case KeyEvent.KEYCODE_DPAD_UP:
5216 if (-vy >= mConfigMinFlingVelocity
5217 && Math.abs(vx) < mConfigMinFlingVelocity) {
5218 mFlingVelocity = -vy;
5219 break;
5220 }
5221 return false;
5222
5223 case KeyEvent.KEYCODE_DPAD_DOWN:
5224 if (vy >= mConfigMinFlingVelocity
5225 && Math.abs(vx) < mConfigMinFlingVelocity) {
5226 mFlingVelocity = vy;
5227 break;
5228 }
5229 return false;
5230 }
5231
5232 // Post the first fling event.
5233 mFlinging = postFling(time);
5234 return mFlinging;
5235 }
5236
5237 private boolean postFling(long time) {
5238 // The idea here is to estimate the time when the pointer would have
5239 // traveled one tick distance unit given the current fling velocity.
5240 // This effect creates continuity of motion.
5241 if (mFlingVelocity >= mConfigMinFlingVelocity) {
5242 long delay = (long)(mConfigTickDistance / mFlingVelocity * 1000);
5243 postAtTime(mFlingRunnable, time + delay);
5244 if (LOCAL_DEBUG) {
5245 Log.d(LOCAL_TAG, "Posted fling: velocity="
5246 + mFlingVelocity + ", delay=" + delay
5247 + ", keyCode=" + mPendingKeyCode);
5248 }
5249 return true;
5250 }
5251 return false;
5252 }
5253
5254 private void cancelFling() {
5255 if (mFlinging) {
5256 removeCallbacks(mFlingRunnable);
5257 mFlinging = false;
5258 }
5259 }
5260
5261 private final Runnable mFlingRunnable = new Runnable() {
5262 @Override
5263 public void run() {
5264 final long time = SystemClock.uptimeMillis();
5265 sendKeyDownOrRepeat(time, mPendingKeyCode, mPendingKeyMetaState);
5266 mFlingVelocity *= FLING_TICK_DECAY;
5267 if (!postFling(time)) {
5268 mFlinging = false;
5269 finishKeys(time);
5270 }
5271 }
5272 };
Jeff Browncb1404e2011-01-15 18:14:15 -08005273 }
5274
Michael Wright899d7052014-04-23 17:23:39 -07005275 final class SyntheticKeyboardHandler {
5276 public void process(KeyEvent event) {
5277 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) != 0) {
5278 return;
5279 }
5280
5281 final KeyCharacterMap kcm = event.getKeyCharacterMap();
5282 final int keyCode = event.getKeyCode();
5283 final int metaState = event.getMetaState();
5284
5285 // Check for fallback actions specified by the key character map.
5286 KeyCharacterMap.FallbackAction fallbackAction =
5287 kcm.getFallbackAction(keyCode, metaState);
5288 if (fallbackAction != null) {
5289 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
5290 KeyEvent fallbackEvent = KeyEvent.obtain(
5291 event.getDownTime(), event.getEventTime(),
5292 event.getAction(), fallbackAction.keyCode,
5293 event.getRepeatCount(), fallbackAction.metaState,
5294 event.getDeviceId(), event.getScanCode(),
5295 flags, event.getSource(), null);
5296 fallbackAction.recycle();
5297 enqueueInputEvent(fallbackEvent);
5298 }
5299 }
5300 }
5301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005302 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005303 * Returns true if the key is used for keyboard navigation.
5304 * @param keyEvent The key event.
5305 * @return True if the key is used for keyboard navigation.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005306 */
Jeff Brown4e6319b2010-12-13 10:36:51 -08005307 private static boolean isNavigationKey(KeyEvent keyEvent) {
5308 switch (keyEvent.getKeyCode()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005309 case KeyEvent.KEYCODE_DPAD_LEFT:
5310 case KeyEvent.KEYCODE_DPAD_RIGHT:
5311 case KeyEvent.KEYCODE_DPAD_UP:
5312 case KeyEvent.KEYCODE_DPAD_DOWN:
Jeff Brown4e6319b2010-12-13 10:36:51 -08005313 case KeyEvent.KEYCODE_DPAD_CENTER:
5314 case KeyEvent.KEYCODE_PAGE_UP:
5315 case KeyEvent.KEYCODE_PAGE_DOWN:
5316 case KeyEvent.KEYCODE_MOVE_HOME:
5317 case KeyEvent.KEYCODE_MOVE_END:
5318 case KeyEvent.KEYCODE_TAB:
5319 case KeyEvent.KEYCODE_SPACE:
5320 case KeyEvent.KEYCODE_ENTER:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 return true;
5322 }
5323 return false;
5324 }
5325
5326 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005327 * Returns true if the key is used for typing.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005328 * @param keyEvent The key event.
Jeff Brown4e6319b2010-12-13 10:36:51 -08005329 * @return True if the key is used for typing.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005330 */
Jeff Brown4e6319b2010-12-13 10:36:51 -08005331 private static boolean isTypingKey(KeyEvent keyEvent) {
5332 return keyEvent.getUnicodeChar() > 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005333 }
5334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005336 * See if the key event means we should leave touch mode (and leave touch mode if so).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005337 * @param event The key event.
5338 * @return Whether this key event should be consumed (meaning the act of
5339 * leaving touch mode alone is considered the event).
5340 */
5341 private boolean checkForLeavingTouchModeAndConsume(KeyEvent event) {
Jeff Brown4e6319b2010-12-13 10:36:51 -08005342 // Only relevant in touch mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005343 if (!mAttachInfo.mInTouchMode) {
5344 return false;
5345 }
5346
Jeff Brown4e6319b2010-12-13 10:36:51 -08005347 // Only consider leaving touch mode on DOWN or MULTIPLE actions, never on UP.
5348 final int action = event.getAction();
5349 if (action != KeyEvent.ACTION_DOWN && action != KeyEvent.ACTION_MULTIPLE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005350 return false;
5351 }
5352
Jeff Brown4e6319b2010-12-13 10:36:51 -08005353 // Don't leave touch mode if the IME told us not to.
5354 if ((event.getFlags() & KeyEvent.FLAG_KEEP_TOUCH_MODE) != 0) {
5355 return false;
5356 }
5357
5358 // If the key can be used for keyboard navigation then leave touch mode
5359 // and select a focused view if needed (in ensureTouchMode).
5360 // When a new focused view is selected, we consume the navigation key because
5361 // navigation doesn't make much sense unless a view already has focus so
5362 // the key's purpose is to set focus.
5363 if (isNavigationKey(event)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005364 return ensureTouchMode(false);
5365 }
Jeff Brown4e6319b2010-12-13 10:36:51 -08005366
5367 // If the key can be used for typing then leave touch mode
5368 // and select a focused view if needed (in ensureTouchMode).
5369 // Always allow the view to process the typing key.
5370 if (isTypingKey(event)) {
5371 ensureTouchMode(false);
5372 return false;
5373 }
5374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 return false;
5376 }
5377
Christopher Tatea53146c2010-09-07 11:57:52 -07005378 /* drag/drop */
Christopher Tate407b4e92010-11-30 17:14:08 -08005379 void setLocalDragState(Object obj) {
5380 mLocalDragState = obj;
5381 }
5382
Christopher Tatea53146c2010-09-07 11:57:52 -07005383 private void handleDragEvent(DragEvent event) {
5384 // From the root, only drag start/end/location are dispatched. entered/exited
5385 // are determined and dispatched by the viewgroup hierarchy, who then report
5386 // that back here for ultimate reporting back to the framework.
5387 if (mView != null && mAdded) {
5388 final int what = event.mAction;
5389
5390 if (what == DragEvent.ACTION_DRAG_EXITED) {
5391 // A direct EXITED event means that the window manager knows we've just crossed
5392 // a window boundary, so the current drag target within this one must have
5393 // just been exited. Send it the usual notifications and then we're done
5394 // for now.
Chris Tate9d1ab882010-11-02 15:55:39 -07005395 mView.dispatchDragEvent(event);
Christopher Tatea53146c2010-09-07 11:57:52 -07005396 } else {
5397 // Cache the drag description when the operation starts, then fill it in
5398 // on subsequent calls as a convenience
5399 if (what == DragEvent.ACTION_DRAG_STARTED) {
Chris Tate9d1ab882010-11-02 15:55:39 -07005400 mCurrentDragView = null; // Start the current-recipient tracking
Christopher Tatea53146c2010-09-07 11:57:52 -07005401 mDragDescription = event.mClipDescription;
5402 } else {
5403 event.mClipDescription = mDragDescription;
5404 }
5405
5406 // For events with a [screen] location, translate into window coordinates
5407 if ((what == DragEvent.ACTION_DRAG_LOCATION) || (what == DragEvent.ACTION_DROP)) {
5408 mDragPoint.set(event.mX, event.mY);
5409 if (mTranslator != null) {
5410 mTranslator.translatePointInScreenToAppWindow(mDragPoint);
5411 }
5412
5413 if (mCurScrollY != 0) {
5414 mDragPoint.offset(0, mCurScrollY);
5415 }
5416
5417 event.mX = mDragPoint.x;
5418 event.mY = mDragPoint.y;
5419 }
5420
5421 // Remember who the current drag target is pre-dispatch
5422 final View prevDragView = mCurrentDragView;
5423
5424 // Now dispatch the drag/drop event
Chris Tated4533f12010-10-19 15:15:08 -07005425 boolean result = mView.dispatchDragEvent(event);
Christopher Tatea53146c2010-09-07 11:57:52 -07005426
5427 // If we changed apparent drag target, tell the OS about it
5428 if (prevDragView != mCurrentDragView) {
5429 try {
5430 if (prevDragView != null) {
Jeff Brown98365d72012-08-19 20:30:52 -07005431 mWindowSession.dragRecipientExited(mWindow);
Christopher Tatea53146c2010-09-07 11:57:52 -07005432 }
5433 if (mCurrentDragView != null) {
Jeff Brown98365d72012-08-19 20:30:52 -07005434 mWindowSession.dragRecipientEntered(mWindow);
Christopher Tatea53146c2010-09-07 11:57:52 -07005435 }
5436 } catch (RemoteException e) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005437 Slog.e(mTag, "Unable to note drag target change");
Christopher Tatea53146c2010-09-07 11:57:52 -07005438 }
Christopher Tatea53146c2010-09-07 11:57:52 -07005439 }
Chris Tated4533f12010-10-19 15:15:08 -07005440
Christopher Tate407b4e92010-11-30 17:14:08 -08005441 // Report the drop result when we're done
Chris Tated4533f12010-10-19 15:15:08 -07005442 if (what == DragEvent.ACTION_DROP) {
Christopher Tate1fc014f2011-01-19 12:56:26 -08005443 mDragDescription = null;
Chris Tated4533f12010-10-19 15:15:08 -07005444 try {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005445 Log.i(mTag, "Reporting drop result: " + result);
Jeff Brown98365d72012-08-19 20:30:52 -07005446 mWindowSession.reportDropResult(mWindow, result);
Chris Tated4533f12010-10-19 15:15:08 -07005447 } catch (RemoteException e) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005448 Log.e(mTag, "Unable to report drop result");
Chris Tated4533f12010-10-19 15:15:08 -07005449 }
5450 }
Christopher Tate407b4e92010-11-30 17:14:08 -08005451
Vladislav Kaznacheev82063912015-11-20 14:20:13 -08005452 // When the drag operation ends, reset drag-related state
Christopher Tate407b4e92010-11-30 17:14:08 -08005453 if (what == DragEvent.ACTION_DRAG_ENDED) {
5454 setLocalDragState(null);
Vladislav Kaznacheev82063912015-11-20 14:20:13 -08005455 mAttachInfo.mDragToken = null;
Vladislav Kaznacheev4f639742015-11-18 13:21:35 -08005456 if (mAttachInfo.mDragSurface != null) {
5457 mAttachInfo.mDragSurface.release();
5458 mAttachInfo.mDragSurface = null;
5459 }
Christopher Tate407b4e92010-11-30 17:14:08 -08005460 }
Christopher Tatea53146c2010-09-07 11:57:52 -07005461 }
5462 }
5463 event.recycle();
5464 }
5465
Dianne Hackborn9a230e02011-10-06 11:51:27 -07005466 public void handleDispatchSystemUiVisibilityChanged(SystemUiVisibilityInfo args) {
5467 if (mSeq != args.seq) {
5468 // The sequence has changed, so we need to update our value and make
5469 // sure to do a traversal afterward so the window manager is given our
5470 // most recent data.
5471 mSeq = args.seq;
5472 mAttachInfo.mForceReportNewAttributes = true;
Igor Murashkina86ab6402013-08-30 12:58:36 -07005473 scheduleTraversals();
Joe Onorato14782f72011-01-25 19:53:17 -08005474 }
Dianne Hackborn9a230e02011-10-06 11:51:27 -07005475 if (mView == null) return;
5476 if (args.localChanges != 0) {
Dianne Hackborn9a230e02011-10-06 11:51:27 -07005477 mView.updateLocalSystemUiVisibility(args.localValue, args.localChanges);
Dianne Hackborn9a230e02011-10-06 11:51:27 -07005478 }
Chris Craikd36a81f2014-07-17 10:16:51 -07005479
5480 int visibility = args.globalVisibility&View.SYSTEM_UI_CLEARABLE_FLAGS;
5481 if (visibility != mAttachInfo.mGlobalSystemUiVisibility) {
5482 mAttachInfo.mGlobalSystemUiVisibility = visibility;
5483 mView.dispatchSystemUiVisibilityChanged(visibility);
Dianne Hackborncf675782012-05-10 15:07:24 -07005484 }
Joe Onorato664644d2011-01-23 17:53:23 -08005485 }
5486
Craig Mautner9c795042014-10-28 19:59:59 -07005487 public void handleDispatchWindowShown() {
5488 mAttachInfo.mTreeObserver.dispatchOnWindowShown();
5489 }
5490
Clara Bayarri75e09792015-07-29 16:20:40 +01005491 public void handleRequestKeyboardShortcuts(IResultReceiver receiver) {
5492 Bundle data = new Bundle();
5493 ArrayList<KeyboardShortcutGroup> list = new ArrayList<>();
5494 if (mView != null) {
5495 mView.requestKeyboardShortcuts(list);
5496 }
5497 data.putParcelableArrayList(WindowManager.PARCEL_KEY_SHORTCUTS_ARRAY, list);
5498 try {
5499 receiver.send(0, data);
5500 } catch (RemoteException e) {
5501 }
5502 }
5503
Christopher Tate2c095f32010-10-04 14:13:40 -07005504 public void getLastTouchPoint(Point outLocation) {
5505 outLocation.x = (int) mLastTouchPoint.x;
5506 outLocation.y = (int) mLastTouchPoint.y;
5507 }
5508
Vladislav Kaznacheevba761122016-01-22 12:09:45 -08005509 public int getLastTouchSource() {
5510 return mLastTouchSource;
5511 }
5512
Chris Tate9d1ab882010-11-02 15:55:39 -07005513 public void setDragFocus(View newDragTarget) {
Christopher Tatea53146c2010-09-07 11:57:52 -07005514 if (mCurrentDragView != newDragTarget) {
Chris Tate048691c2010-10-12 17:39:18 -07005515 mCurrentDragView = newDragTarget;
Christopher Tatea53146c2010-09-07 11:57:52 -07005516 }
Christopher Tatea53146c2010-09-07 11:57:52 -07005517 }
5518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005519 private AudioManager getAudioManager() {
5520 if (mView == null) {
5521 throw new IllegalStateException("getAudioManager called when there is no mView");
5522 }
5523 if (mAudioManager == null) {
5524 mAudioManager = (AudioManager) mView.getContext().getSystemService(Context.AUDIO_SERVICE);
5525 }
5526 return mAudioManager;
5527 }
5528
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07005529 public AccessibilityInteractionController getAccessibilityInteractionController() {
5530 if (mView == null) {
5531 throw new IllegalStateException("getAccessibilityInteractionController"
5532 + " called when there is no mView");
5533 }
Gilles Debunne5ac84422011-10-19 09:35:58 -07005534 if (mAccessibilityInteractionController == null) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07005535 mAccessibilityInteractionController = new AccessibilityInteractionController(this);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07005536 }
Gilles Debunne5ac84422011-10-19 09:35:58 -07005537 return mAccessibilityInteractionController;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07005538 }
5539
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07005540 private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
5541 boolean insetsPending) throws RemoteException {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07005542
5543 float appScale = mAttachInfo.mApplicationScale;
Mitsuru Oshima3d914922009-05-13 22:29:15 -07005544 boolean restore = false;
Mitsuru Oshima64f59342009-06-21 00:03:11 -07005545 if (params != null && mTranslator != null) {
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005546 restore = true;
5547 params.backup();
Mitsuru Oshima64f59342009-06-21 00:03:11 -07005548 mTranslator.translateWindowLayout(params);
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07005549 }
Mitsuru Oshima64f59342009-06-21 00:03:11 -07005550 if (params != null) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005551 if (DBG) Log.d(mTag, "WindowLayout in layoutWindow:" + params);
Mitsuru Oshima3d914922009-05-13 22:29:15 -07005552 }
Dianne Hackborn694f79b2010-03-17 19:44:59 -07005553 mPendingConfiguration.seq = 0;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005554 //Log.d(mTag, ">>>>>> CALLING relayout");
Dianne Hackborn180c4842011-09-13 12:39:25 -07005555 if (params != null && mOrigWindowType != params.type) {
5556 // For compatibility with old apps, don't crash here.
Michael Wright5bd69e62015-05-14 14:48:08 +01005557 if (mTargetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005558 Slog.w(mTag, "Window type can not be changed after "
Dianne Hackborn180c4842011-09-13 12:39:25 -07005559 + "the window is added; ignoring change of " + mView);
5560 params.type = mOrigWindowType;
5561 }
5562 }
Jeff Brown98365d72012-08-19 20:30:52 -07005563 int relayoutResult = mWindowSession.relayout(
Dianne Hackborn9a230e02011-10-06 11:51:27 -07005564 mWindow, mSeq, params,
Dianne Hackborn189ee182010-12-02 21:48:53 -08005565 (int) (mView.getMeasuredWidth() * appScale + 0.5f),
5566 (int) (mView.getMeasuredHeight() * appScale + 0.5f),
Jeff Brown98365d72012-08-19 20:30:52 -07005567 viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
Dianne Hackbornc4aad012013-02-22 15:05:25 -08005568 mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
Jorim Jaggi2e95a482016-01-14 17:36:55 -08005569 mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingConfiguration,
5570 mSurface);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005571 //Log.d(mTag, "<<<<<< BACK FROM relayout");
Mitsuru Oshima3d914922009-05-13 22:29:15 -07005572 if (restore) {
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005573 params.restore();
Mitsuru Oshima3d914922009-05-13 22:29:15 -07005574 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07005575
Mitsuru Oshima64f59342009-06-21 00:03:11 -07005576 if (mTranslator != null) {
5577 mTranslator.translateRectInScreenToAppWinFrame(mWinFrame);
Dianne Hackbornc4aad012013-02-22 15:05:25 -08005578 mTranslator.translateRectInScreenToAppWindow(mPendingOverscanInsets);
Mitsuru Oshima64f59342009-06-21 00:03:11 -07005579 mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets);
5580 mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets);
Adrian Roosfa104232014-06-20 16:10:14 -07005581 mTranslator.translateRectInScreenToAppWindow(mPendingStableInsets);
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07005582 }
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07005583 return relayoutResult;
5584 }
Romain Guy8506ab42009-06-11 17:35:47 -07005585
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07005586 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005587 * {@inheritDoc}
5588 */
Igor Murashkina86ab6402013-08-30 12:58:36 -07005589 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005590 public void playSoundEffect(int effectId) {
5591 checkThread();
5592
Jean-Michel Trivi13b18fd2010-05-05 09:18:15 -07005593 try {
5594 final AudioManager audioManager = getAudioManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005595
Jean-Michel Trivi13b18fd2010-05-05 09:18:15 -07005596 switch (effectId) {
5597 case SoundEffectConstants.CLICK:
5598 audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
5599 return;
5600 case SoundEffectConstants.NAVIGATION_DOWN:
5601 audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN);
5602 return;
5603 case SoundEffectConstants.NAVIGATION_LEFT:
5604 audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT);
5605 return;
5606 case SoundEffectConstants.NAVIGATION_RIGHT:
5607 audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT);
5608 return;
5609 case SoundEffectConstants.NAVIGATION_UP:
5610 audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP);
5611 return;
5612 default:
5613 throw new IllegalArgumentException("unknown effect id " + effectId +
5614 " not defined in " + SoundEffectConstants.class.getCanonicalName());
5615 }
5616 } catch (IllegalStateException e) {
5617 // Exception thrown by getAudioManager() when mView is null
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005618 Log.e(mTag, "FATAL EXCEPTION when attempting to play sound effect: " + e);
Jean-Michel Trivi13b18fd2010-05-05 09:18:15 -07005619 e.printStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005620 }
5621 }
5622
5623 /**
5624 * {@inheritDoc}
5625 */
Igor Murashkina86ab6402013-08-30 12:58:36 -07005626 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005627 public boolean performHapticFeedback(int effectId, boolean always) {
5628 try {
Jeff Brown98365d72012-08-19 20:30:52 -07005629 return mWindowSession.performHapticFeedback(mWindow, effectId, always);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005630 } catch (RemoteException e) {
5631 return false;
5632 }
5633 }
5634
5635 /**
5636 * {@inheritDoc}
5637 */
Igor Murashkina86ab6402013-08-30 12:58:36 -07005638 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005639 public View focusSearch(View focused, int direction) {
5640 checkThread();
5641 if (!(mView instanceof ViewGroup)) {
5642 return null;
5643 }
5644 return FocusFinder.getInstance().findNextFocus((ViewGroup) mView, focused, direction);
5645 }
5646
5647 public void debug() {
5648 mView.debug();
5649 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07005650
Jeff Brown5182c782013-10-15 20:31:52 -07005651 public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
5652 String innerPrefix = prefix + " ";
5653 writer.print(prefix); writer.println("ViewRoot:");
5654 writer.print(innerPrefix); writer.print("mAdded="); writer.print(mAdded);
5655 writer.print(" mRemoved="); writer.println(mRemoved);
5656 writer.print(innerPrefix); writer.print("mConsumeBatchedInputScheduled=");
5657 writer.println(mConsumeBatchedInputScheduled);
Michael Wright9d744c72014-02-18 21:27:42 -08005658 writer.print(innerPrefix); writer.print("mConsumeBatchedInputImmediatelyScheduled=");
5659 writer.println(mConsumeBatchedInputImmediatelyScheduled);
Jeff Brown5182c782013-10-15 20:31:52 -07005660 writer.print(innerPrefix); writer.print("mPendingInputEventCount=");
5661 writer.println(mPendingInputEventCount);
5662 writer.print(innerPrefix); writer.print("mProcessInputEventsScheduled=");
5663 writer.println(mProcessInputEventsScheduled);
5664 writer.print(innerPrefix); writer.print("mTraversalScheduled=");
5665 writer.print(mTraversalScheduled);
Daniel Koulomzin087ae472015-12-16 17:52:25 -05005666 writer.print(innerPrefix); writer.print("mIsAmbientMode=");
5667 writer.print(mIsAmbientMode);
Jeff Brown5182c782013-10-15 20:31:52 -07005668 if (mTraversalScheduled) {
5669 writer.print(" (barrier="); writer.print(mTraversalBarrier); writer.println(")");
5670 } else {
5671 writer.println();
5672 }
5673 mFirstInputStage.dump(innerPrefix, writer);
5674
5675 mChoreographer.dump(prefix, writer);
5676
5677 writer.print(prefix); writer.println("View Hierarchy:");
5678 dumpViewHierarchy(innerPrefix, writer, mView);
5679 }
5680
5681 private void dumpViewHierarchy(String prefix, PrintWriter writer, View view) {
5682 writer.print(prefix);
5683 if (view == null) {
5684 writer.println("null");
5685 return;
5686 }
5687 writer.println(view.toString());
5688 if (!(view instanceof ViewGroup)) {
5689 return;
5690 }
5691 ViewGroup grp = (ViewGroup)view;
5692 final int N = grp.getChildCount();
5693 if (N <= 0) {
5694 return;
5695 }
5696 prefix = prefix + " ";
5697 for (int i=0; i<N; i++) {
5698 dumpViewHierarchy(prefix, writer, grp.getChildAt(i));
5699 }
5700 }
5701
Romain Guy211370f2012-02-01 16:10:55 -08005702 public void dumpGfxInfo(int[] info) {
Romain Guy54ab3472012-06-14 12:52:53 -07005703 info[0] = info[1] = 0;
Romain Guy65b345f2011-07-27 18:51:50 -07005704 if (mView != null) {
5705 getGfxInfo(mView, info);
Romain Guy65b345f2011-07-27 18:51:50 -07005706 }
5707 }
5708
Romain Guya998dff2012-03-23 18:58:36 -07005709 private static void getGfxInfo(View view, int[] info) {
Chris Craik64a12e12014-03-28 18:12:12 -07005710 RenderNode renderNode = view.mRenderNode;
Romain Guy65b345f2011-07-27 18:51:50 -07005711 info[0]++;
Chris Craik64a12e12014-03-28 18:12:12 -07005712 if (renderNode != null) {
John Reckfe5e7b72014-05-23 17:42:28 -07005713 info[1] += renderNode.getDebugSize();
Romain Guy65b345f2011-07-27 18:51:50 -07005714 }
5715
5716 if (view instanceof ViewGroup) {
5717 ViewGroup group = (ViewGroup) view;
5718
5719 int count = group.getChildCount();
5720 for (int i = 0; i < count; i++) {
5721 getGfxInfo(group.getChildAt(i), info);
5722 }
5723 }
5724 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005725
Craig Mautner8f303ad2013-06-14 11:32:22 -07005726 /**
5727 * @param immediate True, do now if not in traversal. False, put on queue and do later.
5728 * @return True, request has been queued. False, request has been completed.
5729 */
5730 boolean die(boolean immediate) {
Craig Mautnerdf2390a2012-08-29 20:59:22 -07005731 // Make sure we do execute immediately if we are in the middle of a traversal or the damage
5732 // done by dispatchDetachedFromWindow will cause havoc on return.
5733 if (immediate && !mIsInTraversal) {
Dianne Hackborn94d69142009-09-28 22:14:42 -07005734 doDie();
Craig Mautner8f303ad2013-06-14 11:32:22 -07005735 return false;
Dianne Hackborn94d69142009-09-28 22:14:42 -07005736 }
Craig Mautner8f303ad2013-06-14 11:32:22 -07005737
5738 if (!mIsDrawing) {
5739 destroyHardwareRenderer();
5740 } else {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005741 Log.e(mTag, "Attempting to destroy the window while drawing!\n" +
Craig Mautner8f303ad2013-06-14 11:32:22 -07005742 " window=" + this + ", title=" + mWindowAttributes.getTitle());
5743 }
5744 mHandler.sendEmptyMessage(MSG_DIE);
5745 return true;
Dianne Hackborn94d69142009-09-28 22:14:42 -07005746 }
5747
5748 void doDie() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005749 checkThread();
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005750 if (LOCAL_LOGV) Log.v(mTag, "DIE in " + this + " of " + mSurface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005751 synchronized (this) {
Craig Mautner8f303ad2013-06-14 11:32:22 -07005752 if (mRemoved) {
5753 return;
5754 }
5755 mRemoved = true;
Romain Guy16260e72011-09-01 14:26:11 -07005756 if (mAdded) {
Romain Guy16260e72011-09-01 14:26:11 -07005757 dispatchDetachedFromWindow();
5758 }
5759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 if (mAdded && !mFirst) {
Romain Guy29d89972010-09-22 16:10:57 -07005761 destroyHardwareRenderer();
5762
Romain Guyedbca122012-04-04 18:25:53 -07005763 if (mView != null) {
5764 int viewVisibility = mView.getVisibility();
5765 boolean viewVisibilityChanged = mViewVisibility != viewVisibility;
5766 if (mWindowAttributesChanged || viewVisibilityChanged) {
5767 // If layout params have been changed, first give them
5768 // to the window manager to make sure it has the correct
5769 // animation info.
5770 try {
5771 if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
Jeff Brown98365d72012-08-19 20:30:52 -07005772 & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
5773 mWindowSession.finishDrawing(mWindow);
Romain Guyedbca122012-04-04 18:25:53 -07005774 }
5775 } catch (RemoteException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005777 }
Craig Mautner8f303ad2013-06-14 11:32:22 -07005778
Romain Guyedbca122012-04-04 18:25:53 -07005779 mSurface.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005780 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005781 }
Romain Guyedbca122012-04-04 18:25:53 -07005782
5783 mAdded = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005784 }
Craig Mautner05eb7302013-06-03 17:24:21 -07005785 WindowManagerGlobal.getInstance().doRemoveView(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005786 }
5787
Dianne Hackborn5fd21692011-06-07 14:09:47 -07005788 public void requestUpdateConfiguration(Configuration config) {
Jeff Browna175a5b2012-02-15 19:18:31 -08005789 Message msg = mHandler.obtainMessage(MSG_UPDATE_CONFIGURATION, config);
5790 mHandler.sendMessage(msg);
Dianne Hackborn5fd21692011-06-07 14:09:47 -07005791 }
5792
Dianne Hackborna53de062012-05-08 18:53:51 -07005793 public void loadSystemProperties() {
Romain Guy5bb3c732012-11-29 17:52:58 -08005794 mHandler.post(new Runnable() {
5795 @Override
5796 public void run() {
5797 // Profiling
5798 mProfileRendering = SystemProperties.getBoolean(PROPERTY_PROFILE_RENDERING, false);
5799 profileRendering(mAttachInfo.mHasWindowFocus);
5800
5801 // Hardware rendering
5802 if (mAttachInfo.mHardwareRenderer != null) {
John Reckcec24ae2013-11-05 13:27:50 -08005803 if (mAttachInfo.mHardwareRenderer.loadSystemProperties()) {
Romain Guy5bb3c732012-11-29 17:52:58 -08005804 invalidate();
5805 }
5806 }
5807
5808 // Layout debugging
5809 boolean layout = SystemProperties.getBoolean(View.DEBUG_LAYOUT_PROPERTY, false);
5810 if (layout != mAttachInfo.mDebugLayout) {
5811 mAttachInfo.mDebugLayout = layout;
5812 if (!mHandler.hasMessages(MSG_INVALIDATE_WORLD)) {
5813 mHandler.sendEmptyMessageDelayed(MSG_INVALIDATE_WORLD, 200);
5814 }
5815 }
Dianne Hackborna53de062012-05-08 18:53:51 -07005816 }
Romain Guy5bb3c732012-11-29 17:52:58 -08005817 });
Dianne Hackborna53de062012-05-08 18:53:51 -07005818 }
5819
Romain Guy29d89972010-09-22 16:10:57 -07005820 private void destroyHardwareRenderer() {
John Reck51aaf902015-12-02 15:08:07 -08005821 ThreadedRenderer hardwareRenderer = mAttachInfo.mHardwareRenderer;
Romain Guya998dff2012-03-23 18:58:36 -07005822
5823 if (hardwareRenderer != null) {
5824 if (mView != null) {
5825 hardwareRenderer.destroyHardwareResources(mView);
5826 }
John Reckf47a5942014-06-30 16:20:04 -07005827 hardwareRenderer.destroy();
Romain Guya998dff2012-03-23 18:58:36 -07005828 hardwareRenderer.setRequested(false);
5829
Chris Craikd36a81f2014-07-17 10:16:51 -07005830 mAttachInfo.mHardwareRenderer = null;
5831 mAttachInfo.mHardwareAccelerated = false;
Romain Guy29d89972010-09-22 16:10:57 -07005832 }
5833 }
5834
Jeff Browna175a5b2012-02-15 19:18:31 -08005835 public void dispatchFinishInputConnection(InputConnection connection) {
5836 Message msg = mHandler.obtainMessage(MSG_FINISH_INPUT_CONNECTION, connection);
5837 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005838 }
Mitsuru Oshima3d914922009-05-13 22:29:15 -07005839
Dianne Hackbornc4aad012013-02-22 15:05:25 -08005840 public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
Filip Gruszczynski2217f612015-05-26 11:32:08 -07005841 Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
Jorim Jaggia4a58ef2016-01-27 02:10:08 -08005842 Configuration newConfig, Rect backDropFrame, boolean forceLayout) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005843 if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString()
Svetoslav Ganov758143e2012-08-06 16:40:27 -07005844 + " contentInsets=" + contentInsets.toShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005845 + " visibleInsets=" + visibleInsets.toShortString()
Chong Zhangd153c4f2015-11-06 20:26:40 -08005846 + " reportDraw=" + reportDraw
5847 + " backDropFrame=" + backDropFrame);
Chong Zhangdcee1de2015-10-06 10:26:00 -07005848
5849 // Tell all listeners that we are resizing the window so that the chrome can get
5850 // updated as fast as possible on a separate thread,
5851 if (mDragResizing) {
Jorim Jaggi9511b0f2016-01-29 19:12:44 -08005852 boolean fullscreen = frame.equals(backDropFrame);
Chong Zhangdcee1de2015-10-06 10:26:00 -07005853 synchronized (mWindowCallbacks) {
5854 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
Jorim Jaggi9511b0f2016-01-29 19:12:44 -08005855 mWindowCallbacks.get(i).onWindowSizeIsChanging(backDropFrame, fullscreen,
5856 visibleInsets, stableInsets);
Chong Zhangdcee1de2015-10-06 10:26:00 -07005857 }
5858 }
5859 }
5860
Svetoslav Ganov758143e2012-08-06 16:40:27 -07005861 Message msg = mHandler.obtainMessage(reportDraw ? MSG_RESIZED_REPORT : MSG_RESIZED);
Mitsuru Oshima64f59342009-06-21 00:03:11 -07005862 if (mTranslator != null) {
Svetoslav Ganov758143e2012-08-06 16:40:27 -07005863 mTranslator.translateRectInScreenToAppWindow(frame);
Dianne Hackbornc4aad012013-02-22 15:05:25 -08005864 mTranslator.translateRectInScreenToAppWindow(overscanInsets);
Dianne Hackborn3556c9a2012-05-04 16:31:25 -07005865 mTranslator.translateRectInScreenToAppWindow(contentInsets);
Mitsuru Oshima64f59342009-06-21 00:03:11 -07005866 mTranslator.translateRectInScreenToAppWindow(visibleInsets);
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07005867 }
Svetoslav Ganov758143e2012-08-06 16:40:27 -07005868 SomeArgs args = SomeArgs.obtain();
5869 final boolean sameProcessCall = (Binder.getCallingPid() == android.os.Process.myPid());
5870 args.arg1 = sameProcessCall ? new Rect(frame) : frame;
5871 args.arg2 = sameProcessCall ? new Rect(contentInsets) : contentInsets;
5872 args.arg3 = sameProcessCall ? new Rect(visibleInsets) : visibleInsets;
5873 args.arg4 = sameProcessCall && newConfig != null ? new Configuration(newConfig) : newConfig;
Dianne Hackbornc4aad012013-02-22 15:05:25 -08005874 args.arg5 = sameProcessCall ? new Rect(overscanInsets) : overscanInsets;
Adrian Roosfa104232014-06-20 16:10:14 -07005875 args.arg6 = sameProcessCall ? new Rect(stableInsets) : stableInsets;
Filip Gruszczynski2217f612015-05-26 11:32:08 -07005876 args.arg7 = sameProcessCall ? new Rect(outsets) : outsets;
Jorim Jaggia7262a82015-11-03 15:15:40 +01005877 args.arg8 = sameProcessCall ? new Rect(backDropFrame) : backDropFrame;
Jorim Jaggia4a58ef2016-01-27 02:10:08 -08005878 args.argi1 = forceLayout ? 1 : 0;
Svetoslav Ganov758143e2012-08-06 16:40:27 -07005879 msg.obj = args;
Jeff Browna175a5b2012-02-15 19:18:31 -08005880 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005881 }
Chet Haase1f4786b2011-11-02 10:51:52 -07005882
Craig Mautner5702d4d2012-06-30 14:10:16 -07005883 public void dispatchMoved(int newX, int newY) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005884 if (DEBUG_LAYOUT) Log.v(mTag, "Window moved " + this + ": newX=" + newX + " newY=" + newY);
Craig Mautner5702d4d2012-06-30 14:10:16 -07005885 if (mTranslator != null) {
5886 PointF point = new PointF(newX, newY);
5887 mTranslator.translatePointInScreenToAppWindow(point);
5888 newX = (int) (point.x + 0.5);
5889 newY = (int) (point.y + 0.5);
5890 }
5891 Message msg = mHandler.obtainMessage(MSG_WINDOW_MOVED, newX, newY);
5892 mHandler.sendMessage(msg);
5893 }
5894
Jeff Brown4952dfd2011-11-30 19:23:22 -08005895 /**
5896 * Represents a pending input event that is waiting in a queue.
5897 *
5898 * Input events are processed in serial order by the timestamp specified by
Romain Guy211370f2012-02-01 16:10:55 -08005899 * {@link InputEvent#getEventTimeNano()}. In general, the input dispatcher delivers
Jeff Brown4952dfd2011-11-30 19:23:22 -08005900 * one input event to the application at a time and waits for the application
5901 * to finish handling it before delivering the next one.
5902 *
5903 * However, because the application or IME can synthesize and inject multiple
5904 * key events at a time without going through the input dispatcher, we end up
5905 * needing a queue on the application's side.
5906 */
5907 private static final class QueuedInputEvent {
Jeff Brownf9e989d2013-04-04 23:04:03 -07005908 public static final int FLAG_DELIVER_POST_IME = 1 << 0;
5909 public static final int FLAG_DEFERRED = 1 << 1;
5910 public static final int FLAG_FINISHED = 1 << 2;
5911 public static final int FLAG_FINISHED_HANDLED = 1 << 3;
5912 public static final int FLAG_RESYNTHESIZED = 1 << 4;
Michael Wright899d7052014-04-23 17:23:39 -07005913 public static final int FLAG_UNHANDLED = 1 << 5;
Jeff Brown4952dfd2011-11-30 19:23:22 -08005914
5915 public QueuedInputEvent mNext;
5916
5917 public InputEvent mEvent;
Jeff Brown32cbc38552011-12-01 14:01:49 -08005918 public InputEventReceiver mReceiver;
Jeff Brown4952dfd2011-11-30 19:23:22 -08005919 public int mFlags;
Jeff Brownf9e989d2013-04-04 23:04:03 -07005920
5921 public boolean shouldSkipIme() {
5922 if ((mFlags & FLAG_DELIVER_POST_IME) != 0) {
5923 return true;
5924 }
5925 return mEvent instanceof MotionEvent
5926 && mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER);
5927 }
Michael Wright899d7052014-04-23 17:23:39 -07005928
5929 public boolean shouldSendToSynthesizer() {
5930 if ((mFlags & FLAG_UNHANDLED) != 0) {
5931 return true;
5932 }
5933
5934 return false;
5935 }
Michael Wright06a79252014-05-05 17:45:29 -07005936
5937 @Override
5938 public String toString() {
5939 StringBuilder sb = new StringBuilder("QueuedInputEvent{flags=");
5940 boolean hasPrevious = false;
5941 hasPrevious = flagToString("DELIVER_POST_IME", FLAG_DELIVER_POST_IME, hasPrevious, sb);
5942 hasPrevious = flagToString("DEFERRED", FLAG_DEFERRED, hasPrevious, sb);
5943 hasPrevious = flagToString("FINISHED", FLAG_FINISHED, hasPrevious, sb);
5944 hasPrevious = flagToString("FINISHED_HANDLED", FLAG_FINISHED_HANDLED, hasPrevious, sb);
5945 hasPrevious = flagToString("RESYNTHESIZED", FLAG_RESYNTHESIZED, hasPrevious, sb);
5946 hasPrevious = flagToString("UNHANDLED", FLAG_UNHANDLED, hasPrevious, sb);
5947 if (!hasPrevious) {
5948 sb.append("0");
5949 }
5950 sb.append(", hasNextQueuedEvent=" + (mEvent != null ? "true" : "false"));
5951 sb.append(", hasInputEventReceiver=" + (mReceiver != null ? "true" : "false"));
5952 sb.append(", mEvent=" + mEvent + "}");
5953 return sb.toString();
5954 }
5955
5956 private boolean flagToString(String name, int flag,
5957 boolean hasPrevious, StringBuilder sb) {
5958 if ((mFlags & flag) != 0) {
5959 if (hasPrevious) {
5960 sb.append("|");
5961 }
5962 sb.append(name);
5963 return true;
5964 }
5965 return hasPrevious;
5966 }
Jeff Brown4952dfd2011-11-30 19:23:22 -08005967 }
5968
5969 private QueuedInputEvent obtainQueuedInputEvent(InputEvent event,
Jeff Brown32cbc38552011-12-01 14:01:49 -08005970 InputEventReceiver receiver, int flags) {
Jeff Brown4952dfd2011-11-30 19:23:22 -08005971 QueuedInputEvent q = mQueuedInputEventPool;
5972 if (q != null) {
5973 mQueuedInputEventPoolSize -= 1;
5974 mQueuedInputEventPool = q.mNext;
5975 q.mNext = null;
5976 } else {
5977 q = new QueuedInputEvent();
Jeff Brown46b9ac02010-04-22 18:58:52 -07005978 }
5979
Jeff Brown4952dfd2011-11-30 19:23:22 -08005980 q.mEvent = event;
Jeff Brown32cbc38552011-12-01 14:01:49 -08005981 q.mReceiver = receiver;
Jeff Brown4952dfd2011-11-30 19:23:22 -08005982 q.mFlags = flags;
Jeff Brown4952dfd2011-11-30 19:23:22 -08005983 return q;
5984 }
5985
5986 private void recycleQueuedInputEvent(QueuedInputEvent q) {
5987 q.mEvent = null;
Jeff Brown32cbc38552011-12-01 14:01:49 -08005988 q.mReceiver = null;
Jeff Brown4952dfd2011-11-30 19:23:22 -08005989
5990 if (mQueuedInputEventPoolSize < MAX_QUEUED_INPUT_EVENT_POOL_SIZE) {
5991 mQueuedInputEventPoolSize += 1;
5992 q.mNext = mQueuedInputEventPool;
5993 mQueuedInputEventPool = q;
5994 }
5995 }
5996
Jeff Brownf9261d22012-02-03 13:49:15 -08005997 void enqueueInputEvent(InputEvent event) {
5998 enqueueInputEvent(event, null, 0, false);
5999 }
6000
Jeff Brown4952dfd2011-11-30 19:23:22 -08006001 void enqueueInputEvent(InputEvent event,
Jeff Brownf9261d22012-02-03 13:49:15 -08006002 InputEventReceiver receiver, int flags, boolean processImmediately) {
Michael Wright5bd69e62015-05-14 14:48:08 +01006003 adjustInputEventForCompatibility(event);
Jeff Brown32cbc38552011-12-01 14:01:49 -08006004 QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
Jeff Brown4952dfd2011-11-30 19:23:22 -08006005
Jeff Brown4952dfd2011-11-30 19:23:22 -08006006 // Always enqueue the input event in order, regardless of its time stamp.
6007 // We do this because the application or the IME may inject key events
6008 // in response to touch events and we want to ensure that the injected keys
6009 // are processed in the order they were received and we cannot trust that
6010 // the time stamp of injected events are monotonic.
Michael Wrightc8a7e542013-03-20 17:58:33 -07006011 QueuedInputEvent last = mPendingInputEventTail;
Jeff Brown4952dfd2011-11-30 19:23:22 -08006012 if (last == null) {
Michael Wrightc8a7e542013-03-20 17:58:33 -07006013 mPendingInputEventHead = q;
6014 mPendingInputEventTail = q;
Jeff Brown4952dfd2011-11-30 19:23:22 -08006015 } else {
Jeff Brown4952dfd2011-11-30 19:23:22 -08006016 last.mNext = q;
Michael Wrightc8a7e542013-03-20 17:58:33 -07006017 mPendingInputEventTail = q;
Jeff Brown4952dfd2011-11-30 19:23:22 -08006018 }
Michael Wright95ae9422013-03-14 10:58:50 -07006019 mPendingInputEventCount += 1;
6020 Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
6021 mPendingInputEventCount);
Jeff Brown4952dfd2011-11-30 19:23:22 -08006022
Jeff Brownf9261d22012-02-03 13:49:15 -08006023 if (processImmediately) {
6024 doProcessInputEvents();
6025 } else {
6026 scheduleProcessInputEvents();
6027 }
Jeff Brown4952dfd2011-11-30 19:23:22 -08006028 }
6029
6030 private void scheduleProcessInputEvents() {
Jeff Brown96e942d2011-11-30 19:55:01 -08006031 if (!mProcessInputEventsScheduled) {
6032 mProcessInputEventsScheduled = true;
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006033 Message msg = mHandler.obtainMessage(MSG_PROCESS_INPUT_EVENTS);
6034 msg.setAsynchronous(true);
6035 mHandler.sendMessage(msg);
Jeff Brown4952dfd2011-11-30 19:23:22 -08006036 }
6037 }
6038
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006039 void doProcessInputEvents() {
Jeff Brownf9e989d2013-04-04 23:04:03 -07006040 // Deliver all pending input events in the queue.
Michael Wrightc8a7e542013-03-20 17:58:33 -07006041 while (mPendingInputEventHead != null) {
6042 QueuedInputEvent q = mPendingInputEventHead;
6043 mPendingInputEventHead = q.mNext;
6044 if (mPendingInputEventHead == null) {
6045 mPendingInputEventTail = null;
6046 }
Jeff Brown4952dfd2011-11-30 19:23:22 -08006047 q.mNext = null;
Jeff Brown29c0ed22013-01-14 13:50:37 -08006048
Michael Wright95ae9422013-03-14 10:58:50 -07006049 mPendingInputEventCount -= 1;
6050 Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
6051 mPendingInputEventCount);
6052
John Reckba6adf62015-02-19 14:36:50 -08006053 long eventTime = q.mEvent.getEventTimeNano();
6054 long oldestEventTime = eventTime;
6055 if (q.mEvent instanceof MotionEvent) {
6056 MotionEvent me = (MotionEvent)q.mEvent;
6057 if (me.getHistorySize() > 0) {
6058 oldestEventTime = me.getHistoricalEventTimeNano(0);
6059 }
6060 }
6061 mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
6062
Jeff Brownf9e989d2013-04-04 23:04:03 -07006063 deliverInputEvent(q);
Jeff Brown4952dfd2011-11-30 19:23:22 -08006064 }
6065
6066 // We are done processing all input events that we can process right now
6067 // so we can clear the pending flag immediately.
Jeff Brown96e942d2011-11-30 19:55:01 -08006068 if (mProcessInputEventsScheduled) {
6069 mProcessInputEventsScheduled = false;
Jeff Browna175a5b2012-02-15 19:18:31 -08006070 mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
Jeff Brown4952dfd2011-11-30 19:23:22 -08006071 }
6072 }
6073
Jeff Brownf9e989d2013-04-04 23:04:03 -07006074 private void deliverInputEvent(QueuedInputEvent q) {
Michael Wrightd2c3adc2014-02-18 22:50:50 -08006075 Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
6076 q.mEvent.getSequenceNumber());
6077 if (mInputEventConsistencyVerifier != null) {
6078 mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
6079 }
Michael Wrightc8a7e542013-03-20 17:58:33 -07006080
Michael Wright899d7052014-04-23 17:23:39 -07006081 InputStage stage;
6082 if (q.shouldSendToSynthesizer()) {
6083 stage = mSyntheticInputStage;
6084 } else {
6085 stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
6086 }
6087
Michael Wrightd2c3adc2014-02-18 22:50:50 -08006088 if (stage != null) {
6089 stage.deliver(q);
6090 } else {
6091 finishInputEvent(q);
Michael Wrightbf020962013-03-28 17:27:50 -07006092 }
Michael Wrightbf020962013-03-28 17:27:50 -07006093 }
6094
Jeff Brownf9e989d2013-04-04 23:04:03 -07006095 private void finishInputEvent(QueuedInputEvent q) {
Michael Wrightd2c3adc2014-02-18 22:50:50 -08006096 Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
6097 q.mEvent.getSequenceNumber());
Michael Wright9d744c72014-02-18 21:27:42 -08006098
Jeff Brown32cbc38552011-12-01 14:01:49 -08006099 if (q.mReceiver != null) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07006100 boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0;
Jeff Brown32cbc38552011-12-01 14:01:49 -08006101 q.mReceiver.finishInputEvent(q.mEvent, handled);
Jeff Brown92cc2d82011-12-02 01:19:47 -08006102 } else {
6103 q.mEvent.recycleIfNeededAfterDispatch();
Jeff Brown4952dfd2011-11-30 19:23:22 -08006104 }
6105
6106 recycleQueuedInputEvent(q);
Jeff Brown29c0ed22013-01-14 13:50:37 -08006107 }
Jeff Brown4952dfd2011-11-30 19:23:22 -08006108
Michael Wright5bd69e62015-05-14 14:48:08 +01006109 private void adjustInputEventForCompatibility(InputEvent e) {
Dianne Hackborn0e3de6c2015-07-29 15:20:21 -07006110 if (mTargetSdkVersion < Build.VERSION_CODES.M && e instanceof MotionEvent) {
Michael Wright5bd69e62015-05-14 14:48:08 +01006111 MotionEvent motion = (MotionEvent) e;
6112 final int mask =
6113 MotionEvent.BUTTON_STYLUS_PRIMARY | MotionEvent.BUTTON_STYLUS_SECONDARY;
6114 final int buttonState = motion.getButtonState();
6115 final int compatButtonState = (buttonState & mask) >> 4;
6116 if (compatButtonState != 0) {
6117 motion.setButtonState(buttonState | compatButtonState);
6118 }
6119 }
6120 }
6121
Jeff Brownf9e989d2013-04-04 23:04:03 -07006122 static boolean isTerminalInputEvent(InputEvent event) {
Jeff Brown29c0ed22013-01-14 13:50:37 -08006123 if (event instanceof KeyEvent) {
6124 final KeyEvent keyEvent = (KeyEvent)event;
6125 return keyEvent.getAction() == KeyEvent.ACTION_UP;
6126 } else {
6127 final MotionEvent motionEvent = (MotionEvent)event;
6128 final int action = motionEvent.getAction();
6129 return action == MotionEvent.ACTION_UP
6130 || action == MotionEvent.ACTION_CANCEL
6131 || action == MotionEvent.ACTION_HOVER_EXIT;
Jeff Brown4952dfd2011-11-30 19:23:22 -08006132 }
6133 }
6134
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006135 void scheduleConsumeBatchedInput() {
6136 if (!mConsumeBatchedInputScheduled) {
6137 mConsumeBatchedInputScheduled = true;
6138 mChoreographer.postCallback(Choreographer.CALLBACK_INPUT,
6139 mConsumedBatchedInputRunnable, null);
Jeff Brown4a06c802012-02-15 15:06:01 -08006140 }
6141 }
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006142
6143 void unscheduleConsumeBatchedInput() {
6144 if (mConsumeBatchedInputScheduled) {
6145 mConsumeBatchedInputScheduled = false;
6146 mChoreographer.removeCallbacks(Choreographer.CALLBACK_INPUT,
6147 mConsumedBatchedInputRunnable, null);
6148 }
6149 }
6150
Michael Wright9d744c72014-02-18 21:27:42 -08006151 void scheduleConsumeBatchedInputImmediately() {
6152 if (!mConsumeBatchedInputImmediatelyScheduled) {
6153 unscheduleConsumeBatchedInput();
6154 mConsumeBatchedInputImmediatelyScheduled = true;
6155 mHandler.post(mConsumeBatchedInputImmediatelyRunnable);
6156 }
6157 }
6158
Jeff Brown771526c2012-04-27 15:13:25 -07006159 void doConsumeBatchedInput(long frameTimeNanos) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006160 if (mConsumeBatchedInputScheduled) {
6161 mConsumeBatchedInputScheduled = false;
Jeff Brown330314c2012-04-27 02:20:22 -07006162 if (mInputEventReceiver != null) {
Michael Wright9d744c72014-02-18 21:27:42 -08006163 if (mInputEventReceiver.consumeBatchedInputEvents(frameTimeNanos)
6164 && frameTimeNanos != -1) {
Michael Wright62ce65d2013-10-25 14:50:36 -07006165 // If we consumed a batch here, we want to go ahead and schedule the
6166 // consumption of batched input events on the next frame. Otherwise, we would
6167 // wait until we have more input events pending and might get starved by other
Michael Wright9d744c72014-02-18 21:27:42 -08006168 // things occurring in the process. If the frame time is -1, however, then
6169 // we're in a non-batching mode, so there's no need to schedule this.
Michael Wright62ce65d2013-10-25 14:50:36 -07006170 scheduleConsumeBatchedInput();
6171 }
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006172 }
Jeff Brown330314c2012-04-27 02:20:22 -07006173 doProcessInputEvents();
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006174 }
6175 }
6176
6177 final class TraversalRunnable implements Runnable {
6178 @Override
6179 public void run() {
6180 doTraversal();
6181 }
6182 }
6183 final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
Jeff Brown4a06c802012-02-15 15:06:01 -08006184
Jeff Brown32cbc38552011-12-01 14:01:49 -08006185 final class WindowInputEventReceiver extends InputEventReceiver {
6186 public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
6187 super(inputChannel, looper);
Jeff Brown46b9ac02010-04-22 18:58:52 -07006188 }
Jeff Brown32cbc38552011-12-01 14:01:49 -08006189
6190 @Override
6191 public void onInputEvent(InputEvent event) {
Jeff Brownf9261d22012-02-03 13:49:15 -08006192 enqueueInputEvent(event, this, 0, true);
Jeff Brown32cbc38552011-12-01 14:01:49 -08006193 }
Jeff Brown072ec962012-02-07 14:46:57 -08006194
6195 @Override
6196 public void onBatchedInputEventPending() {
Michael Wright9d744c72014-02-18 21:27:42 -08006197 if (mUnbufferedInputDispatch) {
6198 super.onBatchedInputEventPending();
6199 } else {
6200 scheduleConsumeBatchedInput();
6201 }
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006202 }
6203
6204 @Override
6205 public void dispose() {
6206 unscheduleConsumeBatchedInput();
6207 super.dispose();
Jeff Brown072ec962012-02-07 14:46:57 -08006208 }
Jeff Brown32cbc38552011-12-01 14:01:49 -08006209 }
6210 WindowInputEventReceiver mInputEventReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006211
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006212 final class ConsumeBatchedInputRunnable implements Runnable {
6213 @Override
6214 public void run() {
Jeff Brown771526c2012-04-27 15:13:25 -07006215 doConsumeBatchedInput(mChoreographer.getFrameTimeNanos());
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006216 }
6217 }
6218 final ConsumeBatchedInputRunnable mConsumedBatchedInputRunnable =
6219 new ConsumeBatchedInputRunnable();
6220 boolean mConsumeBatchedInputScheduled;
6221
Michael Wright9d744c72014-02-18 21:27:42 -08006222 final class ConsumeBatchedInputImmediatelyRunnable implements Runnable {
6223 @Override
6224 public void run() {
6225 doConsumeBatchedInput(-1);
6226 }
6227 }
6228 final ConsumeBatchedInputImmediatelyRunnable mConsumeBatchedInputImmediatelyRunnable =
6229 new ConsumeBatchedInputImmediatelyRunnable();
6230 boolean mConsumeBatchedInputImmediatelyScheduled;
6231
Jeff Brown6cb7b462012-03-05 13:21:17 -08006232 final class InvalidateOnAnimationRunnable implements Runnable {
6233 private boolean mPosted;
Igor Murashkina86ab6402013-08-30 12:58:36 -07006234 private final ArrayList<View> mViews = new ArrayList<View>();
6235 private final ArrayList<AttachInfo.InvalidateInfo> mViewRects =
Jeff Brown6cb7b462012-03-05 13:21:17 -08006236 new ArrayList<AttachInfo.InvalidateInfo>();
6237 private View[] mTempViews;
6238 private AttachInfo.InvalidateInfo[] mTempViewRects;
6239
6240 public void addView(View view) {
6241 synchronized (this) {
6242 mViews.add(view);
6243 postIfNeededLocked();
6244 }
6245 }
6246
6247 public void addViewRect(AttachInfo.InvalidateInfo info) {
6248 synchronized (this) {
6249 mViewRects.add(info);
6250 postIfNeededLocked();
6251 }
6252 }
6253
6254 public void removeView(View view) {
6255 synchronized (this) {
6256 mViews.remove(view);
6257
6258 for (int i = mViewRects.size(); i-- > 0; ) {
6259 AttachInfo.InvalidateInfo info = mViewRects.get(i);
6260 if (info.target == view) {
6261 mViewRects.remove(i);
Svetoslav Ganovabae2a12012-11-27 16:59:37 -08006262 info.recycle();
Jeff Brown6cb7b462012-03-05 13:21:17 -08006263 }
6264 }
6265
6266 if (mPosted && mViews.isEmpty() && mViewRects.isEmpty()) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006267 mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, this, null);
Jeff Brown6cb7b462012-03-05 13:21:17 -08006268 mPosted = false;
6269 }
6270 }
6271 }
6272
6273 @Override
6274 public void run() {
6275 final int viewCount;
6276 final int viewRectCount;
6277 synchronized (this) {
6278 mPosted = false;
6279
6280 viewCount = mViews.size();
6281 if (viewCount != 0) {
6282 mTempViews = mViews.toArray(mTempViews != null
6283 ? mTempViews : new View[viewCount]);
6284 mViews.clear();
6285 }
6286
6287 viewRectCount = mViewRects.size();
6288 if (viewRectCount != 0) {
6289 mTempViewRects = mViewRects.toArray(mTempViewRects != null
6290 ? mTempViewRects : new AttachInfo.InvalidateInfo[viewRectCount]);
6291 mViewRects.clear();
6292 }
6293 }
6294
6295 for (int i = 0; i < viewCount; i++) {
6296 mTempViews[i].invalidate();
Adam Powell3e3c4ee2012-05-16 17:34:21 -07006297 mTempViews[i] = null;
Jeff Brown6cb7b462012-03-05 13:21:17 -08006298 }
6299
6300 for (int i = 0; i < viewRectCount; i++) {
6301 final View.AttachInfo.InvalidateInfo info = mTempViewRects[i];
6302 info.target.invalidate(info.left, info.top, info.right, info.bottom);
Svetoslav Ganovabae2a12012-11-27 16:59:37 -08006303 info.recycle();
Jeff Brown6cb7b462012-03-05 13:21:17 -08006304 }
6305 }
6306
6307 private void postIfNeededLocked() {
6308 if (!mPosted) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006309 mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null);
Jeff Brown6cb7b462012-03-05 13:21:17 -08006310 mPosted = true;
6311 }
6312 }
6313 }
6314 final InvalidateOnAnimationRunnable mInvalidateOnAnimationRunnable =
6315 new InvalidateOnAnimationRunnable();
6316
Jeff Browna175a5b2012-02-15 19:18:31 -08006317 public void dispatchInvalidateDelayed(View view, long delayMilliseconds) {
6318 Message msg = mHandler.obtainMessage(MSG_INVALIDATE, view);
6319 mHandler.sendMessageDelayed(msg, delayMilliseconds);
6320 }
6321
Jeff Browna175a5b2012-02-15 19:18:31 -08006322 public void dispatchInvalidateRectDelayed(AttachInfo.InvalidateInfo info,
6323 long delayMilliseconds) {
6324 final Message msg = mHandler.obtainMessage(MSG_INVALIDATE_RECT, info);
6325 mHandler.sendMessageDelayed(msg, delayMilliseconds);
6326 }
6327
Jeff Brown6cb7b462012-03-05 13:21:17 -08006328 public void dispatchInvalidateOnAnimation(View view) {
6329 mInvalidateOnAnimationRunnable.addView(view);
6330 }
6331
6332 public void dispatchInvalidateRectOnAnimation(AttachInfo.InvalidateInfo info) {
6333 mInvalidateOnAnimationRunnable.addViewRect(info);
6334 }
6335
6336 public void cancelInvalidate(View view) {
6337 mHandler.removeMessages(MSG_INVALIDATE, view);
6338 // fixme: might leak the AttachInfo.InvalidateInfo objects instead of returning
6339 // them to the pool
6340 mHandler.removeMessages(MSG_INVALIDATE_RECT, view);
6341 mInvalidateOnAnimationRunnable.removeView(view);
6342 }
6343
keunyoung30f420f2013-08-02 14:23:10 -07006344 public void dispatchInputEvent(InputEvent event) {
Jae Seo6a6059a2014-04-17 21:35:29 -07006345 dispatchInputEvent(event, null);
6346 }
6347
6348 public void dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {
6349 SomeArgs args = SomeArgs.obtain();
6350 args.arg1 = event;
6351 args.arg2 = receiver;
6352 Message msg = mHandler.obtainMessage(MSG_DISPATCH_INPUT_EVENT, args);
Jeff Browne0dbd002012-02-15 19:34:58 -08006353 msg.setAsynchronous(true);
Jeff Browna175a5b2012-02-15 19:18:31 -08006354 mHandler.sendMessage(msg);
6355 }
6356
Michael Wright899d7052014-04-23 17:23:39 -07006357 public void synthesizeInputEvent(InputEvent event) {
6358 Message msg = mHandler.obtainMessage(MSG_SYNTHESIZE_INPUT_EVENT, event);
6359 msg.setAsynchronous(true);
6360 mHandler.sendMessage(msg);
6361 }
6362
Jeff Browna175a5b2012-02-15 19:18:31 -08006363 public void dispatchKeyFromIme(KeyEvent event) {
6364 Message msg = mHandler.obtainMessage(MSG_DISPATCH_KEY_FROM_IME, event);
Jeff Browne0dbd002012-02-15 19:34:58 -08006365 msg.setAsynchronous(true);
Jeff Browna175a5b2012-02-15 19:18:31 -08006366 mHandler.sendMessage(msg);
Jeff Browncb1404e2011-01-15 18:14:15 -08006367 }
6368
Michael Wright899d7052014-04-23 17:23:39 -07006369 /**
6370 * Reinject unhandled {@link InputEvent}s in order to synthesize fallbacks events.
6371 *
6372 * Note that it is the responsibility of the caller of this API to recycle the InputEvent it
6373 * passes in.
6374 */
Michael Wright3da28342014-04-22 17:00:11 -07006375 public void dispatchUnhandledInputEvent(InputEvent event) {
Michael Wright899d7052014-04-23 17:23:39 -07006376 if (event instanceof MotionEvent) {
6377 event = MotionEvent.obtain((MotionEvent) event);
Michael Wright3da28342014-04-22 17:00:11 -07006378 }
Michael Wright899d7052014-04-23 17:23:39 -07006379 synthesizeInputEvent(event);
Michael Wright3da28342014-04-22 17:00:11 -07006380 }
6381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006382 public void dispatchAppVisibility(boolean visible) {
Jeff Browna175a5b2012-02-15 19:18:31 -08006383 Message msg = mHandler.obtainMessage(MSG_DISPATCH_APP_VISIBILITY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006384 msg.arg1 = visible ? 1 : 0;
Jeff Browna175a5b2012-02-15 19:18:31 -08006385 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006386 }
6387
6388 public void dispatchGetNewSurface() {
Jeff Browna175a5b2012-02-15 19:18:31 -08006389 Message msg = mHandler.obtainMessage(MSG_DISPATCH_GET_NEW_SURFACE);
6390 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006391 }
6392
6393 public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
6394 Message msg = Message.obtain();
Jeff Browna175a5b2012-02-15 19:18:31 -08006395 msg.what = MSG_WINDOW_FOCUS_CHANGED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006396 msg.arg1 = hasFocus ? 1 : 0;
6397 msg.arg2 = inTouchMode ? 1 : 0;
Jeff Browna175a5b2012-02-15 19:18:31 -08006398 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006399 }
6400
Craig Mautner9c795042014-10-28 19:59:59 -07006401 public void dispatchWindowShown() {
6402 mHandler.sendEmptyMessage(MSG_DISPATCH_WINDOW_SHOWN);
6403 }
6404
Dianne Hackbornffa42482009-09-23 22:20:11 -07006405 public void dispatchCloseSystemDialogs(String reason) {
6406 Message msg = Message.obtain();
Jeff Browna175a5b2012-02-15 19:18:31 -08006407 msg.what = MSG_CLOSE_SYSTEM_DIALOGS;
Dianne Hackbornffa42482009-09-23 22:20:11 -07006408 msg.obj = reason;
Jeff Browna175a5b2012-02-15 19:18:31 -08006409 mHandler.sendMessage(msg);
Dianne Hackbornffa42482009-09-23 22:20:11 -07006410 }
Christopher Tatea53146c2010-09-07 11:57:52 -07006411
6412 public void dispatchDragEvent(DragEvent event) {
Chris Tate91e9bb32010-10-12 12:58:43 -07006413 final int what;
6414 if (event.getAction() == DragEvent.ACTION_DRAG_LOCATION) {
Jeff Browna175a5b2012-02-15 19:18:31 -08006415 what = MSG_DISPATCH_DRAG_LOCATION_EVENT;
6416 mHandler.removeMessages(what);
Chris Tate91e9bb32010-10-12 12:58:43 -07006417 } else {
Jeff Browna175a5b2012-02-15 19:18:31 -08006418 what = MSG_DISPATCH_DRAG_EVENT;
Chris Tate91e9bb32010-10-12 12:58:43 -07006419 }
Jeff Browna175a5b2012-02-15 19:18:31 -08006420 Message msg = mHandler.obtainMessage(what, event);
6421 mHandler.sendMessage(msg);
Christopher Tatea53146c2010-09-07 11:57:52 -07006422 }
6423
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08006424 public void updatePointerIcon(float x, float y) {
6425 final int what = MSG_UPDATE_POINTER_ICON;
6426 mHandler.removeMessages(what);
6427 final long now = SystemClock.uptimeMillis();
6428 final MotionEvent event = MotionEvent.obtain(
6429 0, now, MotionEvent.ACTION_HOVER_MOVE, x, y, 0);
6430 Message msg = mHandler.obtainMessage(what, event);
6431 mHandler.sendMessage(msg);
6432 }
6433
Dianne Hackborn9a230e02011-10-06 11:51:27 -07006434 public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
6435 int localValue, int localChanges) {
6436 SystemUiVisibilityInfo args = new SystemUiVisibilityInfo();
6437 args.seq = seq;
6438 args.globalVisibility = globalVisibility;
6439 args.localValue = localValue;
6440 args.localChanges = localChanges;
Jeff Browna175a5b2012-02-15 19:18:31 -08006441 mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPATCH_SYSTEM_UI_VISIBILITY, args));
6442 }
6443
6444 public void dispatchCheckFocus() {
6445 if (!mHandler.hasMessages(MSG_CHECK_FOCUS)) {
6446 // This will result in a call to checkFocus() below.
6447 mHandler.sendEmptyMessage(MSG_CHECK_FOCUS);
6448 }
Joe Onorato664644d2011-01-23 17:53:23 -08006449 }
6450
Clara Bayarri75e09792015-07-29 16:20:40 +01006451 public void dispatchRequestKeyboardShortcuts(IResultReceiver receiver) {
6452 mHandler.obtainMessage(MSG_REQUEST_KEYBOARD_SHORTCUTS, receiver).sendToTarget();
6453 }
6454
svetoslavganov75986cf2009-05-14 22:28:01 -07006455 /**
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07006456 * Post a callback to send a
6457 * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
Svetoslav Ganova0156172011-06-26 17:55:44 -07006458 * This event is send at most once every
6459 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07006460 */
Alan Viverette77e9a282013-09-12 17:16:09 -07006461 private void postSendWindowContentChangedCallback(View source, int changeType) {
Svetoslav Ganova0156172011-06-26 17:55:44 -07006462 if (mSendWindowContentChangedAccessibilityEvent == null) {
6463 mSendWindowContentChangedAccessibilityEvent =
6464 new SendWindowContentChangedAccessibilityEvent();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07006465 }
Alan Viverette77e9a282013-09-12 17:16:09 -07006466 mSendWindowContentChangedAccessibilityEvent.runOrPost(source, changeType);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07006467 }
6468
6469 /**
6470 * Remove a posted callback to send a
6471 * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
6472 */
6473 private void removeSendWindowContentChangedCallback() {
Svetoslav Ganova0156172011-06-26 17:55:44 -07006474 if (mSendWindowContentChangedAccessibilityEvent != null) {
Jeff Browna175a5b2012-02-15 19:18:31 -08006475 mHandler.removeCallbacks(mSendWindowContentChangedAccessibilityEvent);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07006476 }
6477 }
6478
Igor Murashkina86ab6402013-08-30 12:58:36 -07006479 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006480 public boolean showContextMenuForChild(View originalView) {
6481 return false;
6482 }
6483
Igor Murashkina86ab6402013-08-30 12:58:36 -07006484 @Override
Oren Blasberged391262015-09-01 12:12:51 -07006485 public boolean showContextMenuForChild(View originalView, float x, float y) {
6486 return false;
6487 }
6488
6489 @Override
Adam Powell6e346362010-07-23 10:18:23 -07006490 public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback) {
6491 return null;
6492 }
6493
Igor Murashkina86ab6402013-08-30 12:58:36 -07006494 @Override
Clara Bayarri4423d912015-03-02 19:42:48 +00006495 public ActionMode startActionModeForChild(
6496 View originalView, ActionMode.Callback callback, int type) {
6497 return null;
6498 }
6499
6500 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006501 public void createContextMenu(ContextMenu menu) {
6502 }
6503
Igor Murashkina86ab6402013-08-30 12:58:36 -07006504 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006505 public void childDrawableStateChanged(View child) {
6506 }
6507
Igor Murashkina86ab6402013-08-30 12:58:36 -07006508 @Override
Svetoslav Ganov736c2752011-04-22 18:30:36 -07006509 public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) {
George Mount41725de2015-04-09 08:23:05 -07006510 if (mView == null || mStopped || mPausedForTransition) {
Svetoslav Ganov736c2752011-04-22 18:30:36 -07006511 return false;
6512 }
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07006513 // Intercept accessibility focus events fired by virtual nodes to keep
6514 // track of accessibility focus position in such nodes.
Svetoslav Ganov791fd312012-05-14 15:12:30 -07006515 final int eventType = event.getEventType();
6516 switch (eventType) {
6517 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07006518 final long sourceNodeId = event.getSourceNodeId();
6519 final int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(
6520 sourceNodeId);
6521 View source = mView.findViewByAccessibilityId(accessibilityViewId);
6522 if (source != null) {
6523 AccessibilityNodeProvider provider = source.getAccessibilityNodeProvider();
6524 if (provider != null) {
Svetoslavb3ba1d42014-09-26 15:20:40 -07006525 final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
6526 sourceNodeId);
6527 final AccessibilityNodeInfo node;
6528 if (virtualNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
6529 node = provider.createAccessibilityNodeInfo(
6530 AccessibilityNodeProvider.HOST_VIEW_ID);
6531 } else {
6532 node = provider.createAccessibilityNodeInfo(virtualNodeId);
6533 }
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07006534 setAccessibilityFocus(source, node);
6535 }
Svetoslav Ganov791fd312012-05-14 15:12:30 -07006536 }
Svetoslav Ganov791fd312012-05-14 15:12:30 -07006537 } break;
6538 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07006539 final long sourceNodeId = event.getSourceNodeId();
6540 final int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(
6541 sourceNodeId);
6542 View source = mView.findViewByAccessibilityId(accessibilityViewId);
6543 if (source != null) {
6544 AccessibilityNodeProvider provider = source.getAccessibilityNodeProvider();
6545 if (provider != null) {
6546 setAccessibilityFocus(null, null);
6547 }
Svetoslav Ganov791fd312012-05-14 15:12:30 -07006548 }
Svetoslav Ganov791fd312012-05-14 15:12:30 -07006549 } break;
Svetoslavf0c758b2014-09-03 17:47:37 -07006550
6551
6552 case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
Alan Viverette34457f52015-03-25 13:09:20 -07006553 handleWindowContentChangedEvent(event);
Svetoslavf0c758b2014-09-03 17:47:37 -07006554 } break;
Svetoslav Ganov791fd312012-05-14 15:12:30 -07006555 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006556 mAccessibilityManager.sendAccessibilityEvent(event);
Svetoslav Ganov736c2752011-04-22 18:30:36 -07006557 return true;
6558 }
6559
Alan Viverette34457f52015-03-25 13:09:20 -07006560 /**
6561 * Updates the focused virtual view, when necessary, in response to a
6562 * content changed event.
6563 * <p>
6564 * This is necessary to get updated bounds after a position change.
6565 *
6566 * @param event an accessibility event of type
6567 * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}
6568 */
6569 private void handleWindowContentChangedEvent(AccessibilityEvent event) {
Alan Viverette25acc7e2015-05-19 11:32:08 -07006570 final View focusedHost = mAccessibilityFocusedHost;
6571 if (focusedHost == null || mAccessibilityFocusedVirtualView == null) {
6572 // No virtual view focused, nothing to do here.
Alan Viverette34457f52015-03-25 13:09:20 -07006573 return;
6574 }
6575
Alan Viverette25acc7e2015-05-19 11:32:08 -07006576 final AccessibilityNodeProvider provider = focusedHost.getAccessibilityNodeProvider();
Alan Viverette34457f52015-03-25 13:09:20 -07006577 if (provider == null) {
Alan Viverette25acc7e2015-05-19 11:32:08 -07006578 // Error state: virtual view with no provider. Clear focus.
6579 mAccessibilityFocusedHost = null;
6580 mAccessibilityFocusedVirtualView = null;
6581 focusedHost.clearAccessibilityFocusNoCallbacks();
Alan Viverette34457f52015-03-25 13:09:20 -07006582 return;
6583 }
6584
6585 // We only care about change types that may affect the bounds of the
6586 // focused virtual view.
6587 final int changes = event.getContentChangeTypes();
6588 if ((changes & AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE) == 0
6589 && changes != AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED) {
6590 return;
6591 }
6592
6593 final long eventSourceNodeId = event.getSourceNodeId();
6594 final int changedViewId = AccessibilityNodeInfo.getAccessibilityViewId(eventSourceNodeId);
6595
6596 // Search up the tree for subtree containment.
6597 boolean hostInSubtree = false;
6598 View root = mAccessibilityFocusedHost;
6599 while (root != null && !hostInSubtree) {
6600 if (changedViewId == root.getAccessibilityViewId()) {
6601 hostInSubtree = true;
6602 } else {
6603 final ViewParent parent = root.getParent();
6604 if (parent instanceof View) {
6605 root = (View) parent;
6606 } else {
6607 root = null;
6608 }
6609 }
6610 }
6611
6612 // We care only about changes in subtrees containing the host view.
6613 if (!hostInSubtree) {
6614 return;
6615 }
6616
6617 final long focusedSourceNodeId = mAccessibilityFocusedVirtualView.getSourceNodeId();
6618 int focusedChildId = AccessibilityNodeInfo.getVirtualDescendantId(focusedSourceNodeId);
6619 if (focusedChildId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
6620 // TODO: Should we clear the focused virtual view?
6621 focusedChildId = AccessibilityNodeProvider.HOST_VIEW_ID;
6622 }
6623
6624 // Refresh the node for the focused virtual view.
Alan Viverettea7ea65e2015-05-15 11:30:21 -07006625 final Rect oldBounds = mTempRect;
6626 mAccessibilityFocusedVirtualView.getBoundsInScreen(oldBounds);
Alan Viverette34457f52015-03-25 13:09:20 -07006627 mAccessibilityFocusedVirtualView = provider.createAccessibilityNodeInfo(focusedChildId);
Alan Viverette25acc7e2015-05-19 11:32:08 -07006628 if (mAccessibilityFocusedVirtualView == null) {
6629 // Error state: The node no longer exists. Clear focus.
6630 mAccessibilityFocusedHost = null;
6631 focusedHost.clearAccessibilityFocusNoCallbacks();
6632
6633 // This will probably fail, but try to keep the provider's internal
6634 // state consistent by clearing focus.
6635 provider.performAction(focusedChildId,
6636 AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS.getId(), null);
Alan Viverettea7ea65e2015-05-15 11:30:21 -07006637 invalidateRectOnScreen(oldBounds);
Alan Viverette25acc7e2015-05-19 11:32:08 -07006638 } else {
6639 // The node was refreshed, invalidate bounds if necessary.
6640 final Rect newBounds = mAccessibilityFocusedVirtualView.getBoundsInScreen();
6641 if (!oldBounds.equals(newBounds)) {
6642 oldBounds.union(newBounds);
6643 invalidateRectOnScreen(oldBounds);
6644 }
Alan Viverettea7ea65e2015-05-15 11:30:21 -07006645 }
Alan Viverette34457f52015-03-25 13:09:20 -07006646 }
6647
Svetoslav Ganov42138042012-03-20 11:51:39 -07006648 @Override
Alan Viverette77e9a282013-09-12 17:16:09 -07006649 public void notifySubtreeAccessibilityStateChanged(View child, View source, int changeType) {
6650 postSendWindowContentChangedCallback(source, changeType);
Svetoslav Ganov42138042012-03-20 11:51:39 -07006651 }
6652
Fabrice Di Meglio9dd4c5c2013-02-08 18:15:07 -08006653 @Override
6654 public boolean canResolveLayoutDirection() {
6655 return true;
6656 }
6657
6658 @Override
6659 public boolean isLayoutDirectionResolved() {
6660 return true;
6661 }
6662
6663 @Override
6664 public int getLayoutDirection() {
6665 return View.LAYOUT_DIRECTION_RESOLVED_DEFAULT;
6666 }
6667
6668 @Override
6669 public boolean canResolveTextDirection() {
6670 return true;
6671 }
6672
6673 @Override
6674 public boolean isTextDirectionResolved() {
6675 return true;
6676 }
6677
6678 @Override
6679 public int getTextDirection() {
6680 return View.TEXT_DIRECTION_RESOLVED_DEFAULT;
6681 }
6682
6683 @Override
6684 public boolean canResolveTextAlignment() {
6685 return true;
6686 }
6687
6688 @Override
6689 public boolean isTextAlignmentResolved() {
6690 return true;
6691 }
6692
6693 @Override
6694 public int getTextAlignment() {
6695 return View.TEXT_ALIGNMENT_RESOLVED_DEFAULT;
6696 }
6697
Svetoslav Ganov42138042012-03-20 11:51:39 -07006698 private View getCommonPredecessor(View first, View second) {
Chris Craikd36a81f2014-07-17 10:16:51 -07006699 if (mTempHashSet == null) {
6700 mTempHashSet = new HashSet<View>();
Svetoslav Ganov42138042012-03-20 11:51:39 -07006701 }
Chris Craikd36a81f2014-07-17 10:16:51 -07006702 HashSet<View> seen = mTempHashSet;
6703 seen.clear();
6704 View firstCurrent = first;
6705 while (firstCurrent != null) {
6706 seen.add(firstCurrent);
6707 ViewParent firstCurrentParent = firstCurrent.mParent;
6708 if (firstCurrentParent instanceof View) {
6709 firstCurrent = (View) firstCurrentParent;
6710 } else {
6711 firstCurrent = null;
6712 }
6713 }
6714 View secondCurrent = second;
6715 while (secondCurrent != null) {
6716 if (seen.contains(secondCurrent)) {
6717 seen.clear();
6718 return secondCurrent;
6719 }
6720 ViewParent secondCurrentParent = secondCurrent.mParent;
6721 if (secondCurrentParent instanceof View) {
6722 secondCurrent = (View) secondCurrentParent;
6723 } else {
6724 secondCurrent = null;
6725 }
6726 }
6727 seen.clear();
Svetoslav Ganov42138042012-03-20 11:51:39 -07006728 return null;
6729 }
6730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006731 void checkThread() {
6732 if (mThread != Thread.currentThread()) {
6733 throw new CalledFromWrongThreadException(
6734 "Only the original thread that created a view hierarchy can touch its views.");
6735 }
6736 }
6737
Igor Murashkina86ab6402013-08-30 12:58:36 -07006738 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006739 public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
Joe Onoratoc6cc0f82011-04-12 11:53:13 -07006740 // ViewAncestor never intercepts touch event, so this can be a no-op
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006741 }
6742
Igor Murashkina86ab6402013-08-30 12:58:36 -07006743 @Override
Svetoslav Ganov1cf70bb2012-08-06 10:53:34 -07006744 public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
Yigit Boyard62d5e92016-01-19 18:56:20 -08006745 if (rectangle == null) {
6746 return scrollToRectOrFocus(null, immediate);
6747 }
6748 rectangle.offset(child.getLeft() - child.getScrollX(),
6749 child.getTop() - child.getScrollY());
Svetoslav Ganov1cf70bb2012-08-06 10:53:34 -07006750 final boolean scrolled = scrollToRectOrFocus(rectangle, immediate);
Yigit Boyard62d5e92016-01-19 18:56:20 -08006751 mTempRect.set(rectangle);
6752 mTempRect.offset(0, -mCurScrollY);
6753 mTempRect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6754 try {
6755 mWindowSession.onRectangleOnScreenRequested(mWindow, mTempRect);
6756 } catch (RemoteException re) {
6757 /* ignore */
Svetoslav Ganov1cf70bb2012-08-06 10:53:34 -07006758 }
6759 return scrolled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006760 }
Romain Guy8506ab42009-06-11 17:35:47 -07006761
Igor Murashkina86ab6402013-08-30 12:58:36 -07006762 @Override
Adam Powell539ee872012-02-03 19:00:49 -08006763 public void childHasTransientStateChanged(View child, boolean hasTransientState) {
6764 // Do nothing.
6765 }
6766
Adam Powell10ba2772014-04-15 09:46:51 -07006767 @Override
6768 public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
6769 return false;
6770 }
6771
6772 @Override
6773 public void onStopNestedScroll(View target) {
6774 }
6775
6776 @Override
6777 public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) {
6778 }
6779
6780 @Override
6781 public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
6782 int dxUnconsumed, int dyUnconsumed) {
6783 }
6784
6785 @Override
6786 public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
6787 }
6788
6789 @Override
Adam Powellb36e4f92014-05-01 10:23:33 -07006790 public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
Adam Powell10ba2772014-04-15 09:46:51 -07006791 return false;
6792 }
6793
Adam Powellb72be592014-07-16 21:41:31 -07006794 @Override
6795 public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
6796 return false;
6797 }
6798
Adam Powellb6ab0982015-01-07 17:00:12 -08006799 @Override
6800 public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle args) {
6801 return false;
6802 }
6803
Jorim Jaggib774e552015-08-24 14:52:45 -07006804 /**
6805 * Force the window to report its next draw.
6806 * <p>
6807 * This method is only supposed to be used to speed up the interaction from SystemUI and window
6808 * manager when waiting for the first frame to be drawn when turning on the screen. DO NOT USE
6809 * unless you fully understand this interaction.
6810 * @hide
6811 */
6812 public void setReportNextDraw() {
6813 mReportNextDraw = true;
6814 invalidate();
6815 }
6816
Craig Mautnerbc57cd12013-08-19 15:47:42 -07006817 void changeCanvasOpacity(boolean opaque) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08006818 Log.d(mTag, "changeCanvasOpacity: opaque=" + opaque);
John Reck63a06672014-05-07 13:45:54 -07006819 if (mAttachInfo.mHardwareRenderer != null) {
6820 mAttachInfo.mHardwareRenderer.setOpaque(opaque);
6821 }
Craig Mautnerbc57cd12013-08-19 15:47:42 -07006822 }
6823
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07006824 class TakenSurfaceHolder extends BaseSurfaceHolder {
6825 @Override
6826 public boolean onAllowLockCanvas() {
6827 return mDrawingAllowed;
6828 }
6829
6830 @Override
6831 public void onRelayoutContainer() {
6832 // Not currently interesting -- from changing between fixed and layout size.
6833 }
6834
Igor Murashkina86ab6402013-08-30 12:58:36 -07006835 @Override
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07006836 public void setFormat(int format) {
6837 ((RootViewSurfaceTaker)mView).setSurfaceFormat(format);
6838 }
6839
Igor Murashkina86ab6402013-08-30 12:58:36 -07006840 @Override
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07006841 public void setType(int type) {
6842 ((RootViewSurfaceTaker)mView).setSurfaceType(type);
6843 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07006844
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07006845 @Override
6846 public void onUpdateSurface() {
6847 // We take care of format and type changes on our own.
6848 throw new IllegalStateException("Shouldn't be here");
6849 }
6850
Igor Murashkina86ab6402013-08-30 12:58:36 -07006851 @Override
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07006852 public boolean isCreating() {
6853 return mIsCreating;
6854 }
6855
6856 @Override
6857 public void setFixedSize(int width, int height) {
6858 throw new UnsupportedOperationException(
6859 "Currently only support sizing from layout");
6860 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07006861
6862 @Override
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07006863 public void setKeepScreenOn(boolean screenOn) {
6864 ((RootViewSurfaceTaker)mView).setSurfaceKeepScreenOn(screenOn);
6865 }
6866 }
Romain Guy8506ab42009-06-11 17:35:47 -07006867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006868 static class W extends IWindow.Stub {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07006869 private final WeakReference<ViewRootImpl> mViewAncestor;
Jeff Brown98365d72012-08-19 20:30:52 -07006870 private final IWindowSession mWindowSession;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006871
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07006872 W(ViewRootImpl viewAncestor) {
6873 mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
Jeff Brown98365d72012-08-19 20:30:52 -07006874 mWindowSession = viewAncestor.mWindowSession;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006875 }
6876
Igor Murashkina86ab6402013-08-30 12:58:36 -07006877 @Override
Dianne Hackbornc4aad012013-02-22 15:05:25 -08006878 public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Filip Gruszczynski2217f612015-05-26 11:32:08 -07006879 Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
Jorim Jaggia4a58ef2016-01-27 02:10:08 -08006880 Configuration newConfig, Rect backDropFrame, boolean forceLayout) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07006881 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006882 if (viewAncestor != null) {
Dianne Hackbornc4aad012013-02-22 15:05:25 -08006883 viewAncestor.dispatchResized(frame, overscanInsets, contentInsets,
Jorim Jaggia4a58ef2016-01-27 02:10:08 -08006884 visibleInsets, stableInsets, outsets, reportDraw, newConfig, backDropFrame,
6885 forceLayout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006886 }
6887 }
6888
Craig Mautner5702d4d2012-06-30 14:10:16 -07006889 @Override
6890 public void moved(int newX, int newY) {
6891 final ViewRootImpl viewAncestor = mViewAncestor.get();
6892 if (viewAncestor != null) {
6893 viewAncestor.dispatchMoved(newX, newY);
6894 }
6895 }
6896
Igor Murashkina86ab6402013-08-30 12:58:36 -07006897 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006898 public void dispatchAppVisibility(boolean visible) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07006899 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006900 if (viewAncestor != null) {
6901 viewAncestor.dispatchAppVisibility(visible);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006902 }
6903 }
6904
Igor Murashkina86ab6402013-08-30 12:58:36 -07006905 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006906 public void dispatchGetNewSurface() {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07006907 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006908 if (viewAncestor != null) {
6909 viewAncestor.dispatchGetNewSurface();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006910 }
6911 }
6912
Igor Murashkina86ab6402013-08-30 12:58:36 -07006913 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006914 public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07006915 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006916 if (viewAncestor != null) {
6917 viewAncestor.windowFocusChanged(hasFocus, inTouchMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006918 }
6919 }
6920
6921 private static int checkCallingPermission(String permission) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006922 try {
6923 return ActivityManagerNative.getDefault().checkPermission(
6924 permission, Binder.getCallingPid(), Binder.getCallingUid());
6925 } catch (RemoteException e) {
6926 return PackageManager.PERMISSION_DENIED;
6927 }
6928 }
6929
Igor Murashkina86ab6402013-08-30 12:58:36 -07006930 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006931 public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07006932 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006933 if (viewAncestor != null) {
6934 final View view = viewAncestor.mView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006935 if (view != null) {
6936 if (checkCallingPermission(Manifest.permission.DUMP) !=
6937 PackageManager.PERMISSION_GRANTED) {
6938 throw new SecurityException("Insufficient permissions to invoke"
6939 + " executeCommand() from pid=" + Binder.getCallingPid()
6940 + ", uid=" + Binder.getCallingUid());
6941 }
6942
6943 OutputStream clientStream = null;
6944 try {
6945 clientStream = new ParcelFileDescriptor.AutoCloseOutputStream(out);
6946 ViewDebug.dispatchCommand(view, command, parameters, clientStream);
6947 } catch (IOException e) {
6948 e.printStackTrace();
6949 } finally {
6950 if (clientStream != null) {
6951 try {
6952 clientStream.close();
6953 } catch (IOException e) {
6954 e.printStackTrace();
6955 }
6956 }
6957 }
6958 }
6959 }
6960 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07006961
6962 @Override
Dianne Hackbornffa42482009-09-23 22:20:11 -07006963 public void closeSystemDialogs(String reason) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07006964 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006965 if (viewAncestor != null) {
6966 viewAncestor.dispatchCloseSystemDialogs(reason);
Dianne Hackbornffa42482009-09-23 22:20:11 -07006967 }
6968 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07006969
6970 @Override
Marco Nelissenbf6956b2009-11-09 15:21:13 -08006971 public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
6972 boolean sync) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07006973 if (sync) {
6974 try {
Jeff Brown98365d72012-08-19 20:30:52 -07006975 mWindowSession.wallpaperOffsetsComplete(asBinder());
Dianne Hackborn19382ac2009-09-11 21:13:37 -07006976 } catch (RemoteException e) {
6977 }
6978 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07006979 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006980
Igor Murashkina86ab6402013-08-30 12:58:36 -07006981 @Override
Dianne Hackborn75804932009-10-20 20:15:20 -07006982 public void dispatchWallpaperCommand(String action, int x, int y,
6983 int z, Bundle extras, boolean sync) {
6984 if (sync) {
6985 try {
Jeff Brown98365d72012-08-19 20:30:52 -07006986 mWindowSession.wallpaperCommandComplete(asBinder(), null);
Dianne Hackborn75804932009-10-20 20:15:20 -07006987 } catch (RemoteException e) {
6988 }
6989 }
6990 }
Christopher Tatea53146c2010-09-07 11:57:52 -07006991
6992 /* Drag/drop */
Igor Murashkina86ab6402013-08-30 12:58:36 -07006993 @Override
Christopher Tatea53146c2010-09-07 11:57:52 -07006994 public void dispatchDragEvent(DragEvent event) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07006995 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006996 if (viewAncestor != null) {
6997 viewAncestor.dispatchDragEvent(event);
Christopher Tatea53146c2010-09-07 11:57:52 -07006998 }
6999 }
Joe Onorato664644d2011-01-23 17:53:23 -08007000
Igor Murashkina86ab6402013-08-30 12:58:36 -07007001 @Override
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08007002 public void updatePointerIcon(float x, float y) {
7003 final ViewRootImpl viewAncestor = mViewAncestor.get();
7004 if (viewAncestor != null) {
7005 viewAncestor.updatePointerIcon(x, y);
7006 }
7007 }
7008
7009 @Override
Dianne Hackborn9a230e02011-10-06 11:51:27 -07007010 public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
7011 int localValue, int localChanges) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07007012 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007013 if (viewAncestor != null) {
Dianne Hackborn9a230e02011-10-06 11:51:27 -07007014 viewAncestor.dispatchSystemUiVisibilityChanged(seq, globalVisibility,
7015 localValue, localChanges);
Joe Onorato664644d2011-01-23 17:53:23 -08007016 }
7017 }
Dianne Hackborn12d3a942012-04-27 14:16:30 -07007018
Igor Murashkina86ab6402013-08-30 12:58:36 -07007019 @Override
Craig Mautner9c795042014-10-28 19:59:59 -07007020 public void dispatchWindowShown() {
7021 final ViewRootImpl viewAncestor = mViewAncestor.get();
7022 if (viewAncestor != null) {
7023 viewAncestor.dispatchWindowShown();
7024 }
7025 }
Clara Bayarri75e09792015-07-29 16:20:40 +01007026
7027 @Override
7028 public void requestAppKeyboardShortcuts(IResultReceiver receiver) {
7029 ViewRootImpl viewAncestor = mViewAncestor.get();
7030 if (viewAncestor != null) {
7031 viewAncestor.dispatchRequestKeyboardShortcuts(receiver);
7032 }
7033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007034 }
7035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007036 public static final class CalledFromWrongThreadException extends AndroidRuntimeException {
7037 public CalledFromWrongThreadException(String msg) {
7038 super(msg);
7039 }
7040 }
7041
Alan Viverettebea0c7da2015-09-01 16:00:20 -04007042 static HandlerActionQueue getRunQueue() {
7043 HandlerActionQueue rq = sRunQueues.get();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007044 if (rq != null) {
7045 return rq;
7046 }
Alan Viverettebea0c7da2015-09-01 16:00:20 -04007047 rq = new HandlerActionQueue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007048 sRunQueues.set(rq);
7049 return rq;
7050 }
Romain Guy8506ab42009-06-11 17:35:47 -07007051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007052 /**
Skuhneb8160872015-09-22 09:51:39 -07007053 * Start a drag resizing which will inform all listeners that a window resize is taking place.
7054 */
Jorim Jaggi9511b0f2016-01-29 19:12:44 -08007055 private void startDragResizing(Rect initialBounds, boolean fullscreen, Rect systemInsets,
7056 Rect stableInsets) {
Skuhneb8160872015-09-22 09:51:39 -07007057 if (!mDragResizing) {
7058 mDragResizing = true;
Chong Zhangdcee1de2015-10-06 10:26:00 -07007059 synchronized (mWindowCallbacks) {
7060 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
Jorim Jaggi9511b0f2016-01-29 19:12:44 -08007061 mWindowCallbacks.get(i).onWindowDragResizeStart(initialBounds, fullscreen,
7062 systemInsets, stableInsets);
Skuhneb8160872015-09-22 09:51:39 -07007063 }
7064 }
7065 mFullRedrawNeeded = true;
7066 }
7067 }
7068
7069 /**
7070 * End a drag resize which will inform all listeners that a window resize has ended.
7071 */
7072 private void endDragResizing() {
7073 if (mDragResizing) {
7074 mDragResizing = false;
Chong Zhangdcee1de2015-10-06 10:26:00 -07007075 synchronized (mWindowCallbacks) {
7076 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
7077 mWindowCallbacks.get(i).onWindowDragResizeEnd();
Skuhneb8160872015-09-22 09:51:39 -07007078 }
7079 }
7080 mFullRedrawNeeded = true;
7081 }
7082 }
7083
Chong Zhang8dbd9ad2015-10-09 10:06:11 -07007084 private boolean updateContentDrawBounds() {
7085 boolean updated = false;
7086 synchronized (mWindowCallbacks) {
7087 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
7088 updated |= mWindowCallbacks.get(i).onContentDrawn(
7089 mWindowAttributes.surfaceInsets.left,
7090 mWindowAttributes.surfaceInsets.top,
7091 mWidth, mHeight);
7092 }
7093 }
7094 return updated | (mDragResizing && mReportNextDraw);
7095 }
7096
7097 private void requestDrawWindow() {
7098 if (mReportNextDraw) {
7099 mWindowDrawCountDown = new CountDownLatch(mWindowCallbacks.size());
7100 }
7101 synchronized (mWindowCallbacks) {
7102 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
7103 mWindowCallbacks.get(i).onRequestDraw(mReportNextDraw);
7104 }
7105 }
7106 }
7107
Skuhneb8160872015-09-22 09:51:39 -07007108 /**
Jorim Jaggi4846ee32016-01-07 17:39:12 +01007109 * Tells this instance that its corresponding activity has just relaunched. In this case, we
7110 * need to force a relayout of the window to make sure we get the correct bounds from window
7111 * manager.
7112 */
7113 public void reportActivityRelaunched() {
7114 mActivityRelaunched = true;
7115 }
7116
7117 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007118 * Class for managing the accessibility interaction connection
7119 * based on the global accessibility state.
7120 */
7121 final class AccessibilityInteractionConnectionManager
7122 implements AccessibilityStateChangeListener {
Igor Murashkina86ab6402013-08-30 12:58:36 -07007123 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007124 public void onAccessibilityStateChanged(boolean enabled) {
7125 if (enabled) {
7126 ensureConnection();
Chris Craikcce47eb2014-07-16 15:12:15 -07007127 if (mAttachInfo.mHasWindowFocus) {
Svetoslav Ganov0d04e242012-02-21 13:46:36 -08007128 mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
7129 View focusedView = mView.findFocus();
7130 if (focusedView != null && focusedView != mView) {
7131 focusedView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
7132 }
7133 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007134 } else {
7135 ensureNoConnection();
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07007136 mHandler.obtainMessage(MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST).sendToTarget();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007137 }
7138 }
7139
7140 public void ensureConnection() {
Chris Craikcce47eb2014-07-16 15:12:15 -07007141 final boolean registered =
Svetoslav8e3feb12014-02-24 13:46:47 -08007142 mAttachInfo.mAccessibilityWindowId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
Chris Craikcce47eb2014-07-16 15:12:15 -07007143 if (!registered) {
7144 mAttachInfo.mAccessibilityWindowId =
Svetoslav Ganov0d04e242012-02-21 13:46:36 -08007145 mAccessibilityManager.addAccessibilityInteractionConnection(mWindow,
7146 new AccessibilityInteractionConnection(ViewRootImpl.this));
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007147 }
7148 }
7149
7150 public void ensureNoConnection() {
Svetoslav Ganov0d04e242012-02-21 13:46:36 -08007151 final boolean registered =
Svetoslav8e3feb12014-02-24 13:46:47 -08007152 mAttachInfo.mAccessibilityWindowId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007153 if (registered) {
Svetoslav8e3feb12014-02-24 13:46:47 -08007154 mAttachInfo.mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007155 mAccessibilityManager.removeAccessibilityInteractionConnection(mWindow);
7156 }
7157 }
7158 }
7159
Chris Craikcce47eb2014-07-16 15:12:15 -07007160 final class HighContrastTextManager implements HighTextContrastChangeListener {
7161 HighContrastTextManager() {
7162 mAttachInfo.mHighContrastText = mAccessibilityManager.isHighTextContrastEnabled();
7163 }
7164 @Override
7165 public void onHighTextContrastStateChanged(boolean enabled) {
7166 mAttachInfo.mHighContrastText = enabled;
7167
7168 // Destroy Displaylists so they can be recreated with high contrast recordings
7169 destroyHardwareResources();
Chris Craikd36a81f2014-07-17 10:16:51 -07007170
7171 // Schedule redraw, which will rerecord + redraw all text
7172 invalidate();
Chris Craikcce47eb2014-07-16 15:12:15 -07007173 }
7174 }
7175
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007176 /**
7177 * This class is an interface this ViewAncestor provides to the
7178 * AccessibilityManagerService to the latter can interact with
7179 * the view hierarchy in this ViewAncestor.
7180 */
Svetoslav Ganovaf5b4f42011-10-28 12:41:38 -07007181 static final class AccessibilityInteractionConnection
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007182 extends IAccessibilityInteractionConnection.Stub {
Svetoslav Ganov02107852011-10-03 17:06:56 -07007183 private final WeakReference<ViewRootImpl> mViewRootImpl;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007184
Svetoslav Ganovf79f4762011-10-28 15:40:32 -07007185 AccessibilityInteractionConnection(ViewRootImpl viewRootImpl) {
7186 mViewRootImpl = new WeakReference<ViewRootImpl>(viewRootImpl);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007187 }
7188
Svetoslav Ganov42138042012-03-20 11:51:39 -07007189 @Override
Svetoslav Ganov02107852011-10-03 17:06:56 -07007190 public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId,
Svetoslav9ae9ed22014-09-02 16:36:35 -07007191 Region interactiveRegion, int interactionId,
7192 IAccessibilityInteractionConnectionCallback callback, int flags,
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -07007193 int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07007194 ViewRootImpl viewRootImpl = mViewRootImpl.get();
7195 if (viewRootImpl != null && viewRootImpl.mView != null) {
Svetoslav Ganovaf5b4f42011-10-28 12:41:38 -07007196 viewRootImpl.getAccessibilityInteractionController()
Svetoslav Ganov02107852011-10-03 17:06:56 -07007197 .findAccessibilityNodeInfoByAccessibilityIdClientThread(accessibilityNodeId,
Svetoslav9ae9ed22014-09-02 16:36:35 -07007198 interactiveRegion, interactionId, callback, flags, interrogatingPid,
7199 interrogatingTid, spec);
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007200 } else {
7201 // We cannot make the call and notify the caller so it does not wait.
7202 try {
7203 callback.setFindAccessibilityNodeInfosResult(null, interactionId);
7204 } catch (RemoteException re) {
7205 /* best effort - ignore */
7206 }
Svetoslav Ganov601ad802011-06-09 14:47:38 -07007207 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007208 }
7209
Svetoslav Ganov42138042012-03-20 11:51:39 -07007210 @Override
Svetoslav Ganov02107852011-10-03 17:06:56 -07007211 public void performAccessibilityAction(long accessibilityNodeId, int action,
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07007212 Bundle arguments, int interactionId,
7213 IAccessibilityInteractionConnectionCallback callback, int flags,
Svet Ganov7498efd2014-09-03 21:33:00 -07007214 int interrogatingPid, long interrogatingTid) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07007215 ViewRootImpl viewRootImpl = mViewRootImpl.get();
7216 if (viewRootImpl != null && viewRootImpl.mView != null) {
Svetoslav Ganovaf5b4f42011-10-28 12:41:38 -07007217 viewRootImpl.getAccessibilityInteractionController()
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07007218 .performAccessibilityActionClientThread(accessibilityNodeId, action, arguments,
Svet Ganov7498efd2014-09-03 21:33:00 -07007219 interactionId, callback, flags, interrogatingPid, interrogatingTid);
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007220 } else {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007221 // We cannot make the call and notify the caller so it does not wait.
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007222 try {
7223 callback.setPerformAccessibilityActionResult(false, interactionId);
7224 } catch (RemoteException re) {
7225 /* best effort - ignore */
7226 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007227 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007228 }
7229
Svetoslav Ganov42138042012-03-20 11:51:39 -07007230 @Override
Svetoslav Ganov80943d82013-01-02 10:25:37 -08007231 public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId,
Svetoslav9ae9ed22014-09-02 16:36:35 -07007232 String viewId, Region interactiveRegion, int interactionId,
Svetoslav Ganov80943d82013-01-02 10:25:37 -08007233 IAccessibilityInteractionConnectionCallback callback, int flags,
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -07007234 int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07007235 ViewRootImpl viewRootImpl = mViewRootImpl.get();
7236 if (viewRootImpl != null && viewRootImpl.mView != null) {
Svetoslav Ganovaf5b4f42011-10-28 12:41:38 -07007237 viewRootImpl.getAccessibilityInteractionController()
Svetoslav Ganov80943d82013-01-02 10:25:37 -08007238 .findAccessibilityNodeInfosByViewIdClientThread(accessibilityNodeId,
Svetoslav9ae9ed22014-09-02 16:36:35 -07007239 viewId, interactiveRegion, interactionId, callback, flags,
7240 interrogatingPid, interrogatingTid, spec);
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007241 } else {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007242 // We cannot make the call and notify the caller so it does not wait.
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007243 try {
7244 callback.setFindAccessibilityNodeInfoResult(null, interactionId);
7245 } catch (RemoteException re) {
7246 /* best effort - ignore */
7247 }
7248 }
7249 }
7250
Svetoslav Ganov42138042012-03-20 11:51:39 -07007251 @Override
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007252 public void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text,
Svetoslav9ae9ed22014-09-02 16:36:35 -07007253 Region interactiveRegion, int interactionId,
7254 IAccessibilityInteractionConnectionCallback callback, int flags,
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -07007255 int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007256 ViewRootImpl viewRootImpl = mViewRootImpl.get();
7257 if (viewRootImpl != null && viewRootImpl.mView != null) {
7258 viewRootImpl.getAccessibilityInteractionController()
7259 .findAccessibilityNodeInfosByTextClientThread(accessibilityNodeId, text,
Svetoslav9ae9ed22014-09-02 16:36:35 -07007260 interactiveRegion, interactionId, callback, flags, interrogatingPid,
7261 interrogatingTid, spec);
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007262 } else {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007263 // We cannot make the call and notify the caller so it does not wait.
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007264 try {
7265 callback.setFindAccessibilityNodeInfosResult(null, interactionId);
7266 } catch (RemoteException re) {
7267 /* best effort - ignore */
7268 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007269 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007270 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007271
Svetoslav Ganov42138042012-03-20 11:51:39 -07007272 @Override
Svetoslav9ae9ed22014-09-02 16:36:35 -07007273 public void findFocus(long accessibilityNodeId, int focusType, Region interactiveRegion,
7274 int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -07007275 int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007276 ViewRootImpl viewRootImpl = mViewRootImpl.get();
7277 if (viewRootImpl != null && viewRootImpl.mView != null) {
7278 viewRootImpl.getAccessibilityInteractionController()
Svetoslav9ae9ed22014-09-02 16:36:35 -07007279 .findFocusClientThread(accessibilityNodeId, focusType, interactiveRegion,
7280 interactionId, callback, flags, interrogatingPid, interrogatingTid,
7281 spec);
Svetoslav Ganov8bd69612011-08-23 13:40:30 -07007282 } else {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007283 // We cannot make the call and notify the caller so it does not wait.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007284 try {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007285 callback.setFindAccessibilityNodeInfoResult(null, interactionId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007286 } catch (RemoteException re) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007287 /* best effort - ignore */
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007288 }
7289 }
7290 }
7291
Svetoslav Ganov42138042012-03-20 11:51:39 -07007292 @Override
Svetoslav9ae9ed22014-09-02 16:36:35 -07007293 public void focusSearch(long accessibilityNodeId, int direction, Region interactiveRegion,
7294 int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -07007295 int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007296 ViewRootImpl viewRootImpl = mViewRootImpl.get();
7297 if (viewRootImpl != null && viewRootImpl.mView != null) {
7298 viewRootImpl.getAccessibilityInteractionController()
Svetoslav9ae9ed22014-09-02 16:36:35 -07007299 .focusSearchClientThread(accessibilityNodeId, direction, interactiveRegion,
7300 interactionId, callback, flags, interrogatingPid, interrogatingTid,
7301 spec);
Svetoslav Ganov8bd69612011-08-23 13:40:30 -07007302 } else {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007303 // We cannot make the call and notify the caller so it does not wait.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007304 try {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007305 callback.setFindAccessibilityNodeInfoResult(null, interactionId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007306 } catch (RemoteException re) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007307 /* best effort - ignore */
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007308 }
7309 }
7310 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007311 }
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07007312
Svetoslav Ganova0156172011-06-26 17:55:44 -07007313 private class SendWindowContentChangedAccessibilityEvent implements Runnable {
Alan Viverette77e9a282013-09-12 17:16:09 -07007314 private int mChangeTypes = 0;
7315
Svetoslav Ganov42138042012-03-20 11:51:39 -07007316 public View mSource;
Svetoslav6254f482013-06-04 17:22:14 -07007317 public long mLastEventTimeMillis;
Svetoslav Ganova0156172011-06-26 17:55:44 -07007318
Igor Murashkina86ab6402013-08-30 12:58:36 -07007319 @Override
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07007320 public void run() {
Svetoslav8d820ecf2013-07-15 17:12:41 -07007321 // The accessibility may be turned off while we were waiting so check again.
7322 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
7323 mLastEventTimeMillis = SystemClock.uptimeMillis();
7324 AccessibilityEvent event = AccessibilityEvent.obtain();
7325 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
Alan Viverette77e9a282013-09-12 17:16:09 -07007326 event.setContentChangeTypes(mChangeTypes);
Svetoslav8d820ecf2013-07-15 17:12:41 -07007327 mSource.sendAccessibilityEventUnchecked(event);
7328 } else {
7329 mLastEventTimeMillis = 0;
7330 }
7331 // In any case reset to initial state.
Svetoslav6254f482013-06-04 17:22:14 -07007332 mSource.resetSubtreeAccessibilityStateChanged();
7333 mSource = null;
Alan Viverette77e9a282013-09-12 17:16:09 -07007334 mChangeTypes = 0;
Svetoslav6254f482013-06-04 17:22:14 -07007335 }
7336
Alan Viverette77e9a282013-09-12 17:16:09 -07007337 public void runOrPost(View source, int changeType) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007338 if (mSource != null) {
Svetoslav9dafebb2013-06-18 16:29:25 -07007339 // If there is no common predecessor, then mSource points to
7340 // a removed view, hence in this case always prefer the source.
7341 View predecessor = getCommonPredecessor(mSource, source);
7342 mSource = (predecessor != null) ? predecessor : source;
Alan Viverette77e9a282013-09-12 17:16:09 -07007343 mChangeTypes |= changeType;
Svetoslav6254f482013-06-04 17:22:14 -07007344 return;
7345 }
7346 mSource = source;
Alan Viverette77e9a282013-09-12 17:16:09 -07007347 mChangeTypes = changeType;
Svetoslav6254f482013-06-04 17:22:14 -07007348 final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
7349 final long minEventIntevalMillis =
7350 ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
7351 if (timeSinceLastMillis >= minEventIntevalMillis) {
Svetoslav9dafebb2013-06-18 16:29:25 -07007352 mSource.removeCallbacks(this);
Svetoslav6254f482013-06-04 17:22:14 -07007353 run();
7354 } else {
7355 mSource.postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007356 }
7357 }
7358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007359}