blob: 6d5037ab1fc5a99f5abc5fbf8c3deb8b2945b2f2 [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
Andrii Kulian44607962017-03-16 11:06:24 -070019import static android.view.Display.INVALID_DISPLAY;
Chris Craik9de95db2017-01-18 17:59:23 -080020import static android.view.View.PFLAG_DRAW_ANIMATION;
Jorim Jaggic39c7b02016-03-24 10:47:07 -070021import static android.view.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER;
22import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM;
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -080023import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
Chong Zhangf6525ce2016-01-14 17:09:56 -080024import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
25import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
26import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -080027
Romain Guy6b7bd242010-10-06 19:49:23 -070028import android.Manifest;
Chet Haasecca2c982011-05-20 14:34:18 -070029import android.animation.LayoutTransition;
Adam Lesinski4ece3d62016-06-16 18:05:41 -070030import android.annotation.NonNull;
Sudheer Shankadc589ac2016-11-10 15:30:17 -080031import android.app.ActivityManager;
Andrii Kulian44607962017-03-16 11:06:24 -070032import android.app.ActivityThread;
Adam Lesinski4ece3d62016-06-16 18:05:41 -070033import android.app.ResourcesManager;
Vadim Trysheva61efa42016-09-28 15:15:52 -070034import android.content.ClipData;
Romain Guy6b7bd242010-10-06 19:49:23 -070035import android.content.ClipDescription;
Romain Guy6b7bd242010-10-06 19:49:23 -070036import android.content.Context;
37import android.content.pm.PackageManager;
38import android.content.res.CompatibilityInfo;
39import android.content.res.Configuration;
40import android.content.res.Resources;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.graphics.Canvas;
Alan Viverettefed3f722013-11-14 14:48:20 -080042import android.graphics.Matrix;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.graphics.PixelFormat;
Christopher Tate2c095f32010-10-04 14:13:40 -070044import android.graphics.Point;
Christopher Tatea53146c2010-09-07 11:57:52 -070045import android.graphics.PointF;
Romain Guy6b7bd242010-10-06 19:49:23 -070046import android.graphics.PorterDuff;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.graphics.Rect;
48import android.graphics.Region;
Doris Liu718cd3e2016-05-17 16:50:31 -070049import android.graphics.drawable.AnimatedVectorDrawable;
Svetoslav Ganov42138042012-03-20 11:51:39 -070050import android.graphics.drawable.Drawable;
Jeff Brownd912e1f2014-04-11 18:46:22 -070051import android.hardware.display.DisplayManager;
52import android.hardware.display.DisplayManager.DisplayListener;
Jun Mukai347e5d42015-12-03 01:13:31 -080053import android.hardware.input.InputManager;
Romain Guy6b7bd242010-10-06 19:49:23 -070054import android.media.AudioManager;
55import android.os.Binder;
Michael Wright5bd69e62015-05-14 14:48:08 +010056import android.os.Build;
Romain Guy6b7bd242010-10-06 19:49:23 -070057import android.os.Bundle;
58import android.os.Debug;
59import android.os.Handler;
Romain Guy6b7bd242010-10-06 19:49:23 -070060import android.os.Looper;
61import android.os.Message;
62import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.os.Process;
Romain Guy6b7bd242010-10-06 19:49:23 -070064import android.os.RemoteException;
Romain Guy6b7bd242010-10-06 19:49:23 -070065import android.os.SystemClock;
Romain Guy59a12ca2011-06-09 17:48:21 -070066import android.os.SystemProperties;
Jeff Brown481c1572012-03-09 14:41:15 -080067import android.os.Trace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import android.util.AndroidRuntimeException;
Mitsuru Oshima9189cab2009-06-03 11:19:12 -070069import android.util.DisplayMetrics;
Romain Guy6b7bd242010-10-06 19:49:23 -070070import android.util.Log;
Andrii Kulian44607962017-03-16 11:06:24 -070071import android.util.MergedConfiguration;
Chet Haase949dbf72010-08-11 18:41:06 -070072import android.util.Slog;
John Reckba6adf62015-02-19 14:36:50 -080073import android.util.TimeUtils;
Dianne Hackborn711e62a2010-11-29 16:38:22 -080074import android.util.TypedValue;
John Reck44fd8d22014-02-26 11:00:11 -080075import android.view.Surface.OutOfResourcesException;
Jeff Browna175a5b2012-02-15 19:18:31 -080076import android.view.View.AttachInfo;
Evan Rosky57223312017-02-08 14:42:45 -080077import android.view.View.FocusDirection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import android.view.View.MeasureSpec;
Yohei Yukawa22dac1c2017-02-12 16:54:16 -080079import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
svetoslavganov75986cf2009-05-14 22:28:01 -070080import android.view.accessibility.AccessibilityEvent;
81import android.view.accessibility.AccessibilityManager;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070082import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
Chris Craikcce47eb2014-07-16 15:12:15 -070083import android.view.accessibility.AccessibilityManager.HighTextContrastChangeListener;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070084import android.view.accessibility.AccessibilityNodeInfo;
Alan Viverette25acc7e2015-05-19 11:32:08 -070085import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
Svetoslav Ganov02107852011-10-03 17:06:56 -070086import android.view.accessibility.AccessibilityNodeProvider;
Phil Weaverf00cd142017-03-03 13:44:00 -080087import android.view.accessibility.AccessibilityWindowInfo;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070088import android.view.accessibility.IAccessibilityInteractionConnection;
89import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
Dianne Hackborn0f761d62010-11-30 22:06:10 -080090import android.view.animation.AccelerateDecelerateInterpolator;
91import android.view.animation.Interpolator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import android.view.inputmethod.InputMethodManager;
93import android.widget.Scroller;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070094
Svetoslav Ganov42138042012-03-20 11:51:39 -070095import com.android.internal.R;
Jorim Jaggi16b63192016-03-25 18:32:19 -070096import com.android.internal.annotations.GuardedBy;
Clara Bayarri75e09792015-07-29 16:20:40 +010097import com.android.internal.os.IResultReceiver;
Svetoslav Ganov758143e2012-08-06 16:40:27 -070098import com.android.internal.os.SomeArgs;
Adam Powell6711f3b2015-05-06 15:57:09 -070099import com.android.internal.policy.PhoneFallbackEventHandler;
Romain Guy6b7bd242010-10-06 19:49:23 -0700100import com.android.internal.view.BaseSurfaceHolder;
Romain Guy6b7bd242010-10-06 19:49:23 -0700101import com.android.internal.view.RootViewSurfaceTaker;
Robert Carr25cfa132016-11-16 13:24:09 -0800102import com.android.internal.view.SurfaceCallbackHelper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103
Jeff Brown5182c782013-10-15 20:31:52 -0700104import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import java.io.IOException;
106import java.io.OutputStream;
Jeff Brown5182c782013-10-15 20:31:52 -0700107import java.io.PrintWriter;
Romain Guy6b7bd242010-10-06 19:49:23 -0700108import java.lang.ref.WeakReference;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import java.util.ArrayList;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700110import java.util.HashSet;
Jorim Jaggic39c7b02016-03-24 10:47:07 -0700111import java.util.concurrent.CountDownLatch;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113/**
114 * The top of a view hierarchy, implementing the needed protocol between View
115 * and the WindowManager. This is for the most part an internal implementation
Jeff Brown98365d72012-08-19 20:30:52 -0700116 * detail of {@link WindowManagerGlobal}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 *
118 * {@hide}
119 */
Romain Guy812ccbe2010-06-01 14:07:24 -0700120@SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"})
Jeff Browna175a5b2012-02-15 19:18:31 -0800121public final class ViewRootImpl implements ViewParent,
Stan Iliev45faba52016-06-28 13:33:15 -0400122 View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
Dianne Hackborn70a3f672011-08-08 14:32:41 -0700123 private static final String TAG = "ViewRootImpl";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124 private static final boolean DBG = false;
Romain Guy812ccbe2010-06-01 14:07:24 -0700125 private static final boolean LOCAL_LOGV = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 /** @noinspection PointlessBooleanExpression*/
127 private static final boolean DEBUG_DRAW = false || LOCAL_LOGV;
128 private static final boolean DEBUG_LAYOUT = false || LOCAL_LOGV;
Dianne Hackborn711e62a2010-11-29 16:38:22 -0800129 private static final boolean DEBUG_DIALOG = false || LOCAL_LOGV;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 private static final boolean DEBUG_INPUT_RESIZE = false || LOCAL_LOGV;
131 private static final boolean DEBUG_ORIENTATION = false || LOCAL_LOGV;
132 private static final boolean DEBUG_TRACKBALL = false || LOCAL_LOGV;
133 private static final boolean DEBUG_IMF = false || LOCAL_LOGV;
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700134 private static final boolean DEBUG_CONFIGURATION = false || LOCAL_LOGV;
Chet Haase2f2022a2011-10-11 06:41:59 -0700135 private static final boolean DEBUG_FPS = false;
Michael Wright06a79252014-05-05 17:45:29 -0700136 private static final boolean DEBUG_INPUT_STAGES = false || LOCAL_LOGV;
Chong Zhang44aabe42016-05-10 11:20:14 -0700137 private static final boolean DEBUG_KEEP_SCREEN_ON = false || LOCAL_LOGV;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138
Romain Guy59a12ca2011-06-09 17:48:21 -0700139 /**
Skuhneb8160872015-09-22 09:51:39 -0700140 * Set to false if we do not want to use the multi threaded renderer. Note that by disabling
141 * this, WindowCallbacks will not fire.
142 */
143 private static final boolean USE_MT_RENDERER = true;
144
145 /**
Romain Guy59a12ca2011-06-09 17:48:21 -0700146 * Set this system property to true to force the view hierarchy to render
147 * at 60 Hz. This can be used to measure the potential framerate.
148 */
Romain Guye9bc11f2013-05-23 12:47:26 -0700149 private static final String PROPERTY_PROFILE_RENDERING = "viewroot.profile_rendering";
Michael Chan53071d62009-05-13 17:29:48 -0700150
Griff Hazena0938022015-03-13 10:01:41 -0700151 // properties used by emulator to determine display shape
Griff Hazena0938022015-03-13 10:01:41 -0700152 public static final String PROPERTY_EMULATOR_WIN_OUTSET_BOTTOM_PX =
153 "ro.emu.win_outset_bottom_px";
Michael Kolb437d3132014-06-20 13:28:44 -0700154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 /**
156 * Maximum time we allow the user to roll the trackball enough to generate
157 * a key event, before resetting the counters.
158 */
159 static final int MAX_TRACKBALL_DELAY = 250;
160
Alan Viverettebea0c7da2015-09-01 16:00:20 -0400161 static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162
Skuhneb8160872015-09-22 09:51:39 -0700163 static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList();
Dianne Hackborn2a9094d2010-02-03 19:20:09 -0800164 static boolean sFirstDrawComplete = false;
Craig Mautner8f303ad2013-06-14 11:32:22 -0700165
Andrii Kulian44607962017-03-16 11:06:24 -0700166 /**
167 * Callback for notifying about global configuration changes.
168 */
169 public interface ConfigChangedCallback {
170
171 /** Notifies about global config change. */
172 void onConfigurationChanged(Configuration globalConfig);
173 }
174
175 private static final ArrayList<ConfigChangedCallback> sConfigCallbacks = new ArrayList<>();
176
177 /**
178 * Callback for notifying activities about override configuration changes.
179 */
180 public interface ActivityConfigCallback {
181
182 /**
183 * Notifies about override config change and/or move to different display.
184 * @param overrideConfig New override config to apply to activity.
185 * @param newDisplayId New display id, {@link Display#INVALID_DISPLAY} if not changed.
186 */
187 void onConfigurationChanged(Configuration overrideConfig, int newDisplayId);
188 }
189
190 /**
191 * Callback used to notify corresponding activity about override configuration change and make
192 * sure that all resources are set correctly before updating the ViewRootImpl's internal state.
193 */
194 private ActivityConfigCallback mActivityConfigCallback;
195
196 /**
197 * Used when configuration change first updates the config of corresponding activity.
198 * In that case we receive a call back from {@link ActivityThread} and this flag is used to
199 * preserve the initial value.
200 *
201 * @see #performConfigurationChange(Configuration, Configuration, boolean, int)
202 */
203 private boolean mForceNextConfigUpdate;
Romain Guy59a12ca2011-06-09 17:48:21 -0700204
Jorim Jaggi16b63192016-03-25 18:32:19 -0700205 /**
Evan Rosky37df2db2017-01-24 16:35:52 -0800206 * Signals that compatibility booleans have been initialized according to
207 * target SDK versions.
208 */
209 private static boolean sCompatibilityDone = false;
210
211 /**
212 * Always assign focus if a focusable View is available.
213 */
214 private static boolean sAlwaysAssignFocus;
215
216 /**
Jorim Jaggi16b63192016-03-25 18:32:19 -0700217 * This list must only be modified by the main thread, so a lock is only needed when changing
218 * the list or when accessing the list from a non-main thread.
219 */
220 @GuardedBy("mWindowCallbacks")
221 final ArrayList<WindowCallbacks> mWindowCallbacks = new ArrayList<>();
Jeff Brownf9e989d2013-04-04 23:04:03 -0700222 final Context mContext;
Jeff Brown98365d72012-08-19 20:30:52 -0700223 final IWindowSession mWindowSession;
Adam Lesinski4ece3d62016-06-16 18:05:41 -0700224 @NonNull Display mDisplay;
Jeff Brownd912e1f2014-04-11 18:46:22 -0700225 final DisplayManager mDisplayManager;
Dianne Hackbornc2293022013-02-06 23:14:49 -0800226 final String mBasePackageName;
Jeff Brown98365d72012-08-19 20:30:52 -0700227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 final int[] mTmpLocation = new int[2];
Romain Guy8506ab42009-06-11 17:35:47 -0700229
Dianne Hackborn711e62a2010-11-29 16:38:22 -0800230 final TypedValue mTmpValue = new TypedValue();
Jeff Brownf9e989d2013-04-04 23:04:03 -0700231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 final Thread mThread;
233
234 final WindowLeaked mLocation;
235
236 final WindowManager.LayoutParams mWindowAttributes = new WindowManager.LayoutParams();
237
238 final W mWindow;
239
Dianne Hackborn180c4842011-09-13 12:39:25 -0700240 final int mTargetSdkVersion;
241
Dianne Hackborn9a230e02011-10-06 11:51:27 -0700242 int mSeq;
243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 View mView;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700245
246 View mAccessibilityFocusedHost;
247 AccessibilityNodeInfo mAccessibilityFocusedVirtualView;
248
Vladislav Kaznacheev3787de12016-12-21 10:36:35 -0800249 // True if the window currently has pointer capture enabled.
250 boolean mPointerCapture;
Jun Mukai347e5d42015-12-03 01:13:31 -0800251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 int mViewVisibility;
253 boolean mAppVisible = true;
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -0800254 // For recents to freeform transition we need to keep drawing after the app receives information
255 // that it became invisible. This will ignore that information and depend on the decor view
256 // visibility to control drawing. The decor view visibility will get adjusted when the app get
257 // stopped and that's when the app will stop drawing further frames.
258 private boolean mForceDecorViewVisibility = false;
Dianne Hackborn180c4842011-09-13 12:39:25 -0700259 int mOrigWindowType = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260
Alan Viverette64bf97a2015-09-18 16:42:00 -0400261 /** Whether the window had focus during the most recent traversal. */
262 boolean mHadWindowFocus;
263
264 /**
265 * Whether the window lost focus during a previous traversal and has not
266 * yet gained it back. Used to determine whether a WINDOW_STATE_CHANGE
267 * accessibility events should be sent during traversal.
268 */
269 boolean mLostWindowFocus;
270
Dianne Hackbornce418e62011-03-01 14:31:38 -0800271 // Set to true if the owner of this window is in the stopped state,
272 // so the window should no longer be active.
273 boolean mStopped = false;
Craig Mautner8f303ad2013-06-14 11:32:22 -0700274
Daniel Koulomzin087ae472015-12-16 17:52:25 -0500275 // Set to true if the owner of this window is in ambient mode,
276 // which means it won't receive input events.
277 boolean mIsAmbientMode = false;
278
George Mount41725de2015-04-09 08:23:05 -0700279 // Set to true to stop input during an Activity Transition.
280 boolean mPausedForTransition = false;
281
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700282 boolean mLastInCompatMode = false;
283
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700284 SurfaceHolder.Callback2 mSurfaceHolderCallback;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700285 BaseSurfaceHolder mSurfaceHolder;
286 boolean mIsCreating;
287 boolean mDrawingAllowed;
Craig Mautner8f303ad2013-06-14 11:32:22 -0700288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 final Region mTransparentRegion;
290 final Region mPreviousTransparentRegion;
291
292 int mWidth;
293 int mHeight;
Romain Guy7d7b5492011-01-24 16:33:45 -0800294 Rect mDirty;
Chris Craik3f06c6d2017-01-09 18:19:48 +0000295 public boolean mIsAnimating;
Romain Guy8506ab42009-06-11 17:35:47 -0700296
Chong Zhang0275e392015-09-17 10:41:44 -0700297 private boolean mDragResizing;
Jorim Jaggic39c7b02016-03-24 10:47:07 -0700298 private boolean mInvalidateRootRequested;
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100299 private int mResizeMode;
Chong Zhang0275e392015-09-17 10:41:44 -0700300 private int mCanvasOffsetX;
301 private int mCanvasOffsetY;
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100302 private boolean mActivityRelaunched;
Chong Zhang0275e392015-09-17 10:41:44 -0700303
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700304 CompatibilityInfo.Translator mTranslator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305
306 final View.AttachInfo mAttachInfo;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700307 InputChannel mInputChannel;
Dianne Hackborn1e4b9f32010-06-23 14:10:57 -0700308 InputQueue.Callback mInputQueueCallback;
309 InputQueue mInputQueue;
Joe Onorato86f67862010-11-05 18:57:34 -0700310 FallbackEventHandler mFallbackEventHandler;
Jeff Brown96e942d2011-11-30 19:55:01 -0800311 Choreographer mChoreographer;
Igor Murashkina86ab6402013-08-30 12:58:36 -0700312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 final Rect mTempRect; // used in the transaction to not thrash the heap.
314 final Rect mVisRect; // used to retrieve visible rect of focused view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315
Chris Craik3f06c6d2017-01-09 18:19:48 +0000316 public boolean mTraversalScheduled;
Jeff Browne0dbd002012-02-15 19:34:58 -0800317 int mTraversalBarrier;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 boolean mWillDrawSoon;
Craig Mautnerdf2390a2012-08-29 20:59:22 -0700319 /** Set to true while in performTraversals for detecting when die(true) is called from internal
320 * callbacks such as onMeasure, onPreDraw, onDraw and deferring doDie() until later. */
321 boolean mIsInTraversal;
Adrian Roosfa104232014-06-20 16:10:14 -0700322 boolean mApplyInsetsRequested;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323 boolean mLayoutRequested;
324 boolean mFirst;
325 boolean mReportNextDraw;
326 boolean mFullRedrawNeeded;
327 boolean mNewSurfaceNeeded;
328 boolean mHasHadWindowFocus;
329 boolean mLastWasImTarget;
Jorim Jaggia4a58ef2016-01-27 02:10:08 -0800330 boolean mForceNextWindowRelayout;
Chong Zhang8dbd9ad2015-10-09 10:06:11 -0700331 CountDownLatch mWindowDrawCountDown;
Jorim Jaggi827e0fa2015-05-07 11:41:41 -0700332
Romain Guy1f59e5c2012-05-06 14:11:16 -0700333 boolean mIsDrawing;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700334 int mLastSystemUiVisibility;
Dianne Hackborn9d090892012-06-11 18:35:41 -0700335 int mClientWindowLayoutFlags;
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800336 boolean mLastOverscanRequested;
Jeff Brown4952dfd2011-11-30 19:23:22 -0800337
338 // Pool of queued input events.
339 private static final int MAX_QUEUED_INPUT_EVENT_POOL_SIZE = 10;
340 private QueuedInputEvent mQueuedInputEventPool;
341 private int mQueuedInputEventPoolSize;
Jeff Brown4952dfd2011-11-30 19:23:22 -0800342
Michael Wrightc8a7e542013-03-20 17:58:33 -0700343 /* Input event queue.
Jeff Brownf9e989d2013-04-04 23:04:03 -0700344 * Pending input events are input events waiting to be delivered to the input stages
345 * and handled by the application.
Michael Wrightc8a7e542013-03-20 17:58:33 -0700346 */
347 QueuedInputEvent mPendingInputEventHead;
348 QueuedInputEvent mPendingInputEventTail;
Michael Wright95ae9422013-03-14 10:58:50 -0700349 int mPendingInputEventCount;
Jeff Brown96e942d2011-11-30 19:55:01 -0800350 boolean mProcessInputEventsScheduled;
Michael Wright9d744c72014-02-18 21:27:42 -0800351 boolean mUnbufferedInputDispatch;
Michael Wright95ae9422013-03-14 10:58:50 -0700352 String mPendingInputEventQueueLengthCounterName = "pq";
Jeff Brownf9e989d2013-04-04 23:04:03 -0700353
354 InputStage mFirstInputStage;
355 InputStage mFirstPostImeInputStage;
Michael Wright899d7052014-04-23 17:23:39 -0700356 InputStage mSyntheticInputStage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357
358 boolean mWindowAttributesChanged = false;
Romain Guyf21c9b02011-09-06 16:56:54 -0700359 int mWindowAttributesChangesFlag = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360
361 // These can be accessed by any thread, must be protected with a lock.
Mathias Agopian5583dc62009-07-09 16:28:11 -0700362 // Surface can never be reassigned or cleared (use Surface.clear()).
John Reckb13de072014-11-19 16:33:47 -0800363 final Surface mSurface = new Surface();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364
365 boolean mAdded;
366 boolean mAddedTouchMode;
367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 // These are accessed by multiple threads.
369 final Rect mWinFrame; // frame given by window manager.
370
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800371 final Rect mPendingOverscanInsets = new Rect();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 final Rect mPendingVisibleInsets = new Rect();
Adrian Roosfa104232014-06-20 16:10:14 -0700373 final Rect mPendingStableInsets = new Rect();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 final Rect mPendingContentInsets = new Rect();
Filip Gruszczynski2217f612015-05-26 11:32:08 -0700375 final Rect mPendingOutsets = new Rect();
Jorim Jaggia7262a82015-11-03 15:15:40 +0100376 final Rect mPendingBackDropFrame = new Rect();
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -0800377 boolean mPendingAlwaysConsumeNavBar;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
379 = new ViewTreeObserver.InternalInsetsInfo();
380
Adrian Roosfa104232014-06-20 16:10:14 -0700381 final Rect mDispatchContentInsets = new Rect();
382 final Rect mDispatchStableInsets = new Rect();
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700383
Filip Gruszczynski954289d2015-02-26 15:46:47 -0800384 private WindowInsets mLastWindowInsets;
385
Andrii Kulian44607962017-03-16 11:06:24 -0700386 /** Last applied configuration obtained from resources. */
387 private final Configuration mLastConfigurationFromResources = new Configuration();
388 /** Last configuration reported from WM or via {@link #MSG_UPDATE_CONFIGURATION}. */
389 private final MergedConfiguration mLastReportedMergedConfiguration = new MergedConfiguration();
390 /** Configurations waiting to be applied. */
391 private final MergedConfiguration mPendingMergedConfiguration = new MergedConfiguration();
Romain Guy59a12ca2011-06-09 17:48:21 -0700392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393 boolean mScrollMayChange;
Yohei Yukawa22dac1c2017-02-12 16:54:16 -0800394 @SoftInputModeFlags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395 int mSoftInputMode;
Svetoslav Ganov149567f2013-01-08 15:23:34 -0800396 WeakReference<View> mLastScrolledFocus;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 int mScrollY;
398 int mCurScrollY;
399 Scroller mScroller;
John Recke56e9df2014-02-21 15:45:10 -0800400 static final Interpolator mResizeInterpolator = new AccelerateDecelerateInterpolator();
Chet Haasecca2c982011-05-20 14:34:18 -0700401 private ArrayList<LayoutTransition> mPendingTransitions;
Romain Guy8506ab42009-06-11 17:35:47 -0700402
Romain Guy8506ab42009-06-11 17:35:47 -0700403 final ViewConfiguration mViewConfiguration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404
Christopher Tatea53146c2010-09-07 11:57:52 -0700405 /* Drag/drop */
406 ClipDescription mDragDescription;
407 View mCurrentDragView;
Christopher Tate7fb8b562011-01-20 13:46:41 -0800408 volatile Object mLocalDragState;
Christopher Tatea53146c2010-09-07 11:57:52 -0700409 final PointF mDragPoint = new PointF();
Christopher Tate2c095f32010-10-04 14:13:40 -0700410 final PointF mLastTouchPoint = new PointF();
Vladislav Kaznacheevba761122016-01-22 12:09:45 -0800411 int mLastTouchSource;
Igor Murashkina86ab6402013-08-30 12:58:36 -0700412
413 private boolean mProfileRendering;
Romain Guyd0750312012-11-29 11:34:43 -0800414 private Choreographer.FrameCallback mRenderProfiler;
415 private boolean mRenderProfilingEnabled;
Christopher Tatea53146c2010-09-07 11:57:52 -0700416
Chet Haase2f2022a2011-10-11 06:41:59 -0700417 // Variables to track frames per second, enabled via DEBUG_FPS flag
418 private long mFpsStartTime = -1;
419 private long mFpsPrevTime = -1;
420 private int mFpsNumFrames;
421
Michael Wrightf9d9ce772016-05-13 17:44:16 +0100422 private int mPointerIconType = PointerIcon.TYPE_NOT_SPECIFIED;
Jun Mukaid4eaef72015-10-30 15:54:33 -0700423 private PointerIcon mCustomPointerIcon = null;
Jun Mukai1db53972015-09-11 18:08:31 -0700424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425 /**
426 * see {@link #playSoundEffect(int)}
427 */
428 AudioManager mAudioManager;
429
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700430 final AccessibilityManager mAccessibilityManager;
431
Gilles Debunne5ac84422011-10-19 09:35:58 -0700432 AccessibilityInteractionController mAccessibilityInteractionController;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700433
434 AccessibilityInteractionConnectionManager mAccessibilityInteractionConnectionManager;
Chris Craikcce47eb2014-07-16 15:12:15 -0700435 HighContrastTextManager mHighContrastTextManager;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700436
Svetoslav Ganova0156172011-06-26 17:55:44 -0700437 SendWindowContentChangedAccessibilityEvent mSendWindowContentChangedAccessibilityEvent;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700438
Svetoslav Ganov42138042012-03-20 11:51:39 -0700439 HashSet<View> mTempHashSet;
Svetoslav Ganov79311c42012-01-17 20:24:26 -0800440
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700441 private final int mDensity;
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700442 private final int mNoncompatDensity;
Adam Powellb08013c2010-09-16 16:28:11 -0700443
Chet Haase97140572012-09-13 14:56:47 -0700444 private boolean mInLayout = false;
445 ArrayList<View> mLayoutRequesters = new ArrayList<View>();
446 boolean mHandlingLayoutInLayoutRequest = false;
447
Fabrice Di Megliob003e282012-10-17 17:20:19 -0700448 private int mViewLayoutDirectionInitial;
Chet Haase97140572012-09-13 14:56:47 -0700449
Craig Mautner8f303ad2013-06-14 11:32:22 -0700450 /** Set to true once doDie() has been called. */
451 private boolean mRemoved;
452
Stan Iliev45faba52016-06-28 13:33:15 -0400453 private boolean mNeedsRendererSetup;
Robert Carr1bccabf2016-04-28 13:27:08 -0700454
Jeff Brown21bc5c92011-02-28 18:27:14 -0800455 /**
456 * Consistency verifier for debugging purposes.
457 */
458 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
459 InputEventConsistencyVerifier.isInstrumentationEnabled() ?
460 new InputEventConsistencyVerifier(this, 0) : null;
461
Dianne Hackborn9a230e02011-10-06 11:51:27 -0700462 static final class SystemUiVisibilityInfo {
463 int seq;
464 int globalVisibility;
465 int localValue;
466 int localChanges;
467 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700468
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -0800469 private String mTag = TAG;
470
Jeff Brown98365d72012-08-19 20:30:52 -0700471 public ViewRootImpl(Context context, Display display) {
Jeff Brownf9e989d2013-04-04 23:04:03 -0700472 mContext = context;
473 mWindowSession = WindowManagerGlobal.getWindowSession();
Jeff Brown98365d72012-08-19 20:30:52 -0700474 mDisplay = display;
Dianne Hackbornc2293022013-02-06 23:14:49 -0800475 mBasePackageName = context.getBasePackageName();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 mThread = Thread.currentThread();
477 mLocation = new WindowLeaked(null);
478 mLocation.fillInStackTrace();
479 mWidth = -1;
480 mHeight = -1;
481 mDirty = new Rect();
482 mTempRect = new Rect();
483 mVisRect = new Rect();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 mWinFrame = new Rect();
Romain Guyfb8b7632010-08-23 21:05:08 -0700485 mWindow = new W(this);
Dianne Hackborn180c4842011-09-13 12:39:25 -0700486 mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487 mViewVisibility = View.GONE;
488 mTransparentRegion = new Region();
489 mPreviousTransparentRegion = new Region();
490 mFirst = true; // true for the first time the view is added
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491 mAdded = false;
John Reckd94094e2016-09-08 14:12:26 -0700492 mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this,
493 context);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700494 mAccessibilityManager = AccessibilityManager.getInstance(context);
495 mAccessibilityInteractionConnectionManager =
496 new AccessibilityInteractionConnectionManager();
Svetoslav Ganov00d0c142012-02-24 11:30:49 -0800497 mAccessibilityManager.addAccessibilityStateChangeListener(
498 mAccessibilityInteractionConnectionManager);
Chris Craikcce47eb2014-07-16 15:12:15 -0700499 mHighContrastTextManager = new HighContrastTextManager();
500 mAccessibilityManager.addHighTextContrastStateChangeListener(
501 mHighContrastTextManager);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 mViewConfiguration = ViewConfiguration.get(context);
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700503 mDensity = context.getResources().getDisplayMetrics().densityDpi;
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700504 mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
Jorim Jaggib10e33f2015-02-04 21:57:40 +0100505 mFallbackEventHandler = new PhoneFallbackEventHandler(context);
Jeff Brown96e942d2011-11-30 19:55:01 -0800506 mChoreographer = Choreographer.getInstance();
Jeff Brownd912e1f2014-04-11 18:46:22 -0700507 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
Evan Rosky37df2db2017-01-24 16:35:52 -0800508
509 if (!sCompatibilityDone) {
Evan Roskycfd6c852017-03-17 12:39:15 -0700510 sAlwaysAssignFocus = true;
Evan Rosky37df2db2017-01-24 16:35:52 -0800511
512 sCompatibilityDone = true;
513 }
514
Dianne Hackborna53de062012-05-08 18:53:51 -0700515 loadSystemProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800516 }
517
Dianne Hackborn2a9094d2010-02-03 19:20:09 -0800518 public static void addFirstDrawHandler(Runnable callback) {
519 synchronized (sFirstDrawHandlers) {
520 if (!sFirstDrawComplete) {
521 sFirstDrawHandlers.add(callback);
522 }
523 }
524 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700525
Andrii Kulian44607962017-03-16 11:06:24 -0700526 /** Add static config callback to be notified about global config changes. */
527 public static void addConfigCallback(ConfigChangedCallback callback) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800528 synchronized (sConfigCallbacks) {
529 sConfigCallbacks.add(callback);
530 }
531 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700532
Andrii Kulian44607962017-03-16 11:06:24 -0700533 /** Add activity config callback to be notified about override config changes. */
534 public void setActivityConfigCallback(ActivityConfigCallback callback) {
535 mActivityConfigCallback = callback;
536 }
537
Chong Zhangdcee1de2015-10-06 10:26:00 -0700538 public void addWindowCallbacks(WindowCallbacks callback) {
Skuhneb8160872015-09-22 09:51:39 -0700539 if (USE_MT_RENDERER) {
Chong Zhangdcee1de2015-10-06 10:26:00 -0700540 synchronized (mWindowCallbacks) {
541 mWindowCallbacks.add(callback);
Skuhneb8160872015-09-22 09:51:39 -0700542 }
543 }
544 }
545
Chong Zhangdcee1de2015-10-06 10:26:00 -0700546 public void removeWindowCallbacks(WindowCallbacks callback) {
Skuhneb8160872015-09-22 09:51:39 -0700547 if (USE_MT_RENDERER) {
Chong Zhangdcee1de2015-10-06 10:26:00 -0700548 synchronized (mWindowCallbacks) {
549 mWindowCallbacks.remove(callback);
Skuhneb8160872015-09-22 09:51:39 -0700550 }
551 }
552 }
553
Chong Zhang8dbd9ad2015-10-09 10:06:11 -0700554 public void reportDrawFinish() {
555 if (mWindowDrawCountDown != null) {
556 mWindowDrawCountDown.countDown();
557 }
558 }
559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560 // FIXME for perf testing only
561 private boolean mProfile = false;
562
563 /**
564 * Call this to profile the next traversal call.
565 * FIXME for perf testing only. Remove eventually
566 */
567 public void profile() {
568 mProfile = true;
569 }
570
571 /**
572 * Indicates whether we are in touch mode. Calling this method triggers an IPC
573 * call and should be avoided whenever possible.
574 *
575 * @return True, if the device is in touch mode, false otherwise.
576 *
577 * @hide
578 */
579 static boolean isInTouchMode() {
Jeff Brown98365d72012-08-19 20:30:52 -0700580 IWindowSession windowSession = WindowManagerGlobal.peekWindowSession();
581 if (windowSession != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 try {
Jeff Brown98365d72012-08-19 20:30:52 -0700583 return windowSession.getInTouchMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584 } catch (RemoteException e) {
585 }
586 }
587 return false;
588 }
589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 /**
Robert Carrb2594852016-04-25 16:21:13 -0700591 * Notifies us that our child has been rebuilt, following
592 * a window preservation operation. In these cases we
593 * keep the same DecorView, but the activity controlling it
594 * is a different instance, and we need to update our
595 * callbacks.
596 *
597 * @hide
598 */
599 public void notifyChildRebuilt() {
600 if (mView instanceof RootViewSurfaceTaker) {
Robert Carr25cfa132016-11-16 13:24:09 -0800601 if (mSurfaceHolderCallback != null) {
602 mSurfaceHolder.removeCallback(mSurfaceHolderCallback);
603 }
604
Robert Carrb2594852016-04-25 16:21:13 -0700605 mSurfaceHolderCallback =
606 ((RootViewSurfaceTaker)mView).willYouTakeTheSurface();
Robert Carr25cfa132016-11-16 13:24:09 -0800607
Robert Carrb2594852016-04-25 16:21:13 -0700608 if (mSurfaceHolderCallback != null) {
609 mSurfaceHolder = new TakenSurfaceHolder();
610 mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
Robert Carr25cfa132016-11-16 13:24:09 -0800611 mSurfaceHolder.addCallback(mSurfaceHolderCallback);
Robert Carrb2594852016-04-25 16:21:13 -0700612 } else {
613 mSurfaceHolder = null;
614 }
615
616 mInputQueueCallback =
617 ((RootViewSurfaceTaker)mView).willYouTakeTheInputQueue();
618 if (mInputQueueCallback != null) {
619 mInputQueueCallback.onInputQueueCreated(mInputQueue);
620 }
621 }
622 }
623
624 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 * We have one child
626 */
Romain Guye4d01122010-06-16 18:44:05 -0700627 public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628 synchronized (this) {
629 if (mView == null) {
Mitsuru Oshima8169dae2009-04-28 18:12:09 -0700630 mView = view;
Jeff Brownd912e1f2014-04-11 18:46:22 -0700631
632 mAttachInfo.mDisplayState = mDisplay.getState();
633 mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
634
Fabrice Di Megliob003e282012-10-17 17:20:19 -0700635 mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
Joe Onorato86f67862010-11-05 18:57:34 -0700636 mFallbackEventHandler.setView(view);
Mitsuru Oshima9189cab2009-06-03 11:19:12 -0700637 mWindowAttributes.copyFrom(attrs);
Dianne Hackbornc2293022013-02-06 23:14:49 -0800638 if (mWindowAttributes.packageName == null) {
639 mWindowAttributes.packageName = mBasePackageName;
640 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -0700641 attrs = mWindowAttributes;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -0800642 setTag();
Chong Zhang4ffc3182016-05-04 15:06:02 -0700643
Chong Zhang44aabe42016-05-10 11:20:14 -0700644 if (DEBUG_KEEP_SCREEN_ON && (mClientWindowLayoutFlags
645 & WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) != 0
Chong Zhang4ffc3182016-05-04 15:06:02 -0700646 && (attrs.flags&WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) == 0) {
Chong Zhang44aabe42016-05-10 11:20:14 -0700647 Slog.d(mTag, "setView: FLAG_KEEP_SCREEN_ON changed from true to false!");
Chong Zhang4ffc3182016-05-04 15:06:02 -0700648 }
Dianne Hackborn9d090892012-06-11 18:35:41 -0700649 // Keep track of the actual window flags supplied by the client.
650 mClientWindowLayoutFlags = attrs.flags;
Svetoslav Ganov791fd312012-05-14 15:12:30 -0700651
Svetoslav Ganov45a02e02012-06-17 15:07:29 -0700652 setAccessibilityFocus(null, null);
Svetoslav Ganov791fd312012-05-14 15:12:30 -0700653
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700654 if (view instanceof RootViewSurfaceTaker) {
655 mSurfaceHolderCallback =
656 ((RootViewSurfaceTaker)view).willYouTakeTheSurface();
657 if (mSurfaceHolderCallback != null) {
658 mSurfaceHolder = new TakenSurfaceHolder();
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700659 mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
Robert Carr25cfa132016-11-16 13:24:09 -0800660 mSurfaceHolder.addCallback(mSurfaceHolderCallback);
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700661 }
662 }
Romain Guy1aec9a22011-01-05 09:37:12 -0800663
Alan Viverette49a22e82014-07-12 20:01:27 -0700664 // Compute surface insets required to draw at specified Z value.
665 // TODO: Use real shadow insets for a constant max Z.
Alan Viverette5435a302015-01-29 10:25:34 -0800666 if (!attrs.hasManualSurfaceInsets) {
Wale Ogunwale246c2092016-04-07 14:12:44 -0700667 attrs.setSurfaceInsets(view, false /*manual*/, true /*preservePrevious*/);
Alan Viverette5435a302015-01-29 10:25:34 -0800668 }
Alan Viverette49a22e82014-07-12 20:01:27 -0700669
Adam Lesinski4ece3d62016-06-16 18:05:41 -0700670 CompatibilityInfo compatibilityInfo =
671 mDisplay.getDisplayAdjustments().getCompatibilityInfo();
Romain Guy856d4e12011-10-14 15:47:55 -0700672 mTranslator = compatibilityInfo.getTranslator();
673
Romain Guy1aec9a22011-01-05 09:37:12 -0800674 // If the application owns the surface, don't enable hardware acceleration
675 if (mSurfaceHolder == null) {
Romain Guy3b748a42013-04-17 18:54:38 -0700676 enableHardwareAcceleration(attrs);
Romain Guy1aec9a22011-01-05 09:37:12 -0800677 }
678
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700679 boolean restore = false;
Romain Guy35b38ce2009-10-07 13:38:55 -0700680 if (mTranslator != null) {
Romain Guy856d4e12011-10-14 15:47:55 -0700681 mSurface.setCompatibilityTranslator(mTranslator);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700682 restore = true;
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700683 attrs.backup();
684 mTranslator.translateWindowLayout(attrs);
Mitsuru Oshima3d914922009-05-13 22:29:15 -0700685 }
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -0800686 if (DEBUG_LAYOUT) Log.d(mTag, "WindowLayout in setView:" + attrs);
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700687
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -0700688 if (!compatibilityInfo.supportsScreen()) {
Adam Lesinski95c42972013-10-02 10:13:27 -0700689 attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700690 mLastInCompatMode = true;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -0700691 }
692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693 mSoftInputMode = attrs.softInputMode;
694 mWindowAttributesChanged = true;
Romain Guyf21c9b02011-09-06 16:56:54 -0700695 mWindowAttributesChangesFlag = WindowManager.LayoutParams.EVERYTHING_CHANGED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696 mAttachInfo.mRootView = view;
Romain Guy35b38ce2009-10-07 13:38:55 -0700697 mAttachInfo.mScalingRequired = mTranslator != null;
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700698 mAttachInfo.mApplicationScale =
699 mTranslator == null ? 1.0f : mTranslator.applicationScale;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 if (panelParentView != null) {
701 mAttachInfo.mPanelParentWindowToken
702 = panelParentView.getApplicationWindowToken();
703 }
704 mAdded = true;
705 int res; /* = WindowManagerImpl.ADD_OKAY; */
Romain Guy8506ab42009-06-11 17:35:47 -0700706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 // Schedule the first layout -before- adding to the window
708 // manager, to make sure we do the relayout before receiving
709 // any other events from the system.
710 requestLayout();
Jeff Browncc4f7db2011-08-30 20:34:48 -0700711 if ((mWindowAttributes.inputFeatures
712 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
713 mInputChannel = new InputChannel();
714 }
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -0800715 mForceDecorViewVisibility = (mWindowAttributes.privateFlags
716 & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 try {
Dianne Hackborn180c4842011-09-13 12:39:25 -0700718 mOrigWindowType = mWindowAttributes.type;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700719 mAttachInfo.mRecomputeGlobalAttributes = true;
720 collectViewAttributes();
Jeff Brown98365d72012-08-19 20:30:52 -0700721 res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
722 getHostVisibility(), mDisplay.getDisplayId(),
Filip Gruszczynski0ec13282015-06-25 11:26:01 -0700723 mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
724 mAttachInfo.mOutsets, mInputChannel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800725 } catch (RemoteException e) {
726 mAdded = false;
727 mView = null;
728 mAttachInfo.mRootView = null;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700729 mInputChannel = null;
Joe Onorato86f67862010-11-05 18:57:34 -0700730 mFallbackEventHandler.setView(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 unscheduleTraversals();
Svetoslav Ganov45a02e02012-06-17 15:07:29 -0700732 setAccessibilityFocus(null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 throw new RuntimeException("Adding window failed", e);
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700734 } finally {
735 if (restore) {
736 attrs.restore();
737 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700739
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700740 if (mTranslator != null) {
741 mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets);
Mitsuru Oshima9189cab2009-06-03 11:19:12 -0700742 }
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800743 mPendingOverscanInsets.set(0, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 mPendingContentInsets.set(mAttachInfo.mContentInsets);
Adrian Roosfa104232014-06-20 16:10:14 -0700745 mPendingStableInsets.set(mAttachInfo.mStableInsets);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 mPendingVisibleInsets.set(0, 0, 0, 0);
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -0800747 mAttachInfo.mAlwaysConsumeNavBar =
748 (res & WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR) != 0;
749 mPendingAlwaysConsumeNavBar = mAttachInfo.mAlwaysConsumeNavBar;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -0800750 if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
Jeff Brown98365d72012-08-19 20:30:52 -0700751 if (res < WindowManagerGlobal.ADD_OKAY) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 mAttachInfo.mRootView = null;
753 mAdded = false;
Joe Onorato86f67862010-11-05 18:57:34 -0700754 mFallbackEventHandler.setView(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 unscheduleTraversals();
Svetoslav Ganov45a02e02012-06-17 15:07:29 -0700756 setAccessibilityFocus(null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800757 switch (res) {
Jeff Brown98365d72012-08-19 20:30:52 -0700758 case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
759 case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
760 throw new WindowManager.BadTokenException(
Wale Ogunwale74bf0652015-01-12 10:24:36 -0800761 "Unable to add window -- token " + attrs.token
762 + " is not valid; is your activity running?");
Jeff Brown98365d72012-08-19 20:30:52 -0700763 case WindowManagerGlobal.ADD_NOT_APP_TOKEN:
764 throw new WindowManager.BadTokenException(
Wale Ogunwale74bf0652015-01-12 10:24:36 -0800765 "Unable to add window -- token " + attrs.token
766 + " is not for an application");
Jeff Brown98365d72012-08-19 20:30:52 -0700767 case WindowManagerGlobal.ADD_APP_EXITING:
768 throw new WindowManager.BadTokenException(
Wale Ogunwale74bf0652015-01-12 10:24:36 -0800769 "Unable to add window -- app for token " + attrs.token
770 + " is exiting");
Jeff Brown98365d72012-08-19 20:30:52 -0700771 case WindowManagerGlobal.ADD_DUPLICATE_ADD:
772 throw new WindowManager.BadTokenException(
Wale Ogunwale74bf0652015-01-12 10:24:36 -0800773 "Unable to add window -- window " + mWindow
774 + " has already been added");
Jeff Brown98365d72012-08-19 20:30:52 -0700775 case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 // Silently ignore -- we would have just removed it
777 // right away, anyway.
778 return;
Jeff Brown98365d72012-08-19 20:30:52 -0700779 case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON:
Alan Viverette73f6d602015-09-14 16:01:19 -0400780 throw new WindowManager.BadTokenException("Unable to add window "
781 + mWindow + " -- another window of type "
782 + mWindowAttributes.type + " already exists");
Jeff Brown98365d72012-08-19 20:30:52 -0700783 case WindowManagerGlobal.ADD_PERMISSION_DENIED:
Alan Viverette73f6d602015-09-14 16:01:19 -0400784 throw new WindowManager.BadTokenException("Unable to add window "
785 + mWindow + " -- permission denied for window type "
786 + mWindowAttributes.type);
Craig Mautner6018aee2012-10-23 14:27:49 -0700787 case WindowManagerGlobal.ADD_INVALID_DISPLAY:
Alan Viverette73f6d602015-09-14 16:01:19 -0400788 throw new WindowManager.InvalidDisplayException("Unable to add window "
789 + mWindow + " -- the specified display can not be found");
Wale Ogunwale74bf0652015-01-12 10:24:36 -0800790 case WindowManagerGlobal.ADD_INVALID_TYPE:
Alan Viverette73f6d602015-09-14 16:01:19 -0400791 throw new WindowManager.InvalidDisplayException("Unable to add window "
792 + mWindow + " -- the specified window type "
793 + mWindowAttributes.type + " is not valid");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 }
795 throw new RuntimeException(
Wale Ogunwale74bf0652015-01-12 10:24:36 -0800796 "Unable to add window -- unknown error code " + res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700798
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700799 if (view instanceof RootViewSurfaceTaker) {
800 mInputQueueCallback =
801 ((RootViewSurfaceTaker)view).willYouTakeTheInputQueue();
802 }
Jeff Browncc4f7db2011-08-30 20:34:48 -0700803 if (mInputChannel != null) {
804 if (mInputQueueCallback != null) {
Michael Wrighta44dd262013-04-10 21:12:00 -0700805 mInputQueue = new InputQueue();
Jeff Browncc4f7db2011-08-30 20:34:48 -0700806 mInputQueueCallback.onInputQueueCreated(mInputQueue);
Jeff Browncc4f7db2011-08-30 20:34:48 -0700807 }
Michael Wrighta44dd262013-04-10 21:12:00 -0700808 mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
809 Looper.myLooper());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700810 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 view.assignParent(this);
Jeff Brown98365d72012-08-19 20:30:52 -0700813 mAddedTouchMode = (res & WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE) != 0;
814 mAppVisible = (res & WindowManagerGlobal.ADD_FLAG_APP_VISIBLE) != 0;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700815
816 if (mAccessibilityManager.isEnabled()) {
817 mAccessibilityInteractionConnectionManager.ensureConnection();
818 }
Svetoslav Ganov42138042012-03-20 11:51:39 -0700819
820 if (view.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
821 view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
822 }
Michael Wright95ae9422013-03-14 10:58:50 -0700823
Jeff Brownf9e989d2013-04-04 23:04:03 -0700824 // Set up the input pipeline.
825 CharSequence counterSuffix = attrs.getTitle();
Michael Wright899d7052014-04-23 17:23:39 -0700826 mSyntheticInputStage = new SyntheticInputStage();
827 InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
Jeff Brownf9e989d2013-04-04 23:04:03 -0700828 InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
829 "aq:native-post-ime:" + counterSuffix);
830 InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
831 InputStage imeStage = new ImeInputStage(earlyPostImeStage,
832 "aq:ime:" + counterSuffix);
833 InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
834 InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
835 "aq:native-pre-ime:" + counterSuffix);
836
837 mFirstInputStage = nativePreImeStage;
838 mFirstPostImeInputStage = earlyPostImeStage;
839 mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 }
841 }
842 }
843
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -0800844 private void setTag() {
845 final String[] split = mWindowAttributes.getTitle().toString().split("\\.");
846 if (split.length > 0) {
847 mTag = TAG + "[" + split[split.length - 1] + "]";
848 }
849 }
850
keunyoung30f420f2013-08-02 14:23:10 -0700851 /** Whether the window is in local focus mode or not */
852 private boolean isInLocalFocusMode() {
853 return (mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE) != 0;
854 }
855
Dianne Hackborn49b043f2015-05-07 14:21:38 -0700856 public int getWindowFlags() {
857 return mWindowAttributes.flags;
858 }
859
Dianne Hackbornece0f4f2015-06-11 13:29:01 -0700860 public int getDisplayId() {
861 return mDisplay.getDisplayId();
862 }
863
Dianne Hackborna7bb6fb2015-02-03 18:13:40 -0800864 public CharSequence getTitle() {
865 return mWindowAttributes.getTitle();
866 }
867
Romain Guy8ff6b9e2011-11-09 20:10:18 -0800868 void destroyHardwareResources() {
Stan Iliev45faba52016-06-28 13:33:15 -0400869 if (mAttachInfo.mThreadedRenderer != null) {
870 mAttachInfo.mThreadedRenderer.destroyHardwareResources(mView);
871 mAttachInfo.mThreadedRenderer.destroy();
Romain Guy31f2c2e2011-11-21 10:55:41 -0800872 }
873 }
874
Bo Liu845535a2014-03-21 12:06:23 -0700875 public void detachFunctor(long functor) {
Stan Iliev45faba52016-06-28 13:33:15 -0400876 if (mAttachInfo.mThreadedRenderer != null) {
John Reck44ac42a2014-05-16 14:46:07 -0700877 // Fence so that any pending invokeFunctor() messages will be processed
878 // before we return from detachFunctor.
Stan Iliev45faba52016-06-28 13:33:15 -0400879 mAttachInfo.mThreadedRenderer.stopDrawing();
John Reck44ac42a2014-05-16 14:46:07 -0700880 }
Romain Guyba6be8a2012-04-23 18:22:09 -0700881 }
882
John Reck3b202512014-06-23 13:13:08 -0700883 /**
884 * Schedules the functor for execution in either kModeProcess or
885 * kModeProcessNoContext, depending on whether or not there is an EGLContext.
886 *
887 * @param functor The native functor to invoke
888 * @param waitForCompletion If true, this will not return until the functor
889 * has invoked. If false, the functor may be invoked
890 * asynchronously.
891 */
John Reck44b49f02016-03-25 14:29:48 -0700892 public static void invokeFunctor(long functor, boolean waitForCompletion) {
John Reck3b202512014-06-23 13:13:08 -0700893 ThreadedRenderer.invokeFunctor(functor, waitForCompletion);
Bo Liuae738a72014-04-27 16:22:04 -0700894 }
895
John Reck119907c2014-08-14 09:02:01 -0700896 public void registerAnimatingRenderNode(RenderNode animator) {
Stan Iliev45faba52016-06-28 13:33:15 -0400897 if (mAttachInfo.mThreadedRenderer != null) {
898 mAttachInfo.mThreadedRenderer.registerAnimatingRenderNode(animator);
John Reck119907c2014-08-14 09:02:01 -0700899 } else {
900 if (mAttachInfo.mPendingAnimatingRenderNodes == null) {
901 mAttachInfo.mPendingAnimatingRenderNodes = new ArrayList<RenderNode>();
902 }
903 mAttachInfo.mPendingAnimatingRenderNodes.add(animator);
904 }
905 }
906
Doris Liu718cd3e2016-05-17 16:50:31 -0700907 public void registerVectorDrawableAnimator(
908 AnimatedVectorDrawable.VectorDrawableAnimatorRT animator) {
Stan Iliev45faba52016-06-28 13:33:15 -0400909 if (mAttachInfo.mThreadedRenderer != null) {
910 mAttachInfo.mThreadedRenderer.registerVectorDrawableAnimator(animator);
Doris Liu718cd3e2016-05-17 16:50:31 -0700911 }
912 }
913
Romain Guy3b748a42013-04-17 18:54:38 -0700914 private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
Dianne Hackborn7eec10e2010-11-12 18:03:47 -0800915 mAttachInfo.mHardwareAccelerated = false;
916 mAttachInfo.mHardwareAccelerationRequested = false;
Romain Guy4f6aff32011-01-12 16:21:41 -0800917
Romain Guy856d4e12011-10-14 15:47:55 -0700918 // Don't enable hardware acceleration when the application is in compatibility mode
John Reckdd58e792014-04-02 16:54:28 +0000919 if (mTranslator != null) return;
Romain Guy856d4e12011-10-14 15:47:55 -0700920
Dianne Hackborn7eec10e2010-11-12 18:03:47 -0800921 // Try to enable hardware acceleration if requested
Igor Murashkina86ab6402013-08-30 12:58:36 -0700922 final boolean hardwareAccelerated =
Jim Miller1b365922011-03-09 19:38:07 -0800923 (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
924
John Reckdd58e792014-04-02 16:54:28 +0000925 if (hardwareAccelerated) {
John Reck51aaf902015-12-02 15:08:07 -0800926 if (!ThreadedRenderer.isAvailable()) {
Romain Guy1af23a32011-03-24 16:03:55 -0700927 return;
928 }
929
Dianne Hackborn5d927c22011-09-02 12:22:18 -0700930 // Persistent processes (including the system) should not do
931 // accelerated rendering on low-end devices. In that case,
932 // sRendererDisabled will be set. In addition, the system process
933 // itself should never do accelerated rendering. In that case, both
934 // sRendererDisabled and sSystemRendererDisabled are set. When
935 // sSystemRendererDisabled is set, PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED
936 // can be used by code on the system process to escape that and enable
937 // HW accelerated drawing. (This is basically for the lock screen.)
Jim Miller1b365922011-03-09 19:38:07 -0800938
John Reck61375a82014-09-18 19:27:48 +0000939 final boolean fakeHwAccelerated = (attrs.privateFlags &
940 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED) != 0;
Dianne Hackborn5d927c22011-09-02 12:22:18 -0700941 final boolean forceHwAccelerated = (attrs.privateFlags &
942 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED) != 0;
Jim Miller1b365922011-03-09 19:38:07 -0800943
John Reck61375a82014-09-18 19:27:48 +0000944 if (fakeHwAccelerated) {
945 // This is exclusively for the preview windows the window manager
946 // shows for launching applications, so they will look more like
947 // the app being launched.
948 mAttachInfo.mHardwareAccelerationRequested = true;
John Reck51aaf902015-12-02 15:08:07 -0800949 } else if (!ThreadedRenderer.sRendererDisabled
950 || (ThreadedRenderer.sSystemRendererDisabled && forceHwAccelerated)) {
Stan Iliev45faba52016-06-28 13:33:15 -0400951 if (mAttachInfo.mThreadedRenderer != null) {
952 mAttachInfo.mThreadedRenderer.destroy();
Romain Guy211370f2012-02-01 16:10:55 -0800953 }
954
Alan Viverette2b12b582014-10-29 11:11:40 -0700955 final Rect insets = attrs.surfaceInsets;
Alan Viverette2cd23e62014-11-04 17:04:02 -0800956 final boolean hasSurfaceInsets = insets.left != 0 || insets.right != 0
957 || insets.top != 0 || insets.bottom != 0;
Alan Viverette2b12b582014-10-29 11:11:40 -0700958 final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
John Reckdf1742e2017-01-19 15:56:21 -0800959 mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
960 attrs.getTitle().toString());
Stan Iliev45faba52016-06-28 13:33:15 -0400961 if (mAttachInfo.mThreadedRenderer != null) {
Romain Guye55945e2013-04-04 15:26:04 -0700962 mAttachInfo.mHardwareAccelerated =
963 mAttachInfo.mHardwareAccelerationRequested = true;
964 }
Romain Guye4d01122010-06-16 18:44:05 -0700965 }
966 }
967 }
968
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800969 public View getView() {
970 return mView;
971 }
972
973 final WindowLeaked getLocation() {
974 return mLocation;
975 }
976
977 void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
978 synchronized (this) {
Alan Viverettedbed8932014-08-06 17:54:52 -0700979 final int oldInsetLeft = mWindowAttributes.surfaceInsets.left;
980 final int oldInsetTop = mWindowAttributes.surfaceInsets.top;
981 final int oldInsetRight = mWindowAttributes.surfaceInsets.right;
982 final int oldInsetBottom = mWindowAttributes.surfaceInsets.bottom;
983 final int oldSoftInputMode = mWindowAttributes.softInputMode;
Alan Viverette5435a302015-01-29 10:25:34 -0800984 final boolean oldHasManualSurfaceInsets = mWindowAttributes.hasManualSurfaceInsets;
Chong Zhang44aabe42016-05-10 11:20:14 -0700985
986 if (DEBUG_KEEP_SCREEN_ON && (mClientWindowLayoutFlags
987 & WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) != 0
Chong Zhang4ffc3182016-05-04 15:06:02 -0700988 && (attrs.flags&WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) == 0) {
Chong Zhang44aabe42016-05-10 11:20:14 -0700989 Slog.d(mTag, "setLayoutParams: FLAG_KEEP_SCREEN_ON from true to false!");
Chong Zhang4ffc3182016-05-04 15:06:02 -0700990 }
Alan Viverettedbed8932014-08-06 17:54:52 -0700991
Dianne Hackborn9d090892012-06-11 18:35:41 -0700992 // Keep track of the actual window flags supplied by the client.
993 mClientWindowLayoutFlags = attrs.flags;
Alan Viverettedbed8932014-08-06 17:54:52 -0700994
995 // Preserve compatible window flag if exists.
996 final int compatibleWindowFlag = mWindowAttributes.privateFlags
Adam Lesinski95c42972013-10-02 10:13:27 -0700997 & WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
Alan Viverettedbed8932014-08-06 17:54:52 -0700998
999 // Transfer over system UI visibility values as they carry current state.
Craig Mautner3fe38c02012-05-03 17:28:09 -07001000 attrs.systemUiVisibility = mWindowAttributes.systemUiVisibility;
1001 attrs.subtreeSystemUiVisibility = mWindowAttributes.subtreeSystemUiVisibility;
Alan Viverettedbed8932014-08-06 17:54:52 -07001002
Romain Guyf21c9b02011-09-06 16:56:54 -07001003 mWindowAttributesChangesFlag = mWindowAttributes.copyFrom(attrs);
John Spurlockbd957402013-10-03 11:38:39 -04001004 if ((mWindowAttributesChangesFlag
1005 & WindowManager.LayoutParams.TRANSLUCENT_FLAGS_CHANGED) != 0) {
1006 // Recompute system ui visibility.
1007 mAttachInfo.mRecomputeGlobalAttributes = true;
1008 }
Teng-Hui Zhu27571282016-05-12 15:53:53 -07001009 if ((mWindowAttributesChangesFlag
1010 & WindowManager.LayoutParams.LAYOUT_CHANGED) != 0) {
1011 // Request to update light center.
1012 mAttachInfo.mNeedsUpdateLightCenter = true;
1013 }
Dianne Hackbornc2293022013-02-06 23:14:49 -08001014 if (mWindowAttributes.packageName == null) {
1015 mWindowAttributes.packageName = mBasePackageName;
1016 }
Adam Lesinski95c42972013-10-02 10:13:27 -07001017 mWindowAttributes.privateFlags |= compatibleWindowFlag;
Dianne Hackborn9d090892012-06-11 18:35:41 -07001018
Wale Ogunwale246c2092016-04-07 14:12:44 -07001019 if (mWindowAttributes.preservePreviousSurfaceInsets) {
1020 // Restore old surface insets.
1021 mWindowAttributes.surfaceInsets.set(
1022 oldInsetLeft, oldInsetTop, oldInsetRight, oldInsetBottom);
1023 mWindowAttributes.hasManualSurfaceInsets = oldHasManualSurfaceInsets;
Robert Carr1bccabf2016-04-28 13:27:08 -07001024 } else if (mWindowAttributes.surfaceInsets.left != oldInsetLeft
1025 || mWindowAttributes.surfaceInsets.top != oldInsetTop
1026 || mWindowAttributes.surfaceInsets.right != oldInsetRight
1027 || mWindowAttributes.surfaceInsets.bottom != oldInsetBottom) {
Stan Iliev45faba52016-06-28 13:33:15 -04001028 mNeedsRendererSetup = true;
Wale Ogunwale246c2092016-04-07 14:12:44 -07001029 }
Alan Viverettedbed8932014-08-06 17:54:52 -07001030
Dianne Hackborn9d090892012-06-11 18:35:41 -07001031 applyKeepScreenOnFlag(mWindowAttributes);
1032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 if (newView) {
1034 mSoftInputMode = attrs.softInputMode;
1035 requestLayout();
1036 }
Alan Viverettedbed8932014-08-06 17:54:52 -07001037
The Android Open Source Project10592532009-03-18 17:39:46 -07001038 // Don't lose the mode we last auto-computed.
Alan Viverettedbed8932014-08-06 17:54:52 -07001039 if ((attrs.softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
The Android Open Source Project10592532009-03-18 17:39:46 -07001040 == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
1041 mWindowAttributes.softInputMode = (mWindowAttributes.softInputMode
1042 & ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
Alan Viverettedbed8932014-08-06 17:54:52 -07001043 | (oldSoftInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST);
The Android Open Source Project10592532009-03-18 17:39:46 -07001044 }
Alan Viverettedbed8932014-08-06 17:54:52 -07001045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001046 mWindowAttributesChanged = true;
1047 scheduleTraversals();
1048 }
1049 }
1050
1051 void handleAppVisibility(boolean visible) {
1052 if (mAppVisible != visible) {
1053 mAppVisible = visible;
1054 scheduleTraversals();
John Reck73840ea2014-09-22 07:39:18 -07001055 if (!mAppVisible) {
1056 WindowManagerGlobal.trimForeground();
1057 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 }
1059 }
1060
1061 void handleGetNewSurface() {
1062 mNewSurfaceNeeded = true;
1063 mFullRedrawNeeded = true;
1064 scheduleTraversals();
1065 }
1066
Jeff Brownd912e1f2014-04-11 18:46:22 -07001067 private final DisplayListener mDisplayListener = new DisplayListener() {
1068 @Override
1069 public void onDisplayChanged(int displayId) {
1070 if (mView != null && mDisplay.getDisplayId() == displayId) {
1071 final int oldDisplayState = mAttachInfo.mDisplayState;
1072 final int newDisplayState = mDisplay.getState();
1073 if (oldDisplayState != newDisplayState) {
1074 mAttachInfo.mDisplayState = newDisplayState;
Jeff Brownc2932a12014-11-20 18:04:05 -08001075 pokeDrawLockIfNeeded();
Jeff Brownd912e1f2014-04-11 18:46:22 -07001076 if (oldDisplayState != Display.STATE_UNKNOWN) {
1077 final int oldScreenState = toViewScreenState(oldDisplayState);
1078 final int newScreenState = toViewScreenState(newDisplayState);
1079 if (oldScreenState != newScreenState) {
1080 mView.dispatchScreenStateChanged(newScreenState);
1081 }
1082 if (oldDisplayState == Display.STATE_OFF) {
1083 // Draw was suppressed so we need to for it to happen here.
1084 mFullRedrawNeeded = true;
1085 scheduleTraversals();
1086 }
1087 }
1088 }
Romain Guy7e4e5612012-03-05 14:37:29 -08001089 }
1090 }
Jeff Brownd912e1f2014-04-11 18:46:22 -07001091
1092 @Override
1093 public void onDisplayRemoved(int displayId) {
1094 }
1095
1096 @Override
1097 public void onDisplayAdded(int displayId) {
1098 }
1099
1100 private int toViewScreenState(int displayState) {
1101 return displayState == Display.STATE_OFF ?
1102 View.SCREEN_STATE_OFF : View.SCREEN_STATE_ON;
1103 }
1104 };
Romain Guy7e4e5612012-03-05 14:37:29 -08001105
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001106 /**
1107 * Notify about move to a different display.
1108 * @param displayId The id of the display where this view root is moved to.
1109 *
1110 * @hide
1111 */
1112 public void onMovedToDisplay(int displayId) {
1113 if (mDisplay.getDisplayId() == displayId) {
1114 return;
1115 }
1116
1117 // Get new instance of display based on current display adjustments. It may be updated later
1118 // if moving between the displays also involved a configuration change.
Bryce Lee609bf652017-02-09 16:50:13 -08001119 mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(displayId,
1120 mView.getResources());
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001121 mAttachInfo.mDisplayState = mDisplay.getState();
1122 // Internal state updated, now notify the view hierarchy.
1123 mView.dispatchMovedToDisplay(mDisplay);
1124 }
1125
Jeff Brownc2932a12014-11-20 18:04:05 -08001126 void pokeDrawLockIfNeeded() {
1127 final int displayState = mAttachInfo.mDisplayState;
1128 if (mView != null && mAdded && mTraversalScheduled
1129 && (displayState == Display.STATE_DOZE
1130 || displayState == Display.STATE_DOZE_SUSPEND)) {
1131 try {
1132 mWindowSession.pokeDrawLock(mWindow);
1133 } catch (RemoteException ex) {
1134 // System server died, oh well.
1135 }
1136 }
1137 }
1138
Craig Mautner6018aee2012-10-23 14:27:49 -07001139 @Override
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001140 public void requestFitSystemWindows() {
1141 checkThread();
Adrian Roosfa104232014-06-20 16:10:14 -07001142 mApplyInsetsRequested = true;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001143 scheduleTraversals();
1144 }
1145
Craig Mautner6018aee2012-10-23 14:27:49 -07001146 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001147 public void requestLayout() {
Chet Haase3efa7b52012-12-03 08:33:17 -08001148 if (!mHandlingLayoutInLayoutRequest) {
1149 checkThread();
1150 mLayoutRequested = true;
1151 scheduleTraversals();
1152 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 }
1154
Craig Mautner6018aee2012-10-23 14:27:49 -07001155 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 public boolean isLayoutRequested() {
1157 return mLayoutRequested;
1158 }
1159
Chris Craik9de95db2017-01-18 17:59:23 -08001160 @Override
1161 public void onDescendantInvalidated(@NonNull View child, @NonNull View descendant) {
1162 if ((descendant.mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
1163 mIsAnimating = true;
1164 }
1165 invalidate();
1166 }
1167
Romain Guycfef1232012-02-23 13:50:37 -08001168 void invalidate() {
1169 mDirty.set(0, 0, mWidth, mHeight);
John Recke4267ea2014-06-03 15:53:15 -07001170 if (!mWillDrawSoon) {
1171 scheduleTraversals();
1172 }
Romain Guycfef1232012-02-23 13:50:37 -08001173 }
1174
Dianne Hackborna53de062012-05-08 18:53:51 -07001175 void invalidateWorld(View view) {
1176 view.invalidate();
1177 if (view instanceof ViewGroup) {
Romain Guyf84208f2012-09-13 22:50:18 -07001178 ViewGroup parent = (ViewGroup) view;
1179 for (int i = 0; i < parent.getChildCount(); i++) {
Dianne Hackborna53de062012-05-08 18:53:51 -07001180 invalidateWorld(parent.getChildAt(i));
1181 }
1182 }
1183 }
1184
Craig Mautner6018aee2012-10-23 14:27:49 -07001185 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001186 public void invalidateChild(View child, Rect dirty) {
Romain Guycfef1232012-02-23 13:50:37 -08001187 invalidateChildInParent(null, dirty);
1188 }
1189
Craig Mautner8f303ad2013-06-14 11:32:22 -07001190 @Override
Romain Guycfef1232012-02-23 13:50:37 -08001191 public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192 checkThread();
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001193 if (DEBUG_DRAW) Log.v(mTag, "Invalidate child: " + dirty);
Romain Guycfef1232012-02-23 13:50:37 -08001194
Chet Haase70d4ba12010-10-06 09:46:45 -07001195 if (dirty == null) {
Chet Haase70d4ba12010-10-06 09:46:45 -07001196 invalidate();
Romain Guycfef1232012-02-23 13:50:37 -08001197 return null;
Chet Haase3561d062012-10-23 12:54:51 -07001198 } else if (dirty.isEmpty() && !mIsAnimating) {
Chet Haase05e91ed2012-07-03 14:17:57 -07001199 return null;
Chet Haase70d4ba12010-10-06 09:46:45 -07001200 }
Romain Guycfef1232012-02-23 13:50:37 -08001201
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001202 if (mCurScrollY != 0 || mTranslator != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 mTempRect.set(dirty);
Romain Guy1e095972009-07-07 11:22:45 -07001204 dirty = mTempRect;
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07001205 if (mCurScrollY != 0) {
Romain Guycfef1232012-02-23 13:50:37 -08001206 dirty.offset(0, -mCurScrollY);
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07001207 }
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001208 if (mTranslator != null) {
Romain Guy1e095972009-07-07 11:22:45 -07001209 mTranslator.translateRectInAppWindowToScreen(dirty);
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07001210 }
Romain Guy1e095972009-07-07 11:22:45 -07001211 if (mAttachInfo.mScalingRequired) {
1212 dirty.inset(-1, -1);
1213 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214 }
Romain Guycfef1232012-02-23 13:50:37 -08001215
Alan Viverettea7ea65e2015-05-15 11:30:21 -07001216 invalidateRectOnScreen(dirty);
1217
1218 return null;
1219 }
1220
1221 private void invalidateRectOnScreen(Rect dirty) {
Romain Guycfef1232012-02-23 13:50:37 -08001222 final Rect localDirty = mDirty;
1223 if (!localDirty.isEmpty() && !localDirty.contains(dirty)) {
Romain Guy02ccac62011-06-24 13:20:23 -07001224 mAttachInfo.mSetIgnoreDirtyState = true;
Romain Guy7d695942010-12-01 17:22:29 -08001225 mAttachInfo.mIgnoreDirtyState = true;
1226 }
Romain Guycfef1232012-02-23 13:50:37 -08001227
1228 // Add the new dirty rect to the current one
1229 localDirty.union(dirty.left, dirty.top, dirty.right, dirty.bottom);
1230 // Intersect with the bounds of the window to skip
1231 // updates that lie outside of the visible region
Romain Guy7b2f8b82012-03-19 17:18:54 -07001232 final float appScale = mAttachInfo.mApplicationScale;
Chet Haase3561d062012-10-23 12:54:51 -07001233 final boolean intersected = localDirty.intersect(0, 0,
1234 (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
1235 if (!intersected) {
Chet Haaseb78ee0e2012-10-17 11:32:01 -07001236 localDirty.setEmpty();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 }
Chet Haase3561d062012-10-23 12:54:51 -07001238 if (!mWillDrawSoon && (intersected || mIsAnimating)) {
1239 scheduleTraversals();
1240 }
Romain Guy0d9275e2010-10-26 14:22:30 -07001241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001242
Daniel Koulomzin087ae472015-12-16 17:52:25 -05001243 public void setIsAmbientMode(boolean ambient) {
1244 mIsAmbientMode = ambient;
1245 }
1246
George Mount41725de2015-04-09 08:23:05 -07001247 void setWindowStopped(boolean stopped) {
Dianne Hackbornce418e62011-03-01 14:31:38 -08001248 if (mStopped != stopped) {
1249 mStopped = stopped;
Stan Iliev45faba52016-06-28 13:33:15 -04001250 final ThreadedRenderer renderer = mAttachInfo.mThreadedRenderer;
John Reck8afcc762016-04-13 10:24:06 -07001251 if (renderer != null) {
1252 if (DEBUG_DRAW) Log.d(mTag, "WindowStopped on " + getTitle() + " set to " + mStopped);
1253 renderer.setStopped(mStopped);
1254 }
George Mount41725de2015-04-09 08:23:05 -07001255 if (!mStopped) {
Dianne Hackbornce418e62011-03-01 14:31:38 -08001256 scheduleTraversals();
John Reckd9b16072016-02-23 10:35:19 -08001257 } else {
John Reck8afcc762016-04-13 10:24:06 -07001258 if (renderer != null) {
1259 renderer.destroyHardwareResources(mView);
John Reckf4db3d22016-02-26 12:58:17 -08001260 }
Dianne Hackbornce418e62011-03-01 14:31:38 -08001261 }
1262 }
1263 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264
George Mount41725de2015-04-09 08:23:05 -07001265 /**
1266 * Block the input events during an Activity Transition. The KEYCODE_BACK event is allowed
1267 * through to allow quick reversal of the Activity Transition.
1268 *
1269 * @param paused true to pause, false to resume.
1270 */
1271 public void setPausedForTransition(boolean paused) {
1272 mPausedForTransition = paused;
1273 }
1274
Craig Mautner8f303ad2013-06-14 11:32:22 -07001275 @Override
Romain Guycfef1232012-02-23 13:50:37 -08001276 public ViewParent getParent() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001277 return null;
1278 }
1279
Craig Mautner8f303ad2013-06-14 11:32:22 -07001280 @Override
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001281 public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001282 if (child != mView) {
1283 throw new RuntimeException("child is not mine, honest!");
1284 }
1285 // Note: don't apply scroll offset, because we want to know its
1286 // visibility in the virtual canvas being given to the view hierarchy.
1287 return r.intersect(0, 0, mWidth, mHeight);
1288 }
1289
Igor Murashkina86ab6402013-08-30 12:58:36 -07001290 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 public void bringChildToFront(View child) {
1292 }
1293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001294 int getHostVisibility() {
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -08001295 return (mAppVisible || mForceDecorViewVisibility) ? mView.getVisibility() : View.GONE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001296 }
Romain Guy8506ab42009-06-11 17:35:47 -07001297
Chet Haasecca2c982011-05-20 14:34:18 -07001298 /**
1299 * Add LayoutTransition to the list of transitions to be started in the next traversal.
1300 * This list will be cleared after the transitions on the list are start()'ed. These
1301 * transitionsa re added by LayoutTransition itself when it sets up animations. The setup
1302 * happens during the layout phase of traversal, which we want to complete before any of the
1303 * animations are started (because those animations may side-effect properties that layout
1304 * depends upon, like the bounding rectangles of the affected views). So we add the transition
1305 * to the list and it is started just prior to starting the drawing phase of traversal.
1306 *
1307 * @param transition The LayoutTransition to be started on the next traversal.
1308 *
1309 * @hide
1310 */
1311 public void requestTransitionStart(LayoutTransition transition) {
1312 if (mPendingTransitions == null || !mPendingTransitions.contains(transition)) {
1313 if (mPendingTransitions == null) {
1314 mPendingTransitions = new ArrayList<LayoutTransition>();
1315 }
1316 mPendingTransitions.add(transition);
1317 }
1318 }
1319
John Recka5dda642014-05-22 15:43:54 -07001320 /**
1321 * Notifies the HardwareRenderer that a new frame will be coming soon.
1322 * Currently only {@link ThreadedRenderer} cares about this, and uses
1323 * this knowledge to adjust the scheduling of off-thread animations
1324 */
1325 void notifyRendererOfFramePending() {
Stan Iliev45faba52016-06-28 13:33:15 -04001326 if (mAttachInfo.mThreadedRenderer != null) {
1327 mAttachInfo.mThreadedRenderer.notifyFramePending();
John Recka5dda642014-05-22 15:43:54 -07001328 }
1329 }
1330
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001331 void scheduleTraversals() {
1332 if (!mTraversalScheduled) {
1333 mTraversalScheduled = true;
Jeff Brown3d4e7efe2015-02-26 15:34:16 -08001334 mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001335 mChoreographer.postCallback(
1336 Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
Michael Wright9d744c72014-02-18 21:27:42 -08001337 if (!mUnbufferedInputDispatch) {
1338 scheduleConsumeBatchedInput();
1339 }
John Recka5dda642014-05-22 15:43:54 -07001340 notifyRendererOfFramePending();
Jeff Brownc2932a12014-11-20 18:04:05 -08001341 pokeDrawLockIfNeeded();
Jeff Brown96e942d2011-11-30 19:55:01 -08001342 }
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001343 }
Jeff Brown96e942d2011-11-30 19:55:01 -08001344
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001345 void unscheduleTraversals() {
1346 if (mTraversalScheduled) {
1347 mTraversalScheduled = false;
Jeff Brown3d4e7efe2015-02-26 15:34:16 -08001348 mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001349 mChoreographer.removeCallbacks(
1350 Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
1351 }
1352 }
1353
1354 void doTraversal() {
1355 if (mTraversalScheduled) {
1356 mTraversalScheduled = false;
Jeff Brown3d4e7efe2015-02-26 15:34:16 -08001357 mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001358
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001359 if (mProfile) {
1360 Debug.startMethodTracing("ViewAncestor");
Jeff Brown96e942d2011-11-30 19:55:01 -08001361 }
Jeff Brown96e942d2011-11-30 19:55:01 -08001362
Chris Craike22c59b2015-05-21 18:33:37 -07001363 performTraversals();
Jeff Brown96e942d2011-11-30 19:55:01 -08001364
Jeff Brownebb2d8d2012-03-23 17:14:34 -07001365 if (mProfile) {
1366 Debug.stopMethodTracing();
1367 mProfile = false;
1368 }
Jeff Brown96e942d2011-11-30 19:55:01 -08001369 }
1370 }
1371
Dianne Hackborn9d090892012-06-11 18:35:41 -07001372 private void applyKeepScreenOnFlag(WindowManager.LayoutParams params) {
1373 // Update window's global keep screen on flag: if a view has requested
1374 // that the screen be kept on, then it is always set; otherwise, it is
1375 // set to whatever the client last requested for the global state.
1376 if (mAttachInfo.mKeepScreenOn) {
1377 params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
1378 } else {
1379 params.flags = (params.flags&~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
1380 | (mClientWindowLayoutFlags&WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
1381 }
1382 }
1383
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001384 private boolean collectViewAttributes() {
Chris Craikd36a81f2014-07-17 10:16:51 -07001385 if (mAttachInfo.mRecomputeGlobalAttributes) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001386 //Log.i(mTag, "Computing view hierarchy attributes!");
Chris Craikd36a81f2014-07-17 10:16:51 -07001387 mAttachInfo.mRecomputeGlobalAttributes = false;
1388 boolean oldScreenOn = mAttachInfo.mKeepScreenOn;
1389 mAttachInfo.mKeepScreenOn = false;
1390 mAttachInfo.mSystemUiVisibility = 0;
1391 mAttachInfo.mHasSystemUiListeners = false;
1392 mView.dispatchCollectViewAttributes(mAttachInfo, 0);
1393 mAttachInfo.mSystemUiVisibility &= ~mAttachInfo.mDisabledSystemUiVisibility;
Craig Mautner7eac0f52012-09-13 13:14:14 -07001394 WindowManager.LayoutParams params = mWindowAttributes;
Chris Craikd36a81f2014-07-17 10:16:51 -07001395 mAttachInfo.mSystemUiVisibility |= getImpliedSystemUiVisibility(params);
1396 if (mAttachInfo.mKeepScreenOn != oldScreenOn
1397 || mAttachInfo.mSystemUiVisibility != params.subtreeSystemUiVisibility
1398 || mAttachInfo.mHasSystemUiListeners != params.hasSystemUiListeners) {
Dianne Hackborn9d090892012-06-11 18:35:41 -07001399 applyKeepScreenOnFlag(params);
Chris Craikd36a81f2014-07-17 10:16:51 -07001400 params.subtreeSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
1401 params.hasSystemUiListeners = mAttachInfo.mHasSystemUiListeners;
1402 mView.dispatchWindowSystemUiVisiblityChanged(mAttachInfo.mSystemUiVisibility);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001403 return true;
1404 }
1405 }
1406 return false;
1407 }
1408
John Spurlockbd957402013-10-03 11:38:39 -04001409 private int getImpliedSystemUiVisibility(WindowManager.LayoutParams params) {
1410 int vis = 0;
1411 // Translucent decor window flags imply stable system ui visibility.
1412 if ((params.flags & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) != 0) {
1413 vis |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
1414 }
1415 if ((params.flags & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) != 0) {
1416 vis |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
1417 }
1418 return vis;
1419 }
1420
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001421 private boolean measureHierarchy(final View host, final WindowManager.LayoutParams lp,
1422 final Resources res, final int desiredWindowWidth, final int desiredWindowHeight) {
1423 int childWidthMeasureSpec;
1424 int childHeightMeasureSpec;
1425 boolean windowSizeMayChange = false;
1426
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001427 if (DEBUG_ORIENTATION || DEBUG_LAYOUT) Log.v(mTag,
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001428 "Measuring " + host + " in display " + desiredWindowWidth
1429 + "x" + desiredWindowHeight + "...");
1430
1431 boolean goodMeasure = false;
1432 if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
1433 // On large screens, we don't want to allow dialogs to just
1434 // stretch to fill the entire width of the screen to display
1435 // one line of text. First try doing the layout at a smaller
1436 // size to see if it will fit.
1437 final DisplayMetrics packageMetrics = res.getDisplayMetrics();
1438 res.getValue(com.android.internal.R.dimen.config_prefDialogWidth, mTmpValue, true);
1439 int baseSize = 0;
1440 if (mTmpValue.type == TypedValue.TYPE_DIMENSION) {
1441 baseSize = (int)mTmpValue.getDimension(packageMetrics);
1442 }
Filip Gruszczynski1937a4c2016-01-19 16:17:13 -08001443 if (DEBUG_DIALOG) Log.v(mTag, "Window " + mView + ": baseSize=" + baseSize
1444 + ", desiredWindowWidth=" + desiredWindowWidth);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001445 if (baseSize != 0 && desiredWindowWidth > baseSize) {
1446 childWidthMeasureSpec = getRootMeasureSpec(baseSize, lp.width);
1447 childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
Jeff Brownc8d2668b2012-05-16 17:23:59 -07001448 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001449 if (DEBUG_DIALOG) Log.v(mTag, "Window " + mView + ": measured ("
Filip Gruszczynski1937a4c2016-01-19 16:17:13 -08001450 + host.getMeasuredWidth() + "," + host.getMeasuredHeight()
1451 + ") from width spec: " + MeasureSpec.toString(childWidthMeasureSpec)
1452 + " and height spec: " + MeasureSpec.toString(childHeightMeasureSpec));
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001453 if ((host.getMeasuredWidthAndState()&View.MEASURED_STATE_TOO_SMALL) == 0) {
1454 goodMeasure = true;
1455 } else {
1456 // Didn't fit in that size... try expanding a bit.
1457 baseSize = (baseSize+desiredWindowWidth)/2;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001458 if (DEBUG_DIALOG) Log.v(mTag, "Window " + mView + ": next baseSize="
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001459 + baseSize);
1460 childWidthMeasureSpec = getRootMeasureSpec(baseSize, lp.width);
Jeff Brownc8d2668b2012-05-16 17:23:59 -07001461 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001462 if (DEBUG_DIALOG) Log.v(mTag, "Window " + mView + ": measured ("
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001463 + host.getMeasuredWidth() + "," + host.getMeasuredHeight() + ")");
1464 if ((host.getMeasuredWidthAndState()&View.MEASURED_STATE_TOO_SMALL) == 0) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001465 if (DEBUG_DIALOG) Log.v(mTag, "Good!");
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001466 goodMeasure = true;
1467 }
1468 }
1469 }
1470 }
1471
1472 if (!goodMeasure) {
1473 childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width);
1474 childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
Jeff Brownc8d2668b2012-05-16 17:23:59 -07001475 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001476 if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()) {
1477 windowSizeMayChange = true;
1478 }
1479 }
1480
1481 if (DBG) {
1482 System.out.println("======================================");
1483 System.out.println("performTraversals -- after measure");
1484 host.debug();
1485 }
1486
1487 return windowSizeMayChange;
1488 }
1489
Alan Viverettefed3f722013-11-14 14:48:20 -08001490 /**
1491 * Modifies the input matrix such that it maps view-local coordinates to
1492 * on-screen coordinates.
1493 *
1494 * @param m input matrix to modify
1495 */
1496 void transformMatrixToGlobal(Matrix m) {
Dake Gu7bf379c2014-07-15 16:29:38 -07001497 m.preTranslate(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
Alan Viverettefed3f722013-11-14 14:48:20 -08001498 }
1499
1500 /**
1501 * Modifies the input matrix such that it maps on-screen coordinates to
1502 * view-local coordinates.
1503 *
1504 * @param m input matrix to modify
1505 */
1506 void transformMatrixToLocal(Matrix m) {
Dake Gu7bf379c2014-07-15 16:29:38 -07001507 m.postTranslate(-mAttachInfo.mWindowLeft, -mAttachInfo.mWindowTop);
Alan Viverettefed3f722013-11-14 14:48:20 -08001508 }
1509
Filip Gruszczynski954289d2015-02-26 15:46:47 -08001510 /* package */ WindowInsets getWindowInsets(boolean forceConstruct) {
1511 if (mLastWindowInsets == null || forceConstruct) {
1512 mDispatchContentInsets.set(mAttachInfo.mContentInsets);
1513 mDispatchStableInsets.set(mAttachInfo.mStableInsets);
1514 Rect contentInsets = mDispatchContentInsets;
1515 Rect stableInsets = mDispatchStableInsets;
1516 // For dispatch we preserve old logic, but for direct requests from Views we allow to
1517 // immediately use pending insets.
1518 if (!forceConstruct
1519 && (!mPendingContentInsets.equals(contentInsets) ||
1520 !mPendingStableInsets.equals(stableInsets))) {
1521 contentInsets = mPendingContentInsets;
1522 stableInsets = mPendingStableInsets;
1523 }
Filip Gruszczynski2217f612015-05-26 11:32:08 -07001524 Rect outsets = mAttachInfo.mOutsets;
1525 if (outsets.left > 0 || outsets.top > 0 || outsets.right > 0 || outsets.bottom > 0) {
1526 contentInsets = new Rect(contentInsets.left + outsets.left,
1527 contentInsets.top + outsets.top, contentInsets.right + outsets.right,
1528 contentInsets.bottom + outsets.bottom);
1529 }
Filip Gruszczynski954289d2015-02-26 15:46:47 -08001530 mLastWindowInsets = new WindowInsets(contentInsets,
Adam Powell01f280d2015-05-18 16:07:42 -07001531 null /* windowDecorInsets */, stableInsets,
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -08001532 mContext.getResources().getConfiguration().isScreenRound(),
1533 mAttachInfo.mAlwaysConsumeNavBar);
Filip Gruszczynski954289d2015-02-26 15:46:47 -08001534 }
1535 return mLastWindowInsets;
1536 }
1537
Adam Powell2accbf92014-04-16 23:14:57 +00001538 void dispatchApplyInsets(View host) {
Filip Gruszczynski954289d2015-02-26 15:46:47 -08001539 host.dispatchApplyWindowInsets(getWindowInsets(true /* forceConstruct */));
Adam Powell2accbf92014-04-16 23:14:57 +00001540 }
1541
Chong Zhangf6525ce2016-01-14 17:09:56 -08001542 private static boolean shouldUseDisplaySize(final WindowManager.LayoutParams lp) {
1543 return lp.type == TYPE_STATUS_BAR_PANEL
1544 || lp.type == TYPE_INPUT_METHOD
1545 || lp.type == TYPE_VOLUME_OVERLAY;
1546 }
1547
1548 private int dipToPx(int dip) {
1549 final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
1550 return (int) (displayMetrics.density * dip + 0.5f);
1551 }
1552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 private void performTraversals() {
1554 // cache mView since it is used so much below...
1555 final View host = mView;
1556
1557 if (DBG) {
1558 System.out.println("======================================");
1559 System.out.println("performTraversals");
1560 host.debug();
1561 }
1562
1563 if (host == null || !mAdded)
1564 return;
1565
Craig Mautnerdf2390a2012-08-29 20:59:22 -07001566 mIsInTraversal = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 mWillDrawSoon = true;
Dianne Hackborn711e62a2010-11-29 16:38:22 -08001568 boolean windowSizeMayChange = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 boolean newSurface = false;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07001570 boolean surfaceChanged = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 WindowManager.LayoutParams lp = mWindowAttributes;
1572
1573 int desiredWindowWidth;
1574 int desiredWindowHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 final int viewVisibility = getHostVisibility();
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001577 final boolean viewVisibilityChanged = !mFirst
1578 && (mViewVisibility != viewVisibility || mNewSurfaceNeeded);
Adam Powell06f9eb82016-08-24 17:09:01 -07001579 final boolean viewUserVisibilityChanged = !mFirst &&
1580 ((mViewVisibility == View.VISIBLE) != (viewVisibility == View.VISIBLE));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581
1582 WindowManager.LayoutParams params = null;
1583 if (mWindowAttributesChanged) {
1584 mWindowAttributesChanged = false;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07001585 surfaceChanged = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 params = lp;
1587 }
Adam Lesinski4ece3d62016-06-16 18:05:41 -07001588 CompatibilityInfo compatibilityInfo =
1589 mDisplay.getDisplayAdjustments().getCompatibilityInfo();
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001590 if (compatibilityInfo.supportsScreen() == mLastInCompatMode) {
1591 params = lp;
Jeff Brown96e942d2011-11-30 19:55:01 -08001592 mFullRedrawNeeded = true;
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001593 mLayoutRequested = true;
1594 if (mLastInCompatMode) {
Adam Lesinski95c42972013-10-02 10:13:27 -07001595 params.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001596 mLastInCompatMode = false;
1597 } else {
Adam Lesinski95c42972013-10-02 10:13:27 -07001598 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001599 mLastInCompatMode = true;
1600 }
1601 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07001602
Romain Guyf21c9b02011-09-06 16:56:54 -07001603 mWindowAttributesChangesFlag = 0;
Igor Murashkina86ab6402013-08-30 12:58:36 -07001604
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001605 Rect frame = mWinFrame;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 if (mFirst) {
Jeff Brown96e942d2011-11-30 19:55:01 -08001607 mFullRedrawNeeded = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 mLayoutRequested = true;
1609
Andrii Kulian44607962017-03-16 11:06:24 -07001610 final Configuration config = mContext.getResources().getConfiguration();
Chong Zhangf6525ce2016-01-14 17:09:56 -08001611 if (shouldUseDisplaySize(lp)) {
Dianne Hackborna239c842011-06-01 12:28:20 -07001612 // NOTE -- system code, won't try to do compat mode.
Jeff Brownbc68a592011-07-25 12:58:12 -07001613 Point size = new Point();
Jeff Brown98365d72012-08-19 20:30:52 -07001614 mDisplay.getRealSize(size);
Jeff Brownbc68a592011-07-25 12:58:12 -07001615 desiredWindowWidth = size.x;
1616 desiredWindowHeight = size.y;
Dianne Hackborna239c842011-06-01 12:28:20 -07001617 } else {
Chong Zhangf6525ce2016-01-14 17:09:56 -08001618 desiredWindowWidth = dipToPx(config.screenWidthDp);
1619 desiredWindowHeight = dipToPx(config.screenHeightDp);
Dianne Hackborna239c842011-06-01 12:28:20 -07001620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621
Romain Guyc5d55862011-01-21 19:01:46 -08001622 // We used to use the following condition to choose 32 bits drawing caches:
1623 // PixelFormat.hasAlpha(lp.format) || lp.format == PixelFormat.RGBX_8888
1624 // However, windows are now always 32 bits by default, so choose 32 bits
Chris Craikd36a81f2014-07-17 10:16:51 -07001625 mAttachInfo.mUse32BitDrawingCache = true;
1626 mAttachInfo.mHasWindowFocus = false;
1627 mAttachInfo.mWindowVisibility = viewVisibility;
1628 mAttachInfo.mRecomputeGlobalAttributes = false;
Andrii Kulian44607962017-03-16 11:06:24 -07001629 mLastConfigurationFromResources.setTo(config);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001630 mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
Fabrice Di Megliob003e282012-10-17 17:20:19 -07001631 // Set the layout direction if it has not been set before (inherit is the default)
1632 if (mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
Andrii Kulian44607962017-03-16 11:06:24 -07001633 host.setLayoutDirection(config.getLayoutDirection());
Fabrice Di Megliob003e282012-10-17 17:20:19 -07001634 }
Chris Craikd36a81f2014-07-17 10:16:51 -07001635 host.dispatchAttachedToWindow(mAttachInfo, 0);
1636 mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(true);
Adam Powell2accbf92014-04-16 23:14:57 +00001637 dispatchApplyInsets(host);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001638 //Log.i(mTag, "Screen on initialized: " + attachInfo.mKeepScreenOn);
svetoslavganov75986cf2009-05-14 22:28:01 -07001639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 } else {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001641 desiredWindowWidth = frame.width();
1642 desiredWindowHeight = frame.height();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001644 if (DEBUG_ORIENTATION) Log.v(mTag, "View " + host + " resized to: " + frame);
Jeff Brown96e942d2011-11-30 19:55:01 -08001645 mFullRedrawNeeded = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 mLayoutRequested = true;
Dianne Hackborn711e62a2010-11-29 16:38:22 -08001647 windowSizeMayChange = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 }
1649 }
1650
1651 if (viewVisibilityChanged) {
Chris Craikd36a81f2014-07-17 10:16:51 -07001652 mAttachInfo.mWindowVisibility = viewVisibility;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 host.dispatchWindowVisibilityChanged(viewVisibility);
Adam Powell06f9eb82016-08-24 17:09:01 -07001654 if (viewUserVisibilityChanged) {
Adam Powell64e1ba42016-08-22 09:09:44 -07001655 host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
1656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
Skuhneb8160872015-09-22 09:51:39 -07001658 endDragResizing();
Romain Guy65b345f2011-07-27 18:51:50 -07001659 destroyHardwareResources();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 }
1661 if (viewVisibility == View.GONE) {
1662 // After making a window gone, we will count it as being
1663 // shown for the first time the next time it gets focus.
1664 mHasHadWindowFocus = false;
1665 }
1666 }
1667
Alan Viverette7dbc3bf2015-01-28 16:14:36 -08001668 // Non-visible windows can't hold accessibility focus.
1669 if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
1670 host.clearAccessibilityFocus();
1671 }
1672
Chet Haaseb78c2842012-04-19 13:39:50 -07001673 // Execute enqueued actions on every traversal in case a detached view enqueued an action
Chris Craikd36a81f2014-07-17 10:16:51 -07001674 getRunQueue().executeActions(mAttachInfo.mHandler);
Chet Haaseb78c2842012-04-19 13:39:50 -07001675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 boolean insetsChanged = false;
Romain Guy8506ab42009-06-11 17:35:47 -07001677
Craig Mautner72d6f212015-02-19 16:33:09 -08001678 boolean layoutRequested = mLayoutRequested && (!mStopped || mReportNextDraw);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001679 if (layoutRequested) {
Romain Guy15df6702009-08-17 20:17:30 -07001680
Dianne Hackborn711e62a2010-11-29 16:38:22 -08001681 final Resources res = mView.getContext().getResources();
1682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 if (mFirst) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 // make sure touch mode code executes by setting cached value
1685 // to opposite of the added touch mode.
1686 mAttachInfo.mInTouchMode = !mAddedTouchMode;
Romain Guy2d4cff62010-04-09 15:39:00 -07001687 ensureTouchModeLocally(mAddedTouchMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 } else {
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001689 if (!mPendingOverscanInsets.equals(mAttachInfo.mOverscanInsets)) {
1690 insetsChanged = true;
1691 }
Dianne Hackbornfa6b35b2011-08-24 17:03:54 -07001692 if (!mPendingContentInsets.equals(mAttachInfo.mContentInsets)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 insetsChanged = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694 }
Adrian Roosfa104232014-06-20 16:10:14 -07001695 if (!mPendingStableInsets.equals(mAttachInfo.mStableInsets)) {
1696 insetsChanged = true;
1697 }
Dianne Hackbornfa6b35b2011-08-24 17:03:54 -07001698 if (!mPendingVisibleInsets.equals(mAttachInfo.mVisibleInsets)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001700 if (DEBUG_LAYOUT) Log.v(mTag, "Visible insets changing to: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 + mAttachInfo.mVisibleInsets);
1702 }
Filip Gruszczynski2217f612015-05-26 11:32:08 -07001703 if (!mPendingOutsets.equals(mAttachInfo.mOutsets)) {
1704 insetsChanged = true;
1705 }
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -08001706 if (mPendingAlwaysConsumeNavBar != mAttachInfo.mAlwaysConsumeNavBar) {
1707 insetsChanged = true;
1708 }
Chong Zhangf6525ce2016-01-14 17:09:56 -08001709 if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
1710 || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
Dianne Hackborn711e62a2010-11-29 16:38:22 -08001711 windowSizeMayChange = true;
Chong Zhangf6525ce2016-01-14 17:09:56 -08001712
1713 if (shouldUseDisplaySize(lp)) {
1714 // NOTE -- system code, won't try to do compat mode.
1715 Point size = new Point();
1716 mDisplay.getRealSize(size);
1717 desiredWindowWidth = size.x;
1718 desiredWindowHeight = size.y;
1719 } else {
1720 Configuration config = res.getConfiguration();
1721 desiredWindowWidth = dipToPx(config.screenWidthDp);
1722 desiredWindowHeight = dipToPx(config.screenHeightDp);
1723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 }
1725 }
1726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 // Ask host how big it wants to be
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001728 windowSizeMayChange |= measureHierarchy(host, lp, res,
1729 desiredWindowWidth, desiredWindowHeight);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001730 }
1731
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001732 if (collectViewAttributes()) {
1733 params = lp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001734 }
Chris Craikd36a81f2014-07-17 10:16:51 -07001735 if (mAttachInfo.mForceReportNewAttributes) {
1736 mAttachInfo.mForceReportNewAttributes = false;
Dianne Hackborn9a230e02011-10-06 11:51:27 -07001737 params = lp;
1738 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739
Chris Craikd36a81f2014-07-17 10:16:51 -07001740 if (mFirst || mAttachInfo.mViewVisibilityChanged) {
1741 mAttachInfo.mViewVisibilityChanged = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001742 int resizeMode = mSoftInputMode &
1743 WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
1744 // If we are in auto resize mode, then we need to determine
1745 // what mode to use now.
1746 if (resizeMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
Chris Craikd36a81f2014-07-17 10:16:51 -07001747 final int N = mAttachInfo.mScrollContainers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 for (int i=0; i<N; i++) {
Chris Craikd36a81f2014-07-17 10:16:51 -07001749 if (mAttachInfo.mScrollContainers.get(i).isShown()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001750 resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
1751 }
1752 }
1753 if (resizeMode == 0) {
1754 resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
1755 }
1756 if ((lp.softInputMode &
1757 WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) != resizeMode) {
1758 lp.softInputMode = (lp.softInputMode &
1759 ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) |
1760 resizeMode;
1761 params = lp;
1762 }
1763 }
1764 }
Romain Guy8506ab42009-06-11 17:35:47 -07001765
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001766 if (params != null) {
1767 if ((host.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
1768 if (!PixelFormat.formatHasAlpha(params.format)) {
1769 params.format = PixelFormat.TRANSLUCENT;
1770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 }
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001772 mAttachInfo.mOverscanRequested = (params.flags
1773 & WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 }
1775
Adrian Roosfa104232014-06-20 16:10:14 -07001776 if (mApplyInsetsRequested) {
1777 mApplyInsetsRequested = false;
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001778 mLastOverscanRequested = mAttachInfo.mOverscanRequested;
Adam Powell2accbf92014-04-16 23:14:57 +00001779 dispatchApplyInsets(host);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001780 if (mLayoutRequested) {
1781 // Short-circuit catching a new layout request here, so
1782 // we don't need to go through two layout passes when things
1783 // change due to fitting system windows, which can happen a lot.
1784 windowSizeMayChange |= measureHierarchy(host, lp,
1785 mView.getContext().getResources(),
1786 desiredWindowWidth, desiredWindowHeight);
1787 }
1788 }
1789
1790 if (layoutRequested) {
1791 // Clear this now, so that if anything requests a layout in the
1792 // rest of this function we will catch it and re-run a full
1793 // layout pass.
1794 mLayoutRequested = false;
1795 }
1796
1797 boolean windowShouldResize = layoutRequested && windowSizeMayChange
Dianne Hackborn189ee182010-12-02 21:48:53 -08001798 && ((mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight())
Romain Guy2e4f4262010-04-06 11:07:52 -07001799 || (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT &&
1800 frame.width() < desiredWindowWidth && frame.width() != mWidth)
1801 || (lp.height == ViewGroup.LayoutParams.WRAP_CONTENT &&
1802 frame.height() < desiredWindowHeight && frame.height() != mHeight));
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001803 windowShouldResize |= mDragResizing && mResizeMode == RESIZE_MODE_FREEFORM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001805 // If the activity was just relaunched, it might have unfrozen the task bounds (while
1806 // relaunching), so we need to force a call into window manager to pick up the latest
1807 // bounds.
1808 windowShouldResize |= mActivityRelaunched;
1809
Jeff Brown2e05ec32013-09-30 15:57:43 -07001810 // Determine whether to compute insets.
1811 // If there are no inset listeners remaining then we may still need to compute
1812 // insets in case the old insets were non-empty and must be reset.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001813 final boolean computesInternalInsets =
Chris Craikd36a81f2014-07-17 10:16:51 -07001814 mAttachInfo.mTreeObserver.hasComputeInternalInsetsListeners()
1815 || mAttachInfo.mHasNonEmptyGivenInternalInsets;
Romain Guy812ccbe2010-06-01 14:07:24 -07001816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001817 boolean insetsPending = false;
1818 int relayoutResult = 0;
Chet Haased86fb2c2016-05-04 07:26:02 -07001819 boolean updatedConfiguration = false;
Romain Guy812ccbe2010-06-01 14:07:24 -07001820
Robert Carrb2594852016-04-25 16:21:13 -07001821 final int surfaceGenerationId = mSurface.getGenerationId();
1822
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -08001823 final boolean isViewVisible = viewVisibility == View.VISIBLE;
Andrii Kulianb2e37802017-01-11 00:36:44 -08001824 final boolean windowRelayoutWasForced = mForceNextWindowRelayout;
Romain Guy812ccbe2010-06-01 14:07:24 -07001825 if (mFirst || windowShouldResize || insetsChanged ||
Jorim Jaggia4a58ef2016-01-27 02:10:08 -08001826 viewVisibilityChanged || params != null || mForceNextWindowRelayout) {
1827 mForceNextWindowRelayout = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001828
Alan Viverette64bf97a2015-09-18 16:42:00 -04001829 if (isViewVisible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 // If this window is giving internal insets to the window
1831 // manager, and it is being added or changing its visibility,
1832 // then we want to first give the window manager "fake"
1833 // insets to cause it to effectively ignore the content of
1834 // the window during layout. This avoids it briefly causing
1835 // other windows to resize/move based on the raw frame of the
1836 // window, waiting until we can finish laying out this window
1837 // and get back to the window manager with the ultimately
1838 // computed insets.
Romain Guy812ccbe2010-06-01 14:07:24 -07001839 insetsPending = computesInternalInsets && (mFirst || viewVisibilityChanged);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 }
1841
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07001842 if (mSurfaceHolder != null) {
1843 mSurfaceHolder.mSurfaceLock.lock();
1844 mDrawingAllowed = true;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07001845 }
Romain Guy812ccbe2010-06-01 14:07:24 -07001846
Romain Guyc361da82010-10-25 15:29:10 -07001847 boolean hwInitialized = false;
Chong Zhang75eccbd2016-07-12 19:25:08 -07001848 boolean contentInsetsChanged = false;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07001849 boolean hadSurface = mSurface.isValid();
Romain Guy812ccbe2010-06-01 14:07:24 -07001850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001851 try {
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07001852 if (DEBUG_LAYOUT) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001853 Log.i(mTag, "host=w:" + host.getMeasuredWidth() + ", h:" +
Dianne Hackborn189ee182010-12-02 21:48:53 -08001854 host.getMeasuredHeight() + ", params=" + params);
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07001855 }
Romain Guy2a83f002011-01-18 18:28:21 -08001856
Stan Iliev45faba52016-06-28 13:33:15 -04001857 if (mAttachInfo.mThreadedRenderer != null) {
John Reckf7d9c1d2014-04-09 10:01:03 -07001858 // relayoutWindow may decide to destroy mSurface. As that decision
1859 // happens in WindowManager service, we need to be defensive here
1860 // and stop using the surface in case it gets destroyed.
Stan Iliev45faba52016-06-28 13:33:15 -04001861 if (mAttachInfo.mThreadedRenderer.pauseSurface(mSurface)) {
John Reck01a5ea32014-12-03 13:01:07 -08001862 // Animations were running so we need to push a frame
1863 // to resume them
1864 mDirty.set(0, 0, mWidth, mHeight);
1865 }
John Reckba6adf62015-02-19 14:36:50 -08001866 mChoreographer.mFrameInfo.addFlags(FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED);
John Reckf7d9c1d2014-04-09 10:01:03 -07001867 }
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07001868 relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
1869
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001870 if (DEBUG_LAYOUT) Log.v(mTag, "relayout: frame=" + frame.toShortString()
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001871 + " overscan=" + mPendingOverscanInsets.toShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001872 + " content=" + mPendingContentInsets.toShortString()
1873 + " visible=" + mPendingVisibleInsets.toShortString()
Adrian Roosfa104232014-06-20 16:10:14 -07001874 + " visible=" + mPendingStableInsets.toShortString()
Filip Gruszczynski0ec13282015-06-25 11:26:01 -07001875 + " outsets=" + mPendingOutsets.toShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 + " surface=" + mSurface);
Romain Guy8506ab42009-06-11 17:35:47 -07001877
Andrii Kulian44607962017-03-16 11:06:24 -07001878 final Configuration pendingMergedConfig =
1879 mPendingMergedConfiguration.getMergedConfiguration();
1880 if (pendingMergedConfig.seq != 0) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001881 if (DEBUG_CONFIGURATION) Log.v(mTag, "Visible with new config: "
Andrii Kulian44607962017-03-16 11:06:24 -07001882 + pendingMergedConfig);
1883 performConfigurationChange(mPendingMergedConfiguration, !mFirst,
1884 INVALID_DISPLAY /* same display */);
1885 pendingMergedConfig.seq = 0;
Chet Haased86fb2c2016-05-04 07:26:02 -07001886 updatedConfiguration = true;
Dianne Hackborn694f79b2010-03-17 19:44:59 -07001887 }
Dianne Hackborn3556c9a2012-05-04 16:31:25 -07001888
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001889 final boolean overscanInsetsChanged = !mPendingOverscanInsets.equals(
1890 mAttachInfo.mOverscanInsets);
Chong Zhang75eccbd2016-07-12 19:25:08 -07001891 contentInsetsChanged = !mPendingContentInsets.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 mAttachInfo.mContentInsets);
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001893 final boolean visibleInsetsChanged = !mPendingVisibleInsets.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 mAttachInfo.mVisibleInsets);
Adrian Roosfa104232014-06-20 16:10:14 -07001895 final boolean stableInsetsChanged = !mPendingStableInsets.equals(
1896 mAttachInfo.mStableInsets);
Filip Gruszczynski2217f612015-05-26 11:32:08 -07001897 final boolean outsetsChanged = !mPendingOutsets.equals(mAttachInfo.mOutsets);
Chong Zhangf4abc2b2015-11-12 23:40:58 -08001898 final boolean surfaceSizeChanged = (relayoutResult
1899 & WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0;
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -08001900 final boolean alwaysConsumeNavBarChanged =
1901 mPendingAlwaysConsumeNavBar != mAttachInfo.mAlwaysConsumeNavBar;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001902 if (contentInsetsChanged) {
1903 mAttachInfo.mContentInsets.set(mPendingContentInsets);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001904 if (DEBUG_LAYOUT) Log.v(mTag, "Content insets changing to: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001905 + mAttachInfo.mContentInsets);
1906 }
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001907 if (overscanInsetsChanged) {
1908 mAttachInfo.mOverscanInsets.set(mPendingOverscanInsets);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001909 if (DEBUG_LAYOUT) Log.v(mTag, "Overscan insets changing to: "
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001910 + mAttachInfo.mOverscanInsets);
1911 // Need to relayout with content insets.
1912 contentInsetsChanged = true;
1913 }
Adrian Roosfa104232014-06-20 16:10:14 -07001914 if (stableInsetsChanged) {
1915 mAttachInfo.mStableInsets.set(mPendingStableInsets);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001916 if (DEBUG_LAYOUT) Log.v(mTag, "Decor insets changing to: "
Adrian Roosfa104232014-06-20 16:10:14 -07001917 + mAttachInfo.mStableInsets);
1918 // Need to relayout with content insets.
1919 contentInsetsChanged = true;
1920 }
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -08001921 if (alwaysConsumeNavBarChanged) {
1922 mAttachInfo.mAlwaysConsumeNavBar = mPendingAlwaysConsumeNavBar;
1923 contentInsetsChanged = true;
1924 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001925 if (contentInsetsChanged || mLastSystemUiVisibility !=
Adrian Roosfa104232014-06-20 16:10:14 -07001926 mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested
Filip Gruszczynski2217f612015-05-26 11:32:08 -07001927 || mLastOverscanRequested != mAttachInfo.mOverscanRequested
1928 || outsetsChanged) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001929 mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
Dianne Hackbornc4aad012013-02-22 15:05:25 -08001930 mLastOverscanRequested = mAttachInfo.mOverscanRequested;
Filip Gruszczynski2217f612015-05-26 11:32:08 -07001931 mAttachInfo.mOutsets.set(mPendingOutsets);
Adrian Roosfa104232014-06-20 16:10:14 -07001932 mApplyInsetsRequested = false;
Adam Powell2accbf92014-04-16 23:14:57 +00001933 dispatchApplyInsets(host);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001934 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001935 if (visibleInsetsChanged) {
1936 mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08001937 if (DEBUG_LAYOUT) Log.v(mTag, "Visible insets changing to: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 + mAttachInfo.mVisibleInsets);
1939 }
1940
1941 if (!hadSurface) {
1942 if (mSurface.isValid()) {
1943 // If we are creating a new surface, then we need to
1944 // completely redraw it. Also, when we get to the
1945 // point of drawing it we will hold off and schedule
1946 // a new traversal instead. This is so we can tell the
1947 // window manager about all of the windows being displayed
1948 // before actually drawing them, so it can display then
1949 // all at once.
1950 newSurface = true;
Jeff Brown96e942d2011-11-30 19:55:01 -08001951 mFullRedrawNeeded = true;
Jack Palevich61a6e682009-10-09 17:37:50 -07001952 mPreviousTransparentRegion.setEmpty();
Romain Guy8506ab42009-06-11 17:35:47 -07001953
John Reck63005e62015-05-19 15:00:13 -07001954 // Only initialize up-front if transparent regions are not
1955 // requested, otherwise defer to see if the entire window
1956 // will be transparent
Stan Iliev45faba52016-06-28 13:33:15 -04001957 if (mAttachInfo.mThreadedRenderer != null) {
Dianne Hackborn64825172011-03-02 21:32:58 -08001958 try {
Stan Iliev45faba52016-06-28 13:33:15 -04001959 hwInitialized = mAttachInfo.mThreadedRenderer.initialize(
John Reck79d81e62013-11-05 13:26:57 -08001960 mSurface);
John Reck63005e62015-05-19 15:00:13 -07001961 if (hwInitialized && (host.mPrivateFlags
1962 & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
1963 // Don't pre-allocate if transparent regions
1964 // are requested as they may not be needed
1965 mSurface.allocateBuffers();
1966 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07001967 } catch (OutOfResourcesException e) {
Romain Guy3696779b2013-01-28 14:04:07 -08001968 handleOutOfResourcesException(e);
Dianne Hackborn64825172011-03-02 21:32:58 -08001969 return;
1970 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001971 }
1972 }
1973 } else if (!mSurface.isValid()) {
1974 // If the surface has been removed, then reset the scroll
1975 // positions.
Svetoslav Ganov149567f2013-01-08 15:23:34 -08001976 if (mLastScrolledFocus != null) {
1977 mLastScrolledFocus.clear();
1978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001979 mScrollY = mCurScrollY = 0;
Adrian Roos0e7ae4e2014-10-01 15:33:22 +02001980 if (mView instanceof RootViewSurfaceTaker) {
1981 ((RootViewSurfaceTaker) mView).onRootViewScrollYChanged(mCurScrollY);
1982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001983 if (mScroller != null) {
1984 mScroller.abortAnimation();
1985 }
Romain Guy1d0c7082011-08-03 16:22:24 -07001986 // Our surface is gone
Stan Iliev45faba52016-06-28 13:33:15 -04001987 if (mAttachInfo.mThreadedRenderer != null &&
1988 mAttachInfo.mThreadedRenderer.isEnabled()) {
1989 mAttachInfo.mThreadedRenderer.destroy();
Romain Guy1d0c7082011-08-03 16:22:24 -07001990 }
Chong Zhangf4abc2b2015-11-12 23:40:58 -08001991 } else if ((surfaceGenerationId != mSurface.getGenerationId()
Andrii Kulianb2e37802017-01-11 00:36:44 -08001992 || surfaceSizeChanged || windowRelayoutWasForced)
Chong Zhangf4abc2b2015-11-12 23:40:58 -08001993 && mSurfaceHolder == null
Stan Iliev45faba52016-06-28 13:33:15 -04001994 && mAttachInfo.mThreadedRenderer != null) {
Jeff Brown96e942d2011-11-30 19:55:01 -08001995 mFullRedrawNeeded = true;
Dianne Hackborn64825172011-03-02 21:32:58 -08001996 try {
Chong Zhangf4abc2b2015-11-12 23:40:58 -08001997 // Need to do updateSurface (which leads to CanvasContext::setSurface and
1998 // re-create the EGLSurface) if either the Surface changed (as indicated by
1999 // generation id), or WindowManager changed the surface size. The latter is
2000 // because on some chips, changing the consumer side's BufferQueue size may
2001 // not take effect immediately unless we create a new EGLSurface.
2002 // Note that frame size change doesn't always imply surface size change (eg.
2003 // drag resizing uses fullscreen surface), need to check surfaceSizeChanged
2004 // flag from WindowManager.
Stan Iliev45faba52016-06-28 13:33:15 -04002005 mAttachInfo.mThreadedRenderer.updateSurface(mSurface);
Igor Murashkina86ab6402013-08-30 12:58:36 -07002006 } catch (OutOfResourcesException e) {
Romain Guy3696779b2013-01-28 14:04:07 -08002007 handleOutOfResourcesException(e);
Dianne Hackborn64825172011-03-02 21:32:58 -08002008 return;
2009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010 }
Chong Zhang0275e392015-09-17 10:41:44 -07002011
Jorim Jaggi4846ee32016-01-07 17:39:12 +01002012 final boolean freeformResizing = (relayoutResult
2013 & WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM) != 0;
2014 final boolean dockedResizing = (relayoutResult
2015 & WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED) != 0;
2016 final boolean dragResizing = freeformResizing || dockedResizing;
Chong Zhang0275e392015-09-17 10:41:44 -07002017 if (mDragResizing != dragResizing) {
Skuhneb8160872015-09-22 09:51:39 -07002018 if (dragResizing) {
Jorim Jaggi4846ee32016-01-07 17:39:12 +01002019 mResizeMode = freeformResizing
2020 ? RESIZE_MODE_FREEFORM
2021 : RESIZE_MODE_DOCKED_DIVIDER;
Jorim Jaggic39c7b02016-03-24 10:47:07 -07002022 startDragResizing(mPendingBackDropFrame,
2023 mWinFrame.equals(mPendingBackDropFrame), mPendingVisibleInsets,
2024 mPendingStableInsets, mResizeMode);
Skuhneb8160872015-09-22 09:51:39 -07002025 } else {
2026 // We shouldn't come here, but if we come we should end the resize.
2027 endDragResizing();
2028 }
Chong Zhang0275e392015-09-17 10:41:44 -07002029 }
Skuhneb8160872015-09-22 09:51:39 -07002030 if (!USE_MT_RENDERER) {
2031 if (dragResizing) {
2032 mCanvasOffsetX = mWinFrame.left;
2033 mCanvasOffsetY = mWinFrame.top;
2034 } else {
2035 mCanvasOffsetX = mCanvasOffsetY = 0;
2036 }
Chong Zhang0275e392015-09-17 10:41:44 -07002037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002038 } catch (RemoteException e) {
2039 }
Romain Guy1d0c7082011-08-03 16:22:24 -07002040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002041 if (DEBUG_ORIENTATION) Log.v(
Jeff Brownc5ed5912010-07-14 18:48:53 -07002042 TAG, "Relayout returned: frame=" + frame + ", surface=" + mSurface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002043
Chris Craikd36a81f2014-07-17 10:16:51 -07002044 mAttachInfo.mWindowLeft = frame.left;
2045 mAttachInfo.mWindowTop = frame.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046
2047 // !!FIXME!! This next section handles the case where we did not get the
2048 // window size we asked for. We should avoid this by getting a maximum size from
2049 // the window session beforehand.
Dianne Hackborn3556c9a2012-05-04 16:31:25 -07002050 if (mWidth != frame.width() || mHeight != frame.height()) {
Dianne Hackborn3556c9a2012-05-04 16:31:25 -07002051 mWidth = frame.width();
2052 mHeight = frame.height();
2053 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07002055 if (mSurfaceHolder != null) {
2056 // The app owns the surface; tell it about what is going on.
2057 if (mSurface.isValid()) {
2058 // XXX .copyFrom() doesn't work!
2059 //mSurfaceHolder.mSurface.copyFrom(mSurface);
2060 mSurfaceHolder.mSurface = mSurface;
2061 }
Jeff Brown30bc34f2011-01-25 12:56:56 -08002062 mSurfaceHolder.setSurfaceFrameSize(mWidth, mHeight);
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07002063 mSurfaceHolder.mSurfaceLock.unlock();
2064 if (mSurface.isValid()) {
John Reck208c47c2016-06-09 16:26:21 -07002065 if (!hadSurface) {
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07002066 mSurfaceHolder.ungetCallbacks();
2067
2068 mIsCreating = true;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07002069 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
2070 if (callbacks != null) {
2071 for (SurfaceHolder.Callback c : callbacks) {
2072 c.surfaceCreated(mSurfaceHolder);
2073 }
2074 }
2075 surfaceChanged = true;
2076 }
John Reck208c47c2016-06-09 16:26:21 -07002077 if (surfaceChanged || surfaceGenerationId != mSurface.getGenerationId()) {
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07002078 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
2079 if (callbacks != null) {
2080 for (SurfaceHolder.Callback c : callbacks) {
2081 c.surfaceChanged(mSurfaceHolder, lp.format,
2082 mWidth, mHeight);
2083 }
2084 }
2085 }
2086 mIsCreating = false;
2087 } else if (hadSurface) {
2088 mSurfaceHolder.ungetCallbacks();
2089 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07002090 if (callbacks != null) {
2091 for (SurfaceHolder.Callback c : callbacks) {
2092 c.surfaceDestroyed(mSurfaceHolder);
2093 }
2094 }
2095 mSurfaceHolder.mSurfaceLock.lock();
Jozef BABJAK93c5b6a2011-02-22 09:33:19 +01002096 try {
2097 mSurfaceHolder.mSurface = new Surface();
2098 } finally {
2099 mSurfaceHolder.mSurfaceLock.unlock();
2100 }
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07002101 }
2102 }
Romain Guy53389bd2010-09-07 17:16:32 -07002103
Stan Iliev45faba52016-06-28 13:33:15 -04002104 final ThreadedRenderer threadedRenderer = mAttachInfo.mThreadedRenderer;
2105 if (threadedRenderer != null && threadedRenderer.isEnabled()) {
Alan Viverette50210d92015-05-14 18:05:36 -07002106 if (hwInitialized
Stan Iliev45faba52016-06-28 13:33:15 -04002107 || mWidth != threadedRenderer.getWidth()
2108 || mHeight != threadedRenderer.getHeight()
2109 || mNeedsRendererSetup) {
2110 threadedRenderer.setup(mWidth, mHeight, mAttachInfo,
Alan Viverette50210d92015-05-14 18:05:36 -07002111 mWindowAttributes.surfaceInsets);
Stan Iliev45faba52016-06-28 13:33:15 -04002112 mNeedsRendererSetup = false;
Romain Guy03985752011-07-11 15:33:51 -07002113 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002114 }
2115
Craig Mautner72d6f212015-02-19 16:33:09 -08002116 if (!mStopped || mReportNextDraw) {
Dianne Hackbornce418e62011-03-01 14:31:38 -08002117 boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
Jeff Brown98365d72012-08-19 20:30:52 -07002118 (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
Dianne Hackbornce418e62011-03-01 14:31:38 -08002119 if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
Chong Zhang75eccbd2016-07-12 19:25:08 -07002120 || mHeight != host.getMeasuredHeight() || contentInsetsChanged ||
Chet Haased86fb2c2016-05-04 07:26:02 -07002121 updatedConfiguration) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002122 int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
2123 int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
Igor Murashkina86ab6402013-08-30 12:58:36 -07002124
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002125 if (DEBUG_LAYOUT) Log.v(mTag, "Ooops, something changed! mWidth="
Dianne Hackbornce418e62011-03-01 14:31:38 -08002126 + mWidth + " measuredWidth=" + host.getMeasuredWidth()
2127 + " mHeight=" + mHeight
2128 + " measuredHeight=" + host.getMeasuredHeight()
Chong Zhang75eccbd2016-07-12 19:25:08 -07002129 + " coveredInsetsChanged=" + contentInsetsChanged);
Igor Murashkina86ab6402013-08-30 12:58:36 -07002130
Dianne Hackbornce418e62011-03-01 14:31:38 -08002131 // Ask host how big it wants to be
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002132 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
Igor Murashkina86ab6402013-08-30 12:58:36 -07002133
Dianne Hackbornce418e62011-03-01 14:31:38 -08002134 // Implementation of weights from WindowManager.LayoutParams
2135 // We just grow the dimensions as needed and re-measure if
2136 // needs be
2137 int width = host.getMeasuredWidth();
2138 int height = host.getMeasuredHeight();
2139 boolean measureAgain = false;
Igor Murashkina86ab6402013-08-30 12:58:36 -07002140
Dianne Hackbornce418e62011-03-01 14:31:38 -08002141 if (lp.horizontalWeight > 0.0f) {
2142 width += (int) ((mWidth - width) * lp.horizontalWeight);
2143 childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width,
2144 MeasureSpec.EXACTLY);
2145 measureAgain = true;
2146 }
2147 if (lp.verticalWeight > 0.0f) {
2148 height += (int) ((mHeight - height) * lp.verticalWeight);
2149 childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
2150 MeasureSpec.EXACTLY);
2151 measureAgain = true;
2152 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07002153
Dianne Hackbornce418e62011-03-01 14:31:38 -08002154 if (measureAgain) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002155 if (DEBUG_LAYOUT) Log.v(mTag,
Dianne Hackbornce418e62011-03-01 14:31:38 -08002156 "And hey let's measure once more: width=" + width
2157 + " height=" + height);
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002158 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
Dianne Hackbornce418e62011-03-01 14:31:38 -08002159 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07002160
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002161 layoutRequested = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 }
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -07002164 } else {
2165 // Not the first pass and no window/insets/visibility change but the window
2166 // may have moved and we need check that and if so to update the left and right
2167 // in the attach info. We translate only the window frame since on window move
2168 // the window manager tells us only for the new frame but the insets are the
2169 // same and we do not want to translate them more than once.
Jorim Jaggi2e95a482016-01-14 17:36:55 -08002170 maybeHandleWindowMove(frame);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002171 }
2172
Craig Mautner72d6f212015-02-19 16:33:09 -08002173 final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002174 boolean triggerGlobalLayoutListener = didLayout
Chris Craikd36a81f2014-07-17 10:16:51 -07002175 || mAttachInfo.mRecomputeGlobalAttributes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176 if (didLayout) {
Jorim Jaggi26d02d22016-02-24 18:37:51 -05002177 performLayout(lp, mWidth, mHeight);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178
Mathias Agopian54e3d3842013-04-12 15:13:12 -07002179 // By this point all views have been sized and positioned
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 // We can compute the transparent area
2181
Dianne Hackborn4702a852012-08-17 15:18:29 -07002182 if ((host.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183 // start out transparent
2184 // TODO: AVOID THAT CALL BY CACHING THE RESULT?
2185 host.getLocationInWindow(mTmpLocation);
2186 mTransparentRegion.set(mTmpLocation[0], mTmpLocation[1],
2187 mTmpLocation[0] + host.mRight - host.mLeft,
2188 mTmpLocation[1] + host.mBottom - host.mTop);
2189
2190 host.gatherTransparentRegion(mTransparentRegion);
Mitsuru Oshima64f59342009-06-21 00:03:11 -07002191 if (mTranslator != null) {
2192 mTranslator.translateRegionInWindowToScreen(mTransparentRegion);
2193 }
2194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002195 if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {
2196 mPreviousTransparentRegion.set(mTransparentRegion);
Mathias Agopian54e3d3842013-04-12 15:13:12 -07002197 mFullRedrawNeeded = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 // reconfigure window manager
2199 try {
Jeff Brown98365d72012-08-19 20:30:52 -07002200 mWindowSession.setTransparentRegion(mWindow, mTransparentRegion);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002201 } catch (RemoteException e) {
2202 }
2203 }
2204 }
2205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206 if (DBG) {
2207 System.out.println("======================================");
Chet Haase4610eef2015-12-03 07:38:11 -08002208 System.out.println("performTraversals -- after setFrame");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002209 host.debug();
2210 }
2211 }
2212
2213 if (triggerGlobalLayoutListener) {
Chris Craikd36a81f2014-07-17 10:16:51 -07002214 mAttachInfo.mRecomputeGlobalAttributes = false;
2215 mAttachInfo.mTreeObserver.dispatchOnGlobalLayout();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216 }
2217
2218 if (computesInternalInsets) {
Jeff Brownfbf09772011-01-16 14:06:57 -08002219 // Clear the original insets.
Chris Craikd36a81f2014-07-17 10:16:51 -07002220 final ViewTreeObserver.InternalInsetsInfo insets = mAttachInfo.mGivenInternalInsets;
Jeff Brownfbf09772011-01-16 14:06:57 -08002221 insets.reset();
2222
2223 // Compute new insets in place.
Chris Craikd36a81f2014-07-17 10:16:51 -07002224 mAttachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets);
2225 mAttachInfo.mHasNonEmptyGivenInternalInsets = !insets.isEmpty();
Jeff Brownfbf09772011-01-16 14:06:57 -08002226
2227 // Tell the window manager.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002228 if (insetsPending || !mLastGivenInsets.equals(insets)) {
2229 mLastGivenInsets.set(insets);
Jeff Brownfbf09772011-01-16 14:06:57 -08002230
2231 // Translate insets to screen coordinates if needed.
2232 final Rect contentInsets;
2233 final Rect visibleInsets;
2234 final Region touchableRegion;
2235 if (mTranslator != null) {
2236 contentInsets = mTranslator.getTranslatedContentInsets(insets.contentInsets);
2237 visibleInsets = mTranslator.getTranslatedVisibleInsets(insets.visibleInsets);
2238 touchableRegion = mTranslator.getTranslatedTouchableArea(insets.touchableRegion);
2239 } else {
2240 contentInsets = insets.contentInsets;
2241 visibleInsets = insets.visibleInsets;
2242 touchableRegion = insets.touchableRegion;
2243 }
2244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002245 try {
Jeff Brown98365d72012-08-19 20:30:52 -07002246 mWindowSession.setInsets(mWindow, insets.mTouchableInsets,
Jeff Brownfbf09772011-01-16 14:06:57 -08002247 contentInsets, visibleInsets, touchableRegion);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002248 } catch (RemoteException e) {
2249 }
2250 }
2251 }
Romain Guy8506ab42009-06-11 17:35:47 -07002252
Evan Rosky37df2db2017-01-24 16:35:52 -08002253 if (mFirst && sAlwaysAssignFocus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002254 // handle first focus request
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002255 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "First: mView.hasFocus()="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002256 + mView.hasFocus());
2257 if (mView != null) {
2258 if (!mView.hasFocus()) {
Evan Rosky53fcf112017-01-26 14:37:55 -08002259 mView.restoreDefaultFocus();
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002260 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "First: requested focused view="
Svetoslav Ganov149567f2013-01-08 15:23:34 -08002261 + mView.findFocus());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002262 } else {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002263 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "First: existing focused view="
Svetoslav Ganov149567f2013-01-08 15:23:34 -08002264 + mView.findFocus());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002265 }
2266 }
2267 }
2268
Alan Viverette64bf97a2015-09-18 16:42:00 -04002269 final boolean changedVisibility = (viewVisibilityChanged || mFirst) && isViewVisible;
2270 final boolean hasWindowFocus = mAttachInfo.mHasWindowFocus && isViewVisible;
2271 final boolean regainedFocus = hasWindowFocus && mLostWindowFocus;
2272 if (regainedFocus) {
2273 mLostWindowFocus = false;
2274 } else if (!hasWindowFocus && mHadWindowFocus) {
2275 mLostWindowFocus = true;
2276 }
2277
2278 if (changedVisibility || regainedFocus) {
Phil Weaver532c7992016-08-29 15:59:03 -07002279 // Toasts are presented as notifications - don't present them as windows as well
2280 boolean isToast = (mWindowAttributes == null) ? false
2281 : (mWindowAttributes.type == WindowManager.LayoutParams.TYPE_TOAST);
2282 if (!isToast) {
2283 host.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
2284 }
Alan Viverette64bf97a2015-09-18 16:42:00 -04002285 }
2286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002287 mFirst = false;
2288 mWillDrawSoon = false;
2289 mNewSurfaceNeeded = false;
Jorim Jaggi4846ee32016-01-07 17:39:12 +01002290 mActivityRelaunched = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002291 mViewVisibility = viewVisibility;
Alan Viverette64bf97a2015-09-18 16:42:00 -04002292 mHadWindowFocus = hasWindowFocus;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293
Alan Viverette64bf97a2015-09-18 16:42:00 -04002294 if (hasWindowFocus && !isInLocalFocusMode()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295 final boolean imTarget = WindowManager.LayoutParams
2296 .mayUseInputMethod(mWindowAttributes.flags);
2297 if (imTarget != mLastWasImTarget) {
2298 mLastWasImTarget = imTarget;
2299 InputMethodManager imm = InputMethodManager.peekInstance();
2300 if (imm != null && imTarget) {
Alan Viverette64bf97a2015-09-18 16:42:00 -04002301 imm.onPreWindowFocus(mView, hasWindowFocus);
Yohei Yukawa5f059652015-05-14 22:16:41 -07002302 imm.onPostWindowFocus(mView, mView.findFocus(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002303 mWindowAttributes.softInputMode,
2304 !mHasHadWindowFocus, mWindowAttributes.flags);
2305 }
2306 }
2307 }
Romain Guy8506ab42009-06-11 17:35:47 -07002308
Jeff Brown96e942d2011-11-30 19:55:01 -08002309 // Remember if we must report the next draw.
Jeff Brown98365d72012-08-19 20:30:52 -07002310 if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
Jeff Brown96e942d2011-11-30 19:55:01 -08002311 mReportNextDraw = true;
2312 }
2313
Alan Viverette64bf97a2015-09-18 16:42:00 -04002314 boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315
Jorim Jaggi75c21ca2016-03-28 19:26:09 -04002316 if (!cancelDraw && !newSurface) {
Chet Haase9c450412015-10-01 13:25:58 -07002317 if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
2318 for (int i = 0; i < mPendingTransitions.size(); ++i) {
2319 mPendingTransitions.get(i).startChangingAnimations();
Chet Haased56c6952011-09-07 08:46:23 -07002320 }
Chet Haase9c450412015-10-01 13:25:58 -07002321 mPendingTransitions.clear();
Chet Haased56c6952011-09-07 08:46:23 -07002322 }
Chet Haase9c450412015-10-01 13:25:58 -07002323
2324 performDraw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002325 } else {
Alan Viverette64bf97a2015-09-18 16:42:00 -04002326 if (isViewVisible) {
Chris Wren78cb7cf2012-05-15 12:36:44 -04002327 // Try again
2328 scheduleTraversals();
2329 } else if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
Chet Haased56c6952011-09-07 08:46:23 -07002330 for (int i = 0; i < mPendingTransitions.size(); ++i) {
2331 mPendingTransitions.get(i).endChangingAnimations();
2332 }
2333 mPendingTransitions.clear();
2334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002335 }
Craig Mautnerdf2390a2012-08-29 20:59:22 -07002336
2337 mIsInTraversal = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002338 }
2339
Jorim Jaggi2e95a482016-01-14 17:36:55 -08002340 private void maybeHandleWindowMove(Rect frame) {
2341
2342 // TODO: Well, we are checking whether the frame has changed similarly
2343 // to how this is done for the insets. This is however incorrect since
2344 // the insets and the frame are translated. For example, the old frame
2345 // was (1, 1 - 1, 1) and was translated to say (2, 2 - 2, 2), now the new
2346 // reported frame is (2, 2 - 2, 2) which implies no change but this is not
2347 // true since we are comparing a not translated value to a translated one.
2348 // This scenario is rare but we may want to fix that.
2349
2350 final boolean windowMoved = mAttachInfo.mWindowLeft != frame.left
2351 || mAttachInfo.mWindowTop != frame.top;
2352 if (windowMoved) {
2353 if (mTranslator != null) {
2354 mTranslator.translateRectInScreenToAppWinFrame(frame);
2355 }
2356 mAttachInfo.mWindowLeft = frame.left;
2357 mAttachInfo.mWindowTop = frame.top;
Teng-Hui Zhu27571282016-05-12 15:53:53 -07002358 }
2359 if (windowMoved || mAttachInfo.mNeedsUpdateLightCenter) {
2360 // Update the light position for the new offsets.
Stan Iliev45faba52016-06-28 13:33:15 -04002361 if (mAttachInfo.mThreadedRenderer != null) {
2362 mAttachInfo.mThreadedRenderer.setLightCenter(mAttachInfo);
Jorim Jaggi2e95a482016-01-14 17:36:55 -08002363 }
Teng-Hui Zhu27571282016-05-12 15:53:53 -07002364 mAttachInfo.mNeedsUpdateLightCenter = false;
Jorim Jaggi2e95a482016-01-14 17:36:55 -08002365 }
2366 }
Teng-Hui Zhu27571282016-05-12 15:53:53 -07002367
Romain Guy3696779b2013-01-28 14:04:07 -08002368 private void handleOutOfResourcesException(Surface.OutOfResourcesException e) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002369 Log.e(mTag, "OutOfResourcesException initializing HW surface", e);
Romain Guy3696779b2013-01-28 14:04:07 -08002370 try {
2371 if (!mWindowSession.outOfMemory(mWindow) &&
2372 Process.myUid() != Process.SYSTEM_UID) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002373 Slog.w(mTag, "No processes killed for memory; killing self");
Romain Guy3696779b2013-01-28 14:04:07 -08002374 Process.killProcess(Process.myPid());
2375 }
2376 } catch (RemoteException ex) {
2377 }
2378 mLayoutRequested = true; // ask wm for a new surface next time.
2379 }
2380
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002381 private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
2382 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
2383 try {
2384 mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
2385 } finally {
2386 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
2387 }
2388 }
2389
Chet Haase97140572012-09-13 14:56:47 -07002390 /**
2391 * Called by {@link android.view.View#isInLayout()} to determine whether the view hierarchy
2392 * is currently undergoing a layout pass.
2393 *
2394 * @return whether the view hierarchy is currently undergoing a layout pass
2395 */
2396 boolean isInLayout() {
2397 return mInLayout;
2398 }
2399
2400 /**
Chet Haasecc699b42012-12-13 09:06:55 -08002401 * Called by {@link android.view.View#requestLayout()} if the view hierarchy is currently
2402 * undergoing a layout pass. requestLayout() should not generally be called during layout,
2403 * unless the container hierarchy knows what it is doing (i.e., it is fine as long as
2404 * all children in that container hierarchy are measured and laid out at the end of the layout
2405 * pass for that container). If requestLayout() is called anyway, we handle it correctly
2406 * by registering all requesters during a frame as it proceeds. At the end of the frame,
2407 * we check all of those views to see if any still have pending layout requests, which
2408 * indicates that they were not correctly handled by their container hierarchy. If that is
2409 * the case, we clear all such flags in the tree, to remove the buggy flag state that leads
2410 * to blank containers, and force a second request/measure/layout pass in this frame. If
Chet Haase97140572012-09-13 14:56:47 -07002411 * more requestLayout() calls are received during that second layout pass, we post those
Chet Haasecc699b42012-12-13 09:06:55 -08002412 * requests to the next frame to avoid possible infinite loops.
2413 *
2414 * <p>The return value from this method indicates whether the request should proceed
2415 * (if it is a request during the first layout pass) or should be skipped and posted to the
2416 * next frame (if it is a request during the second layout pass).</p>
Chet Haase97140572012-09-13 14:56:47 -07002417 *
2418 * @param view the view that requested the layout.
Chet Haasecc699b42012-12-13 09:06:55 -08002419 *
2420 * @return true if request should proceed, false otherwise.
Chet Haase97140572012-09-13 14:56:47 -07002421 */
Chet Haasecc699b42012-12-13 09:06:55 -08002422 boolean requestLayoutDuringLayout(final View view) {
2423 if (view.mParent == null || view.mAttachInfo == null) {
2424 // Would not normally trigger another layout, so just let it pass through as usual
2425 return true;
2426 }
Chet Haase107a4822013-03-13 06:46:50 -07002427 if (!mLayoutRequesters.contains(view)) {
2428 mLayoutRequesters.add(view);
2429 }
Chet Haase97140572012-09-13 14:56:47 -07002430 if (!mHandlingLayoutInLayoutRequest) {
Chet Haase107a4822013-03-13 06:46:50 -07002431 // Let the request proceed normally; it will be processed in a second layout pass
2432 // if necessary
Chet Haasecc699b42012-12-13 09:06:55 -08002433 return true;
Chet Haase97140572012-09-13 14:56:47 -07002434 } else {
Chet Haase107a4822013-03-13 06:46:50 -07002435 // Don't let the request proceed during the second layout pass.
2436 // It will post to the next frame instead.
Chet Haasecc699b42012-12-13 09:06:55 -08002437 return false;
Chet Haase97140572012-09-13 14:56:47 -07002438 }
2439 }
2440
Chet Haase3efa7b52012-12-03 08:33:17 -08002441 private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,
2442 int desiredWindowHeight) {
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002443 mLayoutRequested = false;
2444 mScrollMayChange = true;
Chet Haase97140572012-09-13 14:56:47 -07002445 mInLayout = true;
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002446
2447 final View host = mView;
2448 if (DEBUG_ORIENTATION || DEBUG_LAYOUT) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002449 Log.v(mTag, "Laying out " + host + " to (" +
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002450 host.getMeasuredWidth() + ", " + host.getMeasuredHeight() + ")");
2451 }
2452
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002453 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "layout");
2454 try {
2455 host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
Chet Haasecc699b42012-12-13 09:06:55 -08002456
Chet Haased5a83522012-11-21 16:24:44 -08002457 mInLayout = false;
Chet Haase97140572012-09-13 14:56:47 -07002458 int numViewsRequestingLayout = mLayoutRequesters.size();
2459 if (numViewsRequestingLayout > 0) {
Chet Haasecc699b42012-12-13 09:06:55 -08002460 // requestLayout() was called during layout.
2461 // If no layout-request flags are set on the requesting views, there is no problem.
2462 // If some requests are still pending, then we need to clear those flags and do
2463 // a full request/measure/layout pass to handle this situation.
Chet Haase107a4822013-03-13 06:46:50 -07002464 ArrayList<View> validLayoutRequesters = getValidLayoutRequesters(mLayoutRequesters,
2465 false);
2466 if (validLayoutRequesters != null) {
2467 // Set this flag to indicate that any further requests are happening during
2468 // the second pass, which may result in posting those requests to the next
2469 // frame instead
Chet Haasecc699b42012-12-13 09:06:55 -08002470 mHandlingLayoutInLayoutRequest = true;
Chet Haase107a4822013-03-13 06:46:50 -07002471
2472 // Process fresh layout requests, then measure and layout
2473 int numValidRequests = validLayoutRequesters.size();
Chet Haasecc699b42012-12-13 09:06:55 -08002474 for (int i = 0; i < numValidRequests; ++i) {
Chet Haase107a4822013-03-13 06:46:50 -07002475 final View view = validLayoutRequesters.get(i);
2476 Log.w("View", "requestLayout() improperly called by " + view +
2477 " during layout: running second layout pass");
2478 view.requestLayout();
Chet Haasecc699b42012-12-13 09:06:55 -08002479 }
2480 measureHierarchy(host, lp, mView.getContext().getResources(),
2481 desiredWindowWidth, desiredWindowHeight);
2482 mInLayout = true;
2483 host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
Chet Haase107a4822013-03-13 06:46:50 -07002484
Chet Haasecc699b42012-12-13 09:06:55 -08002485 mHandlingLayoutInLayoutRequest = false;
Chet Haase107a4822013-03-13 06:46:50 -07002486
2487 // Check the valid requests again, this time without checking/clearing the
2488 // layout flags, since requests happening during the second pass get noop'd
2489 validLayoutRequesters = getValidLayoutRequesters(mLayoutRequesters, true);
2490 if (validLayoutRequesters != null) {
2491 final ArrayList<View> finalRequesters = validLayoutRequesters;
2492 // Post second-pass requests to the next frame
2493 getRunQueue().post(new Runnable() {
2494 @Override
2495 public void run() {
2496 int numValidRequests = finalRequesters.size();
2497 for (int i = 0; i < numValidRequests; ++i) {
2498 final View view = finalRequesters.get(i);
2499 Log.w("View", "requestLayout() improperly called by " + view +
2500 " during second layout pass: posting in next frame");
2501 view.requestLayout();
2502 }
2503 }
2504 });
2505 }
Chet Haasecc699b42012-12-13 09:06:55 -08002506 }
Chet Haase107a4822013-03-13 06:46:50 -07002507
Chet Haase97140572012-09-13 14:56:47 -07002508 }
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002509 } finally {
2510 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
2511 }
Chet Haase97140572012-09-13 14:56:47 -07002512 mInLayout = false;
Jeff Brownc8d2668b2012-05-16 17:23:59 -07002513 }
2514
Chet Haase107a4822013-03-13 06:46:50 -07002515 /**
2516 * This method is called during layout when there have been calls to requestLayout() during
2517 * layout. It walks through the list of views that requested layout to determine which ones
2518 * still need it, based on visibility in the hierarchy and whether they have already been
2519 * handled (as is usually the case with ListView children).
2520 *
2521 * @param layoutRequesters The list of views that requested layout during layout
2522 * @param secondLayoutRequests Whether the requests were issued during the second layout pass.
2523 * If so, the FORCE_LAYOUT flag was not set on requesters.
2524 * @return A list of the actual views that still need to be laid out.
2525 */
2526 private ArrayList<View> getValidLayoutRequesters(ArrayList<View> layoutRequesters,
2527 boolean secondLayoutRequests) {
2528
2529 int numViewsRequestingLayout = layoutRequesters.size();
2530 ArrayList<View> validLayoutRequesters = null;
2531 for (int i = 0; i < numViewsRequestingLayout; ++i) {
2532 View view = layoutRequesters.get(i);
2533 if (view != null && view.mAttachInfo != null && view.mParent != null &&
2534 (secondLayoutRequests || (view.mPrivateFlags & View.PFLAG_FORCE_LAYOUT) ==
2535 View.PFLAG_FORCE_LAYOUT)) {
2536 boolean gone = false;
2537 View parent = view;
2538 // Only trigger new requests for views in a non-GONE hierarchy
2539 while (parent != null) {
2540 if ((parent.mViewFlags & View.VISIBILITY_MASK) == View.GONE) {
2541 gone = true;
2542 break;
2543 }
2544 if (parent.mParent instanceof View) {
2545 parent = (View) parent.mParent;
2546 } else {
2547 parent = null;
2548 }
2549 }
2550 if (!gone) {
2551 if (validLayoutRequesters == null) {
2552 validLayoutRequesters = new ArrayList<View>();
2553 }
2554 validLayoutRequesters.add(view);
2555 }
2556 }
2557 }
2558 if (!secondLayoutRequests) {
2559 // If we're checking the layout flags, then we need to clean them up also
2560 for (int i = 0; i < numViewsRequestingLayout; ++i) {
2561 View view = layoutRequesters.get(i);
2562 while (view != null &&
2563 (view.mPrivateFlags & View.PFLAG_FORCE_LAYOUT) != 0) {
2564 view.mPrivateFlags &= ~View.PFLAG_FORCE_LAYOUT;
2565 if (view.mParent instanceof View) {
2566 view = (View) view.mParent;
2567 } else {
2568 view = null;
2569 }
2570 }
2571 }
2572 }
2573 layoutRequesters.clear();
2574 return validLayoutRequesters;
2575 }
2576
Igor Murashkina86ab6402013-08-30 12:58:36 -07002577 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002578 public void requestTransparentRegion(View child) {
2579 // the test below should not fail unless someone is messing with us
2580 checkThread();
2581 if (mView == child) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07002582 mView.mPrivateFlags |= View.PFLAG_REQUEST_TRANSPARENT_REGIONS;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002583 // Need to make sure we re-evaluate the window attributes next
2584 // time around, to ensure the window has the correct format.
2585 mWindowAttributesChanged = true;
Romain Guyf21c9b02011-09-06 16:56:54 -07002586 mWindowAttributesChangesFlag = 0;
Mathias Agopian1bd80ad2010-11-04 17:13:39 -07002587 requestLayout();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002588 }
2589 }
2590
2591 /**
2592 * Figures out the measure spec for the root view in a window based on it's
2593 * layout params.
2594 *
2595 * @param windowSize
2596 * The available width or height of the window
2597 *
2598 * @param rootDimension
2599 * The layout params for one dimension (width or height) of the
2600 * window.
2601 *
2602 * @return The measure spec to use to measure the root view.
2603 */
Romain Guya998dff2012-03-23 18:58:36 -07002604 private static int getRootMeasureSpec(int windowSize, int rootDimension) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 int measureSpec;
2606 switch (rootDimension) {
2607
Romain Guy980a9382010-01-08 15:06:28 -08002608 case ViewGroup.LayoutParams.MATCH_PARENT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002609 // Window can't resize. Force root view to be windowSize.
2610 measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY);
2611 break;
2612 case ViewGroup.LayoutParams.WRAP_CONTENT:
2613 // Window can resize. Set max size for root view.
2614 measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST);
2615 break;
2616 default:
2617 // Window wants to be an exact size. Force root view to be that size.
2618 measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);
2619 break;
2620 }
2621 return measureSpec;
2622 }
2623
Alan Viveretteccb11e12014-07-08 16:04:02 -07002624 int mHardwareXOffset;
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002625 int mHardwareYOffset;
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002626
Igor Murashkina86ab6402013-08-30 12:58:36 -07002627 @Override
Stan Iliev45faba52016-06-28 13:33:15 -04002628 public void onPreDraw(DisplayListCanvas canvas) {
Alan Viveretteccb11e12014-07-08 16:04:02 -07002629 canvas.translate(-mHardwareXOffset, -mHardwareYOffset);
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002630 }
2631
Igor Murashkina86ab6402013-08-30 12:58:36 -07002632 @Override
Stan Iliev45faba52016-06-28 13:33:15 -04002633 public void onPostDraw(DisplayListCanvas canvas) {
Alan Viverette632af842014-10-28 13:45:11 -07002634 drawAccessibilityFocusedDrawableIfNeeded(canvas);
Jorim Jaggi16b63192016-03-25 18:32:19 -07002635 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
2636 mWindowCallbacks.get(i).onPostDraw(canvas);
Jorim Jaggic39c7b02016-03-24 10:47:07 -07002637 }
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002638 }
2639
Chet Haaseed30fd82011-04-22 16:18:45 -07002640 /**
2641 * @hide
2642 */
2643 void outputDisplayList(View view) {
Chris Craik356b5fe2015-07-07 10:39:36 -07002644 view.mRenderNode.output();
Stan Iliev45faba52016-06-28 13:33:15 -04002645 if (mAttachInfo.mThreadedRenderer != null) {
2646 ((ThreadedRenderer)mAttachInfo.mThreadedRenderer).serializeDisplayListTree();
John Recke248bd12015-08-05 13:53:53 -07002647 }
Romain Guy59a12ca2011-06-09 17:48:21 -07002648 }
2649
2650 /**
2651 * @see #PROPERTY_PROFILE_RENDERING
2652 */
2653 private void profileRendering(boolean enabled) {
2654 if (mProfileRendering) {
2655 mRenderProfilingEnabled = enabled;
Chris Craikae4f32042013-02-07 12:57:10 -08002656
2657 if (mRenderProfiler != null) {
2658 mChoreographer.removeFrameCallback(mRenderProfiler);
2659 }
2660 if (mRenderProfilingEnabled) {
2661 if (mRenderProfiler == null) {
2662 mRenderProfiler = new Choreographer.FrameCallback() {
2663 @Override
2664 public void doFrame(long frameTimeNanos) {
2665 mDirty.set(0, 0, mWidth, mHeight);
2666 scheduleTraversals();
2667 if (mRenderProfilingEnabled) {
2668 mChoreographer.postFrameCallback(mRenderProfiler);
2669 }
Romain Guy59a12ca2011-06-09 17:48:21 -07002670 }
Chris Craikae4f32042013-02-07 12:57:10 -08002671 };
2672 }
Romain Guy5bb3c732012-11-29 17:52:58 -08002673 mChoreographer.postFrameCallback(mRenderProfiler);
Romain Guy59a12ca2011-06-09 17:48:21 -07002674 } else {
Romain Guy59a12ca2011-06-09 17:48:21 -07002675 mRenderProfiler = null;
Chet Haaseed30fd82011-04-22 16:18:45 -07002676 }
2677 }
2678 }
2679
Chet Haase2f2022a2011-10-11 06:41:59 -07002680 /**
2681 * Called from draw() when DEBUG_FPS is enabled
2682 */
2683 private void trackFPS() {
2684 // Tracks frames per second drawn. First value in a series of draws may be bogus
2685 // because it down not account for the intervening idle time
2686 long nowTime = System.currentTimeMillis();
2687 if (mFpsStartTime < 0) {
2688 mFpsStartTime = mFpsPrevTime = nowTime;
2689 mFpsNumFrames = 0;
2690 } else {
2691 ++mFpsNumFrames;
2692 String thisHash = Integer.toHexString(System.identityHashCode(this));
2693 long frameTime = nowTime - mFpsPrevTime;
2694 long totalTime = nowTime - mFpsStartTime;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002695 Log.v(mTag, "0x" + thisHash + "\tFrame time:\t" + frameTime);
Chet Haase2f2022a2011-10-11 06:41:59 -07002696 mFpsPrevTime = nowTime;
2697 if (totalTime > 1000) {
2698 float fps = (float) mFpsNumFrames * 1000 / totalTime;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002699 Log.v(mTag, "0x" + thisHash + "\tFPS:\t" + fps);
Chet Haase2f2022a2011-10-11 06:41:59 -07002700 mFpsStartTime = nowTime;
2701 mFpsNumFrames = 0;
2702 }
2703 }
2704 }
2705
Robert Carr8508bb22017-03-27 15:46:27 -07002706 /**
2707 * A count of the number of calls to pendingDrawFinished we
2708 * require to notify the WM drawing is complete.
2709 *
2710 * This starts at 1, for the ViewRootImpl surface itself.
2711 * Subsurfaces may debt the value with drawPending.
2712 */
2713 int mDrawsNeededToReport = 1;
2714
2715 /**
2716 * Delay notifying WM of draw finished until
2717 * a balanced call to pendingDrawFinished.
2718 */
2719 void drawPending() {
2720 mDrawsNeededToReport++;
2721 }
2722
2723 void pendingDrawFinished() {
2724 if (mDrawsNeededToReport == 0) {
2725 throw new RuntimeException("Unbalanced drawPending/pendingDrawFinished calls");
2726 }
2727 mDrawsNeededToReport--;
2728 if (mDrawsNeededToReport == 0) {
2729 reportDrawFinished();
2730 }
2731 }
2732
2733 private void postDrawFinished() {
2734 mHandler.sendEmptyMessage(MSG_DRAW_FINISHED);
2735 }
2736
2737 private void reportDrawFinished() {
Robert Carrd5c7dd62017-03-08 10:39:30 -08002738 try {
Robert Carr8508bb22017-03-27 15:46:27 -07002739 mDrawsNeededToReport = 1;
Robert Carrd5c7dd62017-03-08 10:39:30 -08002740 mWindowSession.finishDrawing(mWindow);
2741 } catch (RemoteException e) {
2742 // Have fun!
2743 }
2744 }
2745
Jeff Brown96e942d2011-11-30 19:55:01 -08002746 private void performDraw() {
Jeff Brownd912e1f2014-04-11 18:46:22 -07002747 if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
Craig Mautner006f0e42012-03-21 11:00:32 -07002748 return;
2749 }
Romain Guy7e4e5612012-03-05 14:37:29 -08002750
Jeff Brown96e942d2011-11-30 19:55:01 -08002751 final boolean fullRedrawNeeded = mFullRedrawNeeded;
2752 mFullRedrawNeeded = false;
Jeff Brown481c1572012-03-09 14:41:15 -08002753
Romain Guy1f59e5c2012-05-06 14:11:16 -07002754 mIsDrawing = true;
Jeff Brown481c1572012-03-09 14:41:15 -08002755 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
2756 try {
2757 draw(fullRedrawNeeded);
2758 } finally {
Romain Guy1f59e5c2012-05-06 14:11:16 -07002759 mIsDrawing = false;
Jeff Brown481c1572012-03-09 14:41:15 -08002760 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
2761 }
Jeff Brown96e942d2011-11-30 19:55:01 -08002762
John Reck119907c2014-08-14 09:02:01 -07002763 // For whatever reason we didn't create a HardwareRenderer, end any
2764 // hardware animations that are now dangling
2765 if (mAttachInfo.mPendingAnimatingRenderNodes != null) {
2766 final int count = mAttachInfo.mPendingAnimatingRenderNodes.size();
2767 for (int i = 0; i < count; i++) {
2768 mAttachInfo.mPendingAnimatingRenderNodes.get(i).endAllAnimators();
2769 }
2770 mAttachInfo.mPendingAnimatingRenderNodes.clear();
2771 }
2772
Jeff Brown96e942d2011-11-30 19:55:01 -08002773 if (mReportNextDraw) {
2774 mReportNextDraw = false;
Chong Zhang8dbd9ad2015-10-09 10:06:11 -07002775
2776 // if we're using multi-thread renderer, wait for the window frame draws
2777 if (mWindowDrawCountDown != null) {
2778 try {
2779 mWindowDrawCountDown.await();
2780 } catch (InterruptedException e) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002781 Log.e(mTag, "Window redraw count down interruped!");
Chong Zhang8dbd9ad2015-10-09 10:06:11 -07002782 }
2783 mWindowDrawCountDown = null;
2784 }
2785
Stan Iliev45faba52016-06-28 13:33:15 -04002786 if (mAttachInfo.mThreadedRenderer != null) {
2787 mAttachInfo.mThreadedRenderer.fence();
2788 mAttachInfo.mThreadedRenderer.setStopped(mStopped);
John Reck28ad7b52014-04-07 16:59:25 -07002789 }
Jeff Brown96e942d2011-11-30 19:55:01 -08002790
2791 if (LOCAL_LOGV) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002792 Log.v(mTag, "FINISHED DRAWING: " + mWindowAttributes.getTitle());
Jeff Brown96e942d2011-11-30 19:55:01 -08002793 }
Robert Carr25cfa132016-11-16 13:24:09 -08002794
Jeff Brown96e942d2011-11-30 19:55:01 -08002795 if (mSurfaceHolder != null && mSurface.isValid()) {
Robert Carr8508bb22017-03-27 15:46:27 -07002796 SurfaceCallbackHelper sch = new SurfaceCallbackHelper(this::postDrawFinished);
Jeff Brown96e942d2011-11-30 19:55:01 -08002797 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
Robert Carr25cfa132016-11-16 13:24:09 -08002798
2799 sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
2800 } else {
Robert Carr8508bb22017-03-27 15:46:27 -07002801 pendingDrawFinished();
Jeff Brown96e942d2011-11-30 19:55:01 -08002802 }
Jeff Brown96e942d2011-11-30 19:55:01 -08002803 }
2804 }
2805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002806 private void draw(boolean fullRedrawNeeded) {
2807 Surface surface = mSurface;
Romain Guyfbb93fa2012-12-03 18:50:35 -08002808 if (!surface.isValid()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002809 return;
2810 }
2811
Chet Haase2f2022a2011-10-11 06:41:59 -07002812 if (DEBUG_FPS) {
2813 trackFPS();
2814 }
2815
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002816 if (!sFirstDrawComplete) {
2817 synchronized (sFirstDrawHandlers) {
2818 sFirstDrawComplete = true;
Romain Guy812ccbe2010-06-01 14:07:24 -07002819 final int count = sFirstDrawHandlers.size();
2820 for (int i = 0; i< count; i++) {
Jeff Browna175a5b2012-02-15 19:18:31 -08002821 mHandler.post(sFirstDrawHandlers.get(i));
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002822 }
2823 }
2824 }
Romain Guy59a12ca2011-06-09 17:48:21 -07002825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826 scrollToRectOrFocus(null, false);
2827
Chris Craikd36a81f2014-07-17 10:16:51 -07002828 if (mAttachInfo.mViewScrollChanged) {
2829 mAttachInfo.mViewScrollChanged = false;
2830 mAttachInfo.mTreeObserver.dispatchOnScrollChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002831 }
Romain Guy8506ab42009-06-11 17:35:47 -07002832
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002833 boolean animating = mScroller != null && mScroller.computeScrollOffset();
Alan Viveretteccb11e12014-07-08 16:04:02 -07002834 final int curScrollY;
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002835 if (animating) {
Alan Viveretteccb11e12014-07-08 16:04:02 -07002836 curScrollY = mScroller.getCurrY();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002837 } else {
Alan Viveretteccb11e12014-07-08 16:04:02 -07002838 curScrollY = mScrollY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002839 }
Alan Viveretteccb11e12014-07-08 16:04:02 -07002840 if (mCurScrollY != curScrollY) {
2841 mCurScrollY = curScrollY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002842 fullRedrawNeeded = true;
Adrian Roos0e7ae4e2014-10-01 15:33:22 +02002843 if (mView instanceof RootViewSurfaceTaker) {
2844 ((RootViewSurfaceTaker) mView).onRootViewScrollYChanged(mCurScrollY);
2845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002846 }
Jeff Brown96e942d2011-11-30 19:55:01 -08002847
Chris Craikd36a81f2014-07-17 10:16:51 -07002848 final float appScale = mAttachInfo.mApplicationScale;
2849 final boolean scalingRequired = mAttachInfo.mScalingRequired;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002850
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002851 int resizeAlpha = 0;
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002852
Jeff Brown96e942d2011-11-30 19:55:01 -08002853 final Rect dirty = mDirty;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07002854 if (mSurfaceHolder != null) {
2855 // The app owns the surface, we won't draw.
2856 dirty.setEmpty();
Derek Sollenberger8d948352015-07-16 09:27:59 -04002857 if (animating && mScroller != null) {
2858 mScroller.abortAnimation();
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002859 }
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07002860 return;
2861 }
Romain Guy58ef7fb2010-09-13 12:52:37 -07002862
2863 if (fullRedrawNeeded) {
Chris Craikd36a81f2014-07-17 10:16:51 -07002864 mAttachInfo.mIgnoreDirtyState = true;
Romain Guyc3166e12011-08-08 15:00:03 -07002865 dirty.set(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
Romain Guy58ef7fb2010-09-13 12:52:37 -07002866 }
Chet Haasead4f7032011-06-22 09:18:31 -07002867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002868 if (DEBUG_ORIENTATION || DEBUG_DRAW) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002869 Log.v(mTag, "Draw " + mView + "/"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002870 + mWindowAttributes.getTitle()
2871 + ": dirty={" + dirty.left + "," + dirty.top
2872 + "," + dirty.right + "," + dirty.bottom + "} surface="
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002873 + surface + " surface.isValid()=" + surface.isValid() + ", appScale:" +
2874 appScale + ", width=" + mWidth + ", height=" + mHeight);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002875 }
2876
Chris Craikd36a81f2014-07-17 10:16:51 -07002877 mAttachInfo.mTreeObserver.dispatchOnDraw();
Romain Guy25eba5c2012-04-04 17:29:03 -07002878
Chong Zhang0275e392015-09-17 10:41:44 -07002879 int xOffset = -mCanvasOffsetX;
2880 int yOffset = -mCanvasOffsetY + curScrollY;
Alan Viverettea51cab92014-07-16 15:15:49 -07002881 final WindowManager.LayoutParams params = mWindowAttributes;
2882 final Rect surfaceInsets = params != null ? params.surfaceInsets : null;
2883 if (surfaceInsets != null) {
2884 xOffset -= surfaceInsets.left;
2885 yOffset -= surfaceInsets.top;
2886
2887 // Offset dirty rect for surface insets.
2888 dirty.offset(surfaceInsets.left, surfaceInsets.right);
2889 }
2890
Alan Viverette632af842014-10-28 13:45:11 -07002891 boolean accessibilityFocusDirty = false;
2892 final Drawable drawable = mAttachInfo.mAccessibilityFocusDrawable;
2893 if (drawable != null) {
2894 final Rect bounds = mAttachInfo.mTmpInvalRect;
2895 final boolean hasFocus = getAccessibilityFocusedRect(bounds);
2896 if (!hasFocus) {
2897 bounds.setEmpty();
2898 }
2899 if (!bounds.equals(drawable.getBounds())) {
2900 accessibilityFocusDirty = true;
2901 }
2902 }
2903
John Reckba6adf62015-02-19 14:36:50 -08002904 mAttachInfo.mDrawingTime =
2905 mChoreographer.getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;
2906
Alan Viverette632af842014-10-28 13:45:11 -07002907 if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
Stan Iliev45faba52016-06-28 13:33:15 -04002908 if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) {
Alan Viverette632af842014-10-28 13:45:11 -07002909 // If accessibility focus moved, always invalidate the root.
Jorim Jaggic39c7b02016-03-24 10:47:07 -07002910 boolean invalidateRoot = accessibilityFocusDirty || mInvalidateRootRequested;
2911 mInvalidateRootRequested = false;
Alan Viverette632af842014-10-28 13:45:11 -07002912
Jeff Brown96e942d2011-11-30 19:55:01 -08002913 // Draw with hardware renderer.
2914 mIsAnimating = false;
Alan Viverette632af842014-10-28 13:45:11 -07002915
John Reck0a973302014-07-16 13:29:45 -07002916 if (mHardwareYOffset != yOffset || mHardwareXOffset != xOffset) {
2917 mHardwareYOffset = yOffset;
2918 mHardwareXOffset = xOffset;
Alan Viverette632af842014-10-28 13:45:11 -07002919 invalidateRoot = true;
Alan Viverettef6cf1a02014-08-11 14:13:02 -07002920 }
2921
Alan Viverette632af842014-10-28 13:45:11 -07002922 if (invalidateRoot) {
Stan Iliev45faba52016-06-28 13:33:15 -04002923 mAttachInfo.mThreadedRenderer.invalidateRoot();
Alan Viverette632af842014-10-28 13:45:11 -07002924 }
2925
Jeff Brown96e942d2011-11-30 19:55:01 -08002926 dirty.setEmpty();
2927
Skuhne980ee472015-10-06 11:31:31 -07002928 // Stage the content drawn size now. It will be transferred to the renderer
2929 // shortly before the draw commands get send to the renderer.
Chong Zhang8dbd9ad2015-10-09 10:06:11 -07002930 final boolean updated = updateContentDrawBounds();
2931
John Reck8afcc762016-04-13 10:24:06 -07002932 if (mReportNextDraw) {
2933 // report next draw overrides setStopped()
2934 // This value is re-sync'd to the value of mStopped
2935 // in the handling of mReportNextDraw post-draw.
Stan Iliev45faba52016-06-28 13:33:15 -04002936 mAttachInfo.mThreadedRenderer.setStopped(false);
John Reck8afcc762016-04-13 10:24:06 -07002937 }
2938
Chong Zhang8dbd9ad2015-10-09 10:06:11 -07002939 if (updated) {
2940 requestDrawWindow();
2941 }
Jorim Jaggi0d6222d2016-04-18 20:42:10 -07002942
Stan Iliev45faba52016-06-28 13:33:15 -04002943 mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this);
Romain Guy3696779b2013-01-28 14:04:07 -08002944 } else {
2945 // If we get here with a disabled & requested hardware renderer, something went
2946 // wrong (an invalidate posted right before we destroyed the hardware surface
2947 // for instance) so we should just bail out. Locking the surface with software
2948 // rendering at this point would lock it forever and prevent hardware renderer
2949 // from doing its job when it comes back.
2950 // Before we request a new frame we must however attempt to reinitiliaze the
2951 // hardware renderer if it's in requested state. This would happen after an
2952 // eglTerminate() for instance.
Stan Iliev45faba52016-06-28 13:33:15 -04002953 if (mAttachInfo.mThreadedRenderer != null &&
2954 !mAttachInfo.mThreadedRenderer.isEnabled() &&
2955 mAttachInfo.mThreadedRenderer.isRequested()) {
Romain Guy3696779b2013-01-28 14:04:07 -08002956
2957 try {
Stan Iliev45faba52016-06-28 13:33:15 -04002958 mAttachInfo.mThreadedRenderer.initializeIfNeeded(
Alan Viverette50210d92015-05-14 18:05:36 -07002959 mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets);
Igor Murashkina86ab6402013-08-30 12:58:36 -07002960 } catch (OutOfResourcesException e) {
Romain Guy3696779b2013-01-28 14:04:07 -08002961 handleOutOfResourcesException(e);
2962 return;
2963 }
2964
2965 mFullRedrawNeeded = true;
2966 scheduleTraversals();
2967 return;
2968 }
2969
Chris Craikd36a81f2014-07-17 10:16:51 -07002970 if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
Romain Guy3696779b2013-01-28 14:04:07 -08002971 return;
2972 }
Jeff Brown95db2b22011-11-30 19:54:41 -08002973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002974 }
Romain Guy8506ab42009-06-11 17:35:47 -07002975
Dianne Hackborn0f761d62010-11-30 22:06:10 -08002976 if (animating) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002977 mFullRedrawNeeded = true;
2978 scheduleTraversals();
2979 }
2980 }
2981
Romain Guy25eba5c2012-04-04 17:29:03 -07002982 /**
Alan Viveretteccb11e12014-07-08 16:04:02 -07002983 * @return true if drawing was successful, false if an error occurred
Romain Guy25eba5c2012-04-04 17:29:03 -07002984 */
Alan Viveretteccb11e12014-07-08 16:04:02 -07002985 private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
Romain Guy25eba5c2012-04-04 17:29:03 -07002986 boolean scalingRequired, Rect dirty) {
2987
2988 // Draw with software renderer.
Alan Viverettea51cab92014-07-16 15:15:49 -07002989 final Canvas canvas;
Romain Guy25eba5c2012-04-04 17:29:03 -07002990 try {
Alan Viverettea51cab92014-07-16 15:15:49 -07002991 final int left = dirty.left;
2992 final int top = dirty.top;
2993 final int right = dirty.right;
2994 final int bottom = dirty.bottom;
Romain Guy25eba5c2012-04-04 17:29:03 -07002995
Romain Guy25eba5c2012-04-04 17:29:03 -07002996 canvas = mSurface.lockCanvas(dirty);
2997
Romain Guye55945e2013-04-04 15:26:04 -07002998 // The dirty rectangle can be modified by Surface.lockCanvas()
2999 //noinspection ConstantConditions
Alan Viverettea51cab92014-07-16 15:15:49 -07003000 if (left != dirty.left || top != dirty.top || right != dirty.right
3001 || bottom != dirty.bottom) {
Romain Guy25eba5c2012-04-04 17:29:03 -07003002 attachInfo.mIgnoreDirtyState = true;
3003 }
3004
3005 // TODO: Do this in native
3006 canvas.setDensity(mDensity);
3007 } catch (Surface.OutOfResourcesException e) {
Romain Guy3696779b2013-01-28 14:04:07 -08003008 handleOutOfResourcesException(e);
Romain Guy25eba5c2012-04-04 17:29:03 -07003009 return false;
3010 } catch (IllegalArgumentException e) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003011 Log.e(mTag, "Could not lock surface", e);
Romain Guy25eba5c2012-04-04 17:29:03 -07003012 // Don't assume this is due to out of memory, it could be
3013 // something else, and if it is something else then we could
3014 // kill stuff (or ourself) for no reason.
3015 mLayoutRequested = true; // ask wm for a new surface next time.
3016 return false;
3017 }
3018
3019 try {
3020 if (DEBUG_ORIENTATION || DEBUG_DRAW) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003021 Log.v(mTag, "Surface " + surface + " drawing to bitmap w="
Romain Guy25eba5c2012-04-04 17:29:03 -07003022 + canvas.getWidth() + ", h=" + canvas.getHeight());
3023 //canvas.drawARGB(255, 255, 0, 0);
3024 }
3025
Romain Guy25eba5c2012-04-04 17:29:03 -07003026 // If this bitmap's format includes an alpha channel, we
3027 // need to clear it before drawing so that the child will
3028 // properly re-composite its drawing on a transparent
3029 // background. This automatically respects the clip/dirty region
3030 // or
3031 // If we are applying an offset, we need to clear the area
3032 // where the offset doesn't appear to avoid having garbage
3033 // left in the blank areas.
Alan Viveretteccb11e12014-07-08 16:04:02 -07003034 if (!canvas.isOpaque() || yoff != 0 || xoff != 0) {
Romain Guy25eba5c2012-04-04 17:29:03 -07003035 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
3036 }
3037
3038 dirty.setEmpty();
3039 mIsAnimating = false;
Dianne Hackborn4702a852012-08-17 15:18:29 -07003040 mView.mPrivateFlags |= View.PFLAG_DRAWN;
Romain Guy25eba5c2012-04-04 17:29:03 -07003041
3042 if (DEBUG_DRAW) {
3043 Context cxt = mView.getContext();
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003044 Log.i(mTag, "Drawing: package:" + cxt.getPackageName() +
Romain Guy25eba5c2012-04-04 17:29:03 -07003045 ", metrics=" + cxt.getResources().getDisplayMetrics() +
3046 ", compatibilityInfo=" + cxt.getResources().getCompatibilityInfo());
3047 }
3048 try {
Alan Viveretteccb11e12014-07-08 16:04:02 -07003049 canvas.translate(-xoff, -yoff);
Romain Guy25eba5c2012-04-04 17:29:03 -07003050 if (mTranslator != null) {
3051 mTranslator.translateCanvas(canvas);
3052 }
Dianne Hackborn908aecc2012-07-31 16:37:34 -07003053 canvas.setScreenDensity(scalingRequired ? mNoncompatDensity : 0);
Romain Guy25eba5c2012-04-04 17:29:03 -07003054 attachInfo.mSetIgnoreDirtyState = false;
3055
Romain Guy25eba5c2012-04-04 17:29:03 -07003056 mView.draw(canvas);
Alan Viverette632af842014-10-28 13:45:11 -07003057
3058 drawAccessibilityFocusedDrawableIfNeeded(canvas);
Romain Guy25eba5c2012-04-04 17:29:03 -07003059 } finally {
3060 if (!attachInfo.mSetIgnoreDirtyState) {
3061 // Only clear the flag if it was not set during the mView.draw() call
3062 attachInfo.mIgnoreDirtyState = false;
3063 }
3064 }
Romain Guy25eba5c2012-04-04 17:29:03 -07003065 } finally {
Romain Guydddcd222012-05-18 15:33:57 -07003066 try {
3067 surface.unlockCanvasAndPost(canvas);
3068 } catch (IllegalArgumentException e) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003069 Log.e(mTag, "Could not unlock surface", e);
Romain Guydddcd222012-05-18 15:33:57 -07003070 mLayoutRequested = true; // ask wm for a new surface next time.
3071 //noinspection ReturnInsideFinallyBlock
3072 return false;
3073 }
Romain Guy25eba5c2012-04-04 17:29:03 -07003074
Romain Guy25eba5c2012-04-04 17:29:03 -07003075 if (LOCAL_LOGV) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003076 Log.v(mTag, "Surface " + surface + " unlockCanvasAndPost");
Romain Guy25eba5c2012-04-04 17:29:03 -07003077 }
3078 }
3079 return true;
3080 }
3081
Alan Viverette632af842014-10-28 13:45:11 -07003082 /**
3083 * We want to draw a highlight around the current accessibility focused.
3084 * Since adding a style for all possible view is not a viable option we
3085 * have this specialized drawing method.
3086 *
3087 * Note: We are doing this here to be able to draw the highlight for
3088 * virtual views in addition to real ones.
3089 *
3090 * @param canvas The canvas on which to draw.
3091 */
3092 private void drawAccessibilityFocusedDrawableIfNeeded(Canvas canvas) {
3093 final Rect bounds = mAttachInfo.mTmpInvalRect;
3094 if (getAccessibilityFocusedRect(bounds)) {
3095 final Drawable drawable = getAccessibilityFocusedDrawable();
3096 if (drawable != null) {
3097 drawable.setBounds(bounds);
3098 drawable.draw(canvas);
3099 }
3100 } else if (mAttachInfo.mAccessibilityFocusDrawable != null) {
3101 mAttachInfo.mAccessibilityFocusDrawable.setBounds(0, 0, 0, 0);
3102 }
3103 }
3104
3105 private boolean getAccessibilityFocusedRect(Rect bounds) {
3106 final AccessibilityManager manager = AccessibilityManager.getInstance(mView.mContext);
3107 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
3108 return false;
3109 }
3110
3111 final View host = mAccessibilityFocusedHost;
3112 if (host == null || host.mAttachInfo == null) {
3113 return false;
3114 }
3115
3116 final AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
3117 if (provider == null) {
Svetoslavded133c2015-01-30 20:28:41 -08003118 host.getBoundsOnScreen(bounds, true);
Alan Viverette632af842014-10-28 13:45:11 -07003119 } else if (mAccessibilityFocusedVirtualView != null) {
3120 mAccessibilityFocusedVirtualView.getBoundsInScreen(bounds);
3121 } else {
3122 return false;
3123 }
3124
Alan Viverette2232add2015-05-26 15:24:18 -07003125 // Transform the rect into window-relative coordinates.
Alan Viverette632af842014-10-28 13:45:11 -07003126 final AttachInfo attachInfo = mAttachInfo;
Alan Viverette2232add2015-05-26 15:24:18 -07003127 bounds.offset(0, attachInfo.mViewRootImpl.mScrollY);
Alan Viverette632af842014-10-28 13:45:11 -07003128 bounds.offset(-attachInfo.mWindowLeft, -attachInfo.mWindowTop);
Doris Liu9607fbe2015-05-28 17:17:28 -07003129 if (!bounds.intersect(0, 0, attachInfo.mViewRootImpl.mWidth,
3130 attachInfo.mViewRootImpl.mHeight)) {
3131 // If no intersection, set bounds to empty.
3132 bounds.setEmpty();
3133 }
Alan Viverette632af842014-10-28 13:45:11 -07003134 return !bounds.isEmpty();
3135 }
3136
3137 private Drawable getAccessibilityFocusedDrawable() {
Chris Craikd36a81f2014-07-17 10:16:51 -07003138 // Lazily load the accessibility focus drawable.
3139 if (mAttachInfo.mAccessibilityFocusDrawable == null) {
Alan Viverettef6cf1a02014-08-11 14:13:02 -07003140 final TypedValue value = new TypedValue();
Chris Craikd36a81f2014-07-17 10:16:51 -07003141 final boolean resolved = mView.mContext.getTheme().resolveAttribute(
3142 R.attr.accessibilityFocusedDrawable, value, true);
3143 if (resolved) {
3144 mAttachInfo.mAccessibilityFocusDrawable =
Alan Viverette8eea3ea2014-02-03 18:40:20 -08003145 mView.mContext.getDrawable(value.resourceId);
Svetoslav Ganov42138042012-03-20 11:51:39 -07003146 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07003147 }
Chris Craikd36a81f2014-07-17 10:16:51 -07003148 return mAttachInfo.mAccessibilityFocusDrawable;
Svetoslav Ganov42138042012-03-20 11:51:39 -07003149 }
3150
Jorim Jaggic39c7b02016-03-24 10:47:07 -07003151 /**
3152 * Requests that the root render node is invalidated next time we perform a draw, such that
3153 * {@link WindowCallbacks#onPostDraw} gets called.
3154 */
3155 public void requestInvalidateRootRenderNode() {
3156 mInvalidateRootRequested = true;
3157 }
3158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003159 boolean scrollToRectOrFocus(Rect rectangle, boolean immediate) {
Chris Craikd36a81f2014-07-17 10:16:51 -07003160 final Rect ci = mAttachInfo.mContentInsets;
3161 final Rect vi = mAttachInfo.mVisibleInsets;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 int scrollY = 0;
3163 boolean handled = false;
Romain Guy8506ab42009-06-11 17:35:47 -07003164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003165 if (vi.left > ci.left || vi.top > ci.top
3166 || vi.right > ci.right || vi.bottom > ci.bottom) {
3167 // We'll assume that we aren't going to change the scroll
3168 // offset, since we want to avoid that unless it is actually
3169 // going to make the focus visible... otherwise we scroll
3170 // all over the place.
3171 scrollY = mScrollY;
3172 // We can be called for two different situations: during a draw,
3173 // to update the scroll position if the focus has changed (in which
3174 // case 'rectangle' is null), or in response to a
3175 // requestChildRectangleOnScreen() call (in which case 'rectangle'
3176 // is non-null and we just want to scroll to whatever that
3177 // rectangle is).
Craig Mautner26a84df2013-04-11 19:09:05 -07003178 final View focus = mView.findFocus();
Svetoslav Ganov149567f2013-01-08 15:23:34 -08003179 if (focus == null) {
Romain Guye8b16522009-07-14 13:06:42 -07003180 return false;
3181 }
Svetoslav Ganov149567f2013-01-08 15:23:34 -08003182 View lastScrolledFocus = (mLastScrolledFocus != null) ? mLastScrolledFocus.get() : null;
Craig Mautner26a84df2013-04-11 19:09:05 -07003183 if (focus != lastScrolledFocus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003184 // If the focus has changed, then ignore any requests to scroll
3185 // to a rectangle; first we want to make sure the entire focus
3186 // view is visible.
3187 rectangle = null;
3188 }
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003189 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "Eval scroll: focus=" + focus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003190 + " rectangle=" + rectangle + " ci=" + ci
3191 + " vi=" + vi);
Svetoslav Ganov149567f2013-01-08 15:23:34 -08003192 if (focus == lastScrolledFocus && !mScrollMayChange && rectangle == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003193 // Optimization: if the focus hasn't changed since last
3194 // time, and no layout has happened, then just leave things
3195 // as they are.
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003196 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "Keeping scroll y="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003197 + mScrollY + " vi=" + vi.toShortString());
Craig Mautner26a84df2013-04-11 19:09:05 -07003198 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003199 // We need to determine if the currently focused view is
3200 // within the visible part of the window and, if not, apply
3201 // a pan so it can be seen.
Svetoslav Ganov149567f2013-01-08 15:23:34 -08003202 mLastScrolledFocus = new WeakReference<View>(focus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003203 mScrollMayChange = false;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003204 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "Need to scroll?");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 // Try to find the rectangle from the focus view.
3206 if (focus.getGlobalVisibleRect(mVisRect, null)) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003207 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "Root w="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003208 + mView.getWidth() + " h=" + mView.getHeight()
3209 + " ci=" + ci.toShortString()
3210 + " vi=" + vi.toShortString());
3211 if (rectangle == null) {
3212 focus.getFocusedRect(mTempRect);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003213 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "Focus " + focus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003214 + ": focusRect=" + mTempRect.toShortString());
Dianne Hackborn1c6a8942010-03-23 16:34:20 -07003215 if (mView instanceof ViewGroup) {
3216 ((ViewGroup) mView).offsetDescendantRectToMyCoords(
3217 focus, mTempRect);
3218 }
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003219 if (DEBUG_INPUT_RESIZE) Log.v(mTag,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003220 "Focus in window: focusRect="
3221 + mTempRect.toShortString()
3222 + " visRect=" + mVisRect.toShortString());
3223 } else {
3224 mTempRect.set(rectangle);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003225 if (DEBUG_INPUT_RESIZE) Log.v(mTag,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226 "Request scroll to rect: "
3227 + mTempRect.toShortString()
3228 + " visRect=" + mVisRect.toShortString());
3229 }
3230 if (mTempRect.intersect(mVisRect)) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003231 if (DEBUG_INPUT_RESIZE) Log.v(mTag,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003232 "Focus window visible rect: "
3233 + mTempRect.toShortString());
3234 if (mTempRect.height() >
3235 (mView.getHeight()-vi.top-vi.bottom)) {
3236 // If the focus simply is not going to fit, then
3237 // best is probably just to leave things as-is.
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003238 if (DEBUG_INPUT_RESIZE) Log.v(mTag,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003239 "Too tall; leaving scrollY=" + scrollY);
Chong Zhang67254722016-06-02 12:56:54 -07003240 }
3241 // Next, check whether top or bottom is covered based on the non-scrolled
3242 // position, and calculate new scrollY (or set it to 0).
3243 // We can't keep using mScrollY here. For example mScrollY is non-zero
3244 // due to IME, then IME goes away. The current value of mScrollY leaves top
3245 // and bottom both visible, but we still need to scroll it back to 0.
3246 else if (mTempRect.top < vi.top) {
3247 scrollY = mTempRect.top - vi.top;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003248 if (DEBUG_INPUT_RESIZE) Log.v(mTag,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249 "Top covered; scrollY=" + scrollY);
Chong Zhang67254722016-06-02 12:56:54 -07003250 } else if (mTempRect.bottom > (mView.getHeight()-vi.bottom)) {
3251 scrollY = mTempRect.bottom - (mView.getHeight()-vi.bottom);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003252 if (DEBUG_INPUT_RESIZE) Log.v(mTag,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253 "Bottom covered; scrollY=" + scrollY);
Chong Zhang67254722016-06-02 12:56:54 -07003254 } else {
3255 scrollY = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003256 }
3257 handled = true;
3258 }
3259 }
3260 }
3261 }
Romain Guy8506ab42009-06-11 17:35:47 -07003262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003263 if (scrollY != mScrollY) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003264 if (DEBUG_INPUT_RESIZE) Log.v(mTag, "Pan scroll changed: old="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003265 + mScrollY + " , new=" + scrollY);
Derek Sollenberger8d948352015-07-16 09:27:59 -04003266 if (!immediate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 if (mScroller == null) {
3268 mScroller = new Scroller(mView.getContext());
3269 }
3270 mScroller.startScroll(0, mScrollY, 0, scrollY-mScrollY);
3271 } else if (mScroller != null) {
3272 mScroller.abortAnimation();
3273 }
3274 mScrollY = scrollY;
3275 }
Romain Guy8506ab42009-06-11 17:35:47 -07003276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003277 return handled;
3278 }
Romain Guy8506ab42009-06-11 17:35:47 -07003279
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07003280 /**
3281 * @hide
3282 */
3283 public View getAccessibilityFocusedHost() {
3284 return mAccessibilityFocusedHost;
3285 }
3286
3287 /**
3288 * @hide
3289 */
3290 public AccessibilityNodeInfo getAccessibilityFocusedVirtualView() {
3291 return mAccessibilityFocusedVirtualView;
3292 }
3293
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07003294 void setAccessibilityFocus(View view, AccessibilityNodeInfo node) {
Svetoslav Ganov791fd312012-05-14 15:12:30 -07003295 // If we have a virtual view with accessibility focus we need
3296 // to clear the focus and invalidate the virtual view bounds.
3297 if (mAccessibilityFocusedVirtualView != null) {
3298
3299 AccessibilityNodeInfo focusNode = mAccessibilityFocusedVirtualView;
3300 View focusHost = mAccessibilityFocusedHost;
Svetoslav Ganov791fd312012-05-14 15:12:30 -07003301
3302 // Wipe the state of the current accessibility focus since
3303 // the call into the provider to clear accessibility focus
3304 // will fire an accessibility event which will end up calling
3305 // this method and we want to have clean state when this
3306 // invocation happens.
3307 mAccessibilityFocusedHost = null;
3308 mAccessibilityFocusedVirtualView = null;
3309
Alan Viverette239a0c02013-05-07 17:17:35 -07003310 // Clear accessibility focus on the host after clearing state since
3311 // this method may be reentrant.
Phil Weavere37cfab2016-04-07 21:01:57 -07003312 focusHost.clearAccessibilityFocusNoCallbacks(
3313 AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
Alan Viverette239a0c02013-05-07 17:17:35 -07003314
Svetoslav Ganov791fd312012-05-14 15:12:30 -07003315 AccessibilityNodeProvider provider = focusHost.getAccessibilityNodeProvider();
3316 if (provider != null) {
3317 // Invalidate the area of the cleared accessibility focus.
3318 focusNode.getBoundsInParent(mTempRect);
3319 focusHost.invalidate(mTempRect);
3320 // Clear accessibility focus in the virtual node.
3321 final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
3322 focusNode.getSourceNodeId());
3323 provider.performAction(virtualNodeId,
3324 AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
3325 }
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07003326 focusNode.recycle();
Svetoslav Ganov791fd312012-05-14 15:12:30 -07003327 }
Phil Weaverda469272016-06-24 18:17:21 -07003328 if ((mAccessibilityFocusedHost != null) && (mAccessibilityFocusedHost != view)) {
Svetoslav Ganov791fd312012-05-14 15:12:30 -07003329 // Clear accessibility focus in the view.
Phil Weavere37cfab2016-04-07 21:01:57 -07003330 mAccessibilityFocusedHost.clearAccessibilityFocusNoCallbacks(
3331 AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
Svetoslav Ganov42138042012-03-20 11:51:39 -07003332 }
Svetoslav Ganov791fd312012-05-14 15:12:30 -07003333
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07003334 // Set the new focus host and node.
3335 mAccessibilityFocusedHost = view;
3336 mAccessibilityFocusedVirtualView = node;
John Reck0a973302014-07-16 13:29:45 -07003337
Stan Iliev45faba52016-06-28 13:33:15 -04003338 if (mAttachInfo.mThreadedRenderer != null) {
3339 mAttachInfo.mThreadedRenderer.invalidateRoot();
John Reck0a973302014-07-16 13:29:45 -07003340 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07003341 }
3342
Vladislav Kaznacheev3787de12016-12-21 10:36:35 -08003343 boolean hasPointerCapture() {
3344 return mPointerCapture;
3345 }
3346
3347 void requestPointerCapture(boolean enabled) {
3348 if (mPointerCapture == enabled) {
3349 return;
3350 }
3351 InputManager.getInstance().requestPointerCapture(mAttachInfo.mWindowToken, enabled);
3352 }
3353
3354 private void handlePointerCaptureChanged(boolean hasCapture) {
3355 if (mPointerCapture == hasCapture) {
3356 return;
3357 }
3358 mPointerCapture = hasCapture;
3359 if (mView != null) {
3360 mView.dispatchPointerCaptureChanged(hasCapture);
3361 }
3362 }
3363
Igor Murashkina86ab6402013-08-30 12:58:36 -07003364 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 public void requestChildFocus(View child, View focused) {
Svetoslav Ganovb36a0ac2012-02-14 17:46:47 -08003366 if (DEBUG_INPUT_RESIZE) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003367 Log.v(mTag, "Request child focus: focus now " + focused);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 }
Svetoslav Ganov149567f2013-01-08 15:23:34 -08003369 checkThread();
Svetoslav Ganovb36a0ac2012-02-14 17:46:47 -08003370 scheduleTraversals();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003371 }
3372
Igor Murashkina86ab6402013-08-30 12:58:36 -07003373 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003374 public void clearChildFocus(View child) {
Svetoslav Ganovb36a0ac2012-02-14 17:46:47 -08003375 if (DEBUG_INPUT_RESIZE) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003376 Log.v(mTag, "Clearing child focus");
Amith Yamasani73eb97f2012-02-14 15:45:15 -08003377 }
Svetoslav Ganov149567f2013-01-08 15:23:34 -08003378 checkThread();
3379 scheduleTraversals();
Svetoslav Ganovb36a0ac2012-02-14 17:46:47 -08003380 }
Amith Yamasani73eb97f2012-02-14 15:45:15 -08003381
Svetoslav Ganov42138042012-03-20 11:51:39 -07003382 @Override
3383 public ViewParent getParentForAccessibility() {
3384 return null;
3385 }
3386
Igor Murashkina86ab6402013-08-30 12:58:36 -07003387 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 public void focusableViewAvailable(View v) {
3389 checkThread();
Romain Guy1c90f032011-05-24 14:59:50 -07003390 if (mView != null) {
3391 if (!mView.hasFocus()) {
Evan Rosky37df2db2017-01-24 16:35:52 -08003392 if (sAlwaysAssignFocus) {
3393 v.requestFocus();
3394 }
Romain Guy1c90f032011-05-24 14:59:50 -07003395 } else {
3396 // the one case where will transfer focus away from the current one
3397 // is if the current view is a view group that prefers to give focus
3398 // to its children first AND the view is a descendant of it.
Svetoslav Ganov149567f2013-01-08 15:23:34 -08003399 View focused = mView.findFocus();
3400 if (focused instanceof ViewGroup) {
3401 ViewGroup group = (ViewGroup) focused;
3402 if (group.getDescendantFocusability() == ViewGroup.FOCUS_AFTER_DESCENDANTS
3403 && isViewDescendantOf(v, focused)) {
3404 v.requestFocus();
3405 }
Romain Guy1c90f032011-05-24 14:59:50 -07003406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003407 }
3408 }
3409 }
3410
Igor Murashkina86ab6402013-08-30 12:58:36 -07003411 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003412 public void recomputeViewAttributes(View child) {
3413 checkThread();
3414 if (mView == child) {
3415 mAttachInfo.mRecomputeGlobalAttributes = true;
3416 if (!mWillDrawSoon) {
3417 scheduleTraversals();
3418 }
3419 }
3420 }
3421
3422 void dispatchDetachedFromWindow() {
Romain Guy90fc03b2011-01-16 13:07:15 -08003423 if (mView != null && mView.mAttachInfo != null) {
Dianne Hackborn961cae92013-03-20 14:59:43 -07003424 mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003425 mView.dispatchDetachedFromWindow();
3426 }
3427
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003428 mAccessibilityInteractionConnectionManager.ensureNoConnection();
3429 mAccessibilityManager.removeAccessibilityStateChangeListener(
3430 mAccessibilityInteractionConnectionManager);
Chris Craikcce47eb2014-07-16 15:12:15 -07003431 mAccessibilityManager.removeHighTextContrastStateChangeListener(
3432 mHighContrastTextManager);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003433 removeSendWindowContentChangedCallback();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003434
Romain Guya998dff2012-03-23 18:58:36 -07003435 destroyHardwareRenderer();
3436
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07003437 setAccessibilityFocus(null, null);
Svetoslav Ganov791fd312012-05-14 15:12:30 -07003438
Craig Mautner8f303ad2013-06-14 11:32:22 -07003439 mView.assignParent(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 mView = null;
3441 mAttachInfo.mRootView = null;
3442
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07003443 mSurface.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003444
Jeff Browncc4f7db2011-08-30 20:34:48 -07003445 if (mInputQueueCallback != null && mInputQueue != null) {
3446 mInputQueueCallback.onInputQueueDestroyed(mInputQueue);
Michael Wrighta44dd262013-04-10 21:12:00 -07003447 mInputQueue.dispose();
Jeff Browncc4f7db2011-08-30 20:34:48 -07003448 mInputQueueCallback = null;
3449 mInputQueue = null;
Michael Wrighta44dd262013-04-10 21:12:00 -07003450 }
3451 if (mInputEventReceiver != null) {
Jeff Brown32cbc38552011-12-01 14:01:49 -08003452 mInputEventReceiver.dispose();
3453 mInputEventReceiver = null;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003455 try {
Jeff Brown98365d72012-08-19 20:30:52 -07003456 mWindowSession.remove(mWindow);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003457 } catch (RemoteException e) {
3458 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07003459
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003460 // Dispose the input channel after removing the window so the Window Manager
3461 // doesn't interpret the input channel being closed as an abnormal termination.
3462 if (mInputChannel != null) {
3463 mInputChannel.dispose();
3464 mInputChannel = null;
Jeff Brown349703e2010-06-22 01:27:15 -07003465 }
Jeff Brown96e942d2011-11-30 19:55:01 -08003466
Jeff Brownd912e1f2014-04-11 18:46:22 -07003467 mDisplayManager.unregisterDisplayListener(mDisplayListener);
3468
Jeff Brownebb2d8d2012-03-23 17:14:34 -07003469 unscheduleTraversals();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 }
Romain Guy8506ab42009-06-11 17:35:47 -07003471
Andrii Kulian44607962017-03-16 11:06:24 -07003472 /**
3473 * Notifies all callbacks that configuration and/or display has changed and updates internal
3474 * state.
3475 * @param mergedConfiguration New global and override config in {@link MergedConfiguration}
3476 * container.
3477 * @param force Flag indicating if we should force apply the config.
3478 * @param newDisplayId Id of new display if moved, {@link Display#INVALID_DISPLAY} if not
3479 * changed.
3480 */
3481 private void performConfigurationChange(MergedConfiguration mergedConfiguration, boolean force,
3482 int newDisplayId) {
3483 if (mergedConfiguration == null) {
3484 throw new IllegalArgumentException("No merged config provided.");
3485 }
Dianne Hackborn5fd21692011-06-07 14:09:47 -07003486
Andrii Kulian44607962017-03-16 11:06:24 -07003487 Configuration globalConfig = mergedConfiguration.getGlobalConfiguration();
3488 final Configuration overrideConfig = mergedConfiguration.getOverrideConfiguration();
3489 if (DEBUG_CONFIGURATION) Log.v(mTag,
3490 "Applying new config to window " + mWindowAttributes.getTitle()
3491 + ", globalConfig: " + globalConfig
3492 + ", overrideConfig: " + overrideConfig);
3493
3494 final CompatibilityInfo ci = mDisplay.getDisplayAdjustments().getCompatibilityInfo();
Craig Mautner48d0d182013-06-11 07:53:06 -07003495 if (!ci.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
Andrii Kulian44607962017-03-16 11:06:24 -07003496 globalConfig = new Configuration(globalConfig);
3497 ci.applyToConfiguration(mNoncompatDensity, globalConfig);
Dianne Hackborn5fd21692011-06-07 14:09:47 -07003498 }
3499
Dianne Hackborn694f79b2010-03-17 19:44:59 -07003500 synchronized (sConfigCallbacks) {
3501 for (int i=sConfigCallbacks.size()-1; i>=0; i--) {
Andrii Kulian44607962017-03-16 11:06:24 -07003502 sConfigCallbacks.get(i).onConfigurationChanged(globalConfig);
Dianne Hackborn694f79b2010-03-17 19:44:59 -07003503 }
3504 }
Adam Lesinski4ece3d62016-06-16 18:05:41 -07003505
Andrii Kulian44607962017-03-16 11:06:24 -07003506 mLastReportedMergedConfiguration.setConfiguration(globalConfig, overrideConfig);
3507
3508 mForceNextConfigUpdate = force;
3509 if (mActivityConfigCallback != null) {
3510 // An activity callback is set - notify it about override configuration update.
3511 // This basically initiates a round trip to ActivityThread and back, which will ensure
3512 // that corresponding activity and resources are updated before updating inner state of
3513 // ViewRootImpl. Eventually it will call #updateConfiguration().
3514 mActivityConfigCallback.onConfigurationChanged(overrideConfig, newDisplayId);
3515 } else {
3516 // There is no activity callback - update the configuration right away.
3517 updateConfiguration();
3518 }
3519 mForceNextConfigUpdate = false;
3520 }
3521
3522 /**
3523 * Update display and views if last applied merged configuration changed.
3524 */
3525 public void updateConfiguration() {
3526 if (mView == null) {
3527 return;
3528 }
3529
3530 // At this point the resources have been updated to
3531 // have the most recent config, whatever that is. Use
3532 // the one in them which may be newer.
3533 final Resources localResources = mView.getResources();
3534 final Configuration config = localResources.getConfiguration();
3535 if (mForceNextConfigUpdate || mLastConfigurationFromResources.diff(config) != 0) {
3536 // Update the display with new DisplayAdjustments.
3537 mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(
3538 mDisplay.getDisplayId(), localResources);
3539
3540 final int lastLayoutDirection = mLastConfigurationFromResources.getLayoutDirection();
3541 final int currentLayoutDirection = config.getLayoutDirection();
3542 mLastConfigurationFromResources.setTo(config);
3543 if (lastLayoutDirection != currentLayoutDirection
3544 && mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
3545 mView.setLayoutDirection(currentLayoutDirection);
Dianne Hackborn694f79b2010-03-17 19:44:59 -07003546 }
Andrii Kulian44607962017-03-16 11:06:24 -07003547 mView.dispatchConfigurationChanged(config);
Dianne Hackborn694f79b2010-03-17 19:44:59 -07003548 }
3549 }
John Reck05e85842014-04-23 14:48:28 -07003550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 /**
3552 * Return true if child is an ancestor of parent, (or equal to the parent).
3553 */
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07003554 public static boolean isViewDescendantOf(View child, View parent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003555 if (child == parent) {
3556 return true;
3557 }
3558
3559 final ViewParent theParent = child.getParent();
3560 return (theParent instanceof ViewGroup) && isViewDescendantOf((View) theParent, parent);
3561 }
3562
Yohei Yukawad2e56472015-07-28 17:00:33 -07003563 private static void forceLayout(View view) {
3564 view.forceLayout();
3565 if (view instanceof ViewGroup) {
3566 ViewGroup group = (ViewGroup) view;
3567 final int count = group.getChildCount();
3568 for (int i = 0; i < count; i++) {
3569 forceLayout(group.getChildAt(i));
3570 }
3571 }
3572 }
3573
Jeff Browna175a5b2012-02-15 19:18:31 -08003574 private final static int MSG_INVALIDATE = 1;
3575 private final static int MSG_INVALIDATE_RECT = 2;
3576 private final static int MSG_DIE = 3;
3577 private final static int MSG_RESIZED = 4;
3578 private final static int MSG_RESIZED_REPORT = 5;
3579 private final static int MSG_WINDOW_FOCUS_CHANGED = 6;
keunyoung30f420f2013-08-02 14:23:10 -07003580 private final static int MSG_DISPATCH_INPUT_EVENT = 7;
Jeff Browna175a5b2012-02-15 19:18:31 -08003581 private final static int MSG_DISPATCH_APP_VISIBILITY = 8;
3582 private final static int MSG_DISPATCH_GET_NEW_SURFACE = 9;
Jeff Browna175a5b2012-02-15 19:18:31 -08003583 private final static int MSG_DISPATCH_KEY_FROM_IME = 11;
Jeff Browna175a5b2012-02-15 19:18:31 -08003584 private final static int MSG_CHECK_FOCUS = 13;
3585 private final static int MSG_CLOSE_SYSTEM_DIALOGS = 14;
3586 private final static int MSG_DISPATCH_DRAG_EVENT = 15;
3587 private final static int MSG_DISPATCH_DRAG_LOCATION_EVENT = 16;
3588 private final static int MSG_DISPATCH_SYSTEM_UI_VISIBILITY = 17;
3589 private final static int MSG_UPDATE_CONFIGURATION = 18;
Svetoslav Ganov42138042012-03-20 11:51:39 -07003590 private final static int MSG_PROCESS_INPUT_EVENTS = 19;
Romain Guyfbb93fa2012-12-03 18:50:35 -08003591 private final static int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 21;
Jorim Jaggi827e0fa2015-05-07 11:41:41 -07003592 private final static int MSG_INVALIDATE_WORLD = 22;
3593 private final static int MSG_WINDOW_MOVED = 23;
3594 private final static int MSG_SYNTHESIZE_INPUT_EVENT = 24;
3595 private final static int MSG_DISPATCH_WINDOW_SHOWN = 25;
Clara Bayarri75e09792015-07-29 16:20:40 +01003596 private final static int MSG_REQUEST_KEYBOARD_SHORTCUTS = 26;
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08003597 private final static int MSG_UPDATE_POINTER_ICON = 27;
Vladislav Kaznacheev3787de12016-12-21 10:36:35 -08003598 private final static int MSG_POINTER_CAPTURE_CHANGED = 28;
Robert Carr8508bb22017-03-27 15:46:27 -07003599 private final static int MSG_DRAW_FINISHED = 29;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003600
Jeff Browna175a5b2012-02-15 19:18:31 -08003601 final class ViewRootHandler extends Handler {
3602 @Override
3603 public String getMessageName(Message message) {
3604 switch (message.what) {
3605 case MSG_INVALIDATE:
3606 return "MSG_INVALIDATE";
3607 case MSG_INVALIDATE_RECT:
3608 return "MSG_INVALIDATE_RECT";
3609 case MSG_DIE:
3610 return "MSG_DIE";
3611 case MSG_RESIZED:
3612 return "MSG_RESIZED";
3613 case MSG_RESIZED_REPORT:
3614 return "MSG_RESIZED_REPORT";
3615 case MSG_WINDOW_FOCUS_CHANGED:
3616 return "MSG_WINDOW_FOCUS_CHANGED";
keunyoung30f420f2013-08-02 14:23:10 -07003617 case MSG_DISPATCH_INPUT_EVENT:
3618 return "MSG_DISPATCH_INPUT_EVENT";
Jeff Browna175a5b2012-02-15 19:18:31 -08003619 case MSG_DISPATCH_APP_VISIBILITY:
3620 return "MSG_DISPATCH_APP_VISIBILITY";
3621 case MSG_DISPATCH_GET_NEW_SURFACE:
3622 return "MSG_DISPATCH_GET_NEW_SURFACE";
Jeff Browna175a5b2012-02-15 19:18:31 -08003623 case MSG_DISPATCH_KEY_FROM_IME:
3624 return "MSG_DISPATCH_KEY_FROM_IME";
Jeff Browna175a5b2012-02-15 19:18:31 -08003625 case MSG_CHECK_FOCUS:
3626 return "MSG_CHECK_FOCUS";
3627 case MSG_CLOSE_SYSTEM_DIALOGS:
3628 return "MSG_CLOSE_SYSTEM_DIALOGS";
3629 case MSG_DISPATCH_DRAG_EVENT:
3630 return "MSG_DISPATCH_DRAG_EVENT";
3631 case MSG_DISPATCH_DRAG_LOCATION_EVENT:
3632 return "MSG_DISPATCH_DRAG_LOCATION_EVENT";
3633 case MSG_DISPATCH_SYSTEM_UI_VISIBILITY:
3634 return "MSG_DISPATCH_SYSTEM_UI_VISIBILITY";
3635 case MSG_UPDATE_CONFIGURATION:
3636 return "MSG_UPDATE_CONFIGURATION";
Jeff Browna175a5b2012-02-15 19:18:31 -08003637 case MSG_PROCESS_INPUT_EVENTS:
3638 return "MSG_PROCESS_INPUT_EVENTS";
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07003639 case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST:
3640 return "MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST";
Craig Mautner5702d4d2012-06-30 14:10:16 -07003641 case MSG_WINDOW_MOVED:
3642 return "MSG_WINDOW_MOVED";
Michael Wright899d7052014-04-23 17:23:39 -07003643 case MSG_SYNTHESIZE_INPUT_EVENT:
3644 return "MSG_SYNTHESIZE_INPUT_EVENT";
Craig Mautner9c795042014-10-28 19:59:59 -07003645 case MSG_DISPATCH_WINDOW_SHOWN:
3646 return "MSG_DISPATCH_WINDOW_SHOWN";
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08003647 case MSG_UPDATE_POINTER_ICON:
3648 return "MSG_UPDATE_POINTER_ICON";
Vladislav Kaznacheev3787de12016-12-21 10:36:35 -08003649 case MSG_POINTER_CAPTURE_CHANGED:
3650 return "MSG_POINTER_CAPTURE_CHANGED";
Robert Carr8508bb22017-03-27 15:46:27 -07003651 case MSG_DRAW_FINISHED:
3652 return "MSG_DRAW_FINISHED";
Jeff Browna175a5b2012-02-15 19:18:31 -08003653 }
3654 return super.getMessageName(message);
Romain Guyf9284692011-07-13 18:46:21 -07003655 }
Romain Guyf9284692011-07-13 18:46:21 -07003656
Jeff Browna175a5b2012-02-15 19:18:31 -08003657 @Override
Michael Wright53b854a2016-04-12 19:22:41 -04003658 public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
3659 if (msg.what == MSG_REQUEST_KEYBOARD_SHORTCUTS && msg.obj == null) {
3660 // Debugging for b/27963013
3661 throw new NullPointerException(
3662 "Attempted to call MSG_REQUEST_KEYBOARD_SHORTCUTS with null receiver:");
3663 }
3664 return super.sendMessageAtTime(msg, uptimeMillis);
3665 }
3666
3667 @Override
Jeff Browna175a5b2012-02-15 19:18:31 -08003668 public void handleMessage(Message msg) {
3669 switch (msg.what) {
3670 case MSG_INVALIDATE:
3671 ((View) msg.obj).invalidate();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 break;
Jeff Browna175a5b2012-02-15 19:18:31 -08003673 case MSG_INVALIDATE_RECT:
3674 final View.AttachInfo.InvalidateInfo info = (View.AttachInfo.InvalidateInfo) msg.obj;
3675 info.target.invalidate(info.left, info.top, info.right, info.bottom);
Svetoslav Ganovabae2a12012-11-27 16:59:37 -08003676 info.recycle();
Jeff Browna175a5b2012-02-15 19:18:31 -08003677 break;
Jeff Browna175a5b2012-02-15 19:18:31 -08003678 case MSG_PROCESS_INPUT_EVENTS:
3679 mProcessInputEventsScheduled = false;
3680 doProcessInputEvents();
3681 break;
3682 case MSG_DISPATCH_APP_VISIBILITY:
3683 handleAppVisibility(msg.arg1 != 0);
3684 break;
3685 case MSG_DISPATCH_GET_NEW_SURFACE:
3686 handleGetNewSurface();
3687 break;
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003688 case MSG_RESIZED: {
3689 // Recycled in the fall through...
3690 SomeArgs args = (SomeArgs) msg.obj;
Romain Guydfab3632012-10-03 14:53:25 -07003691 if (mWinFrame.equals(args.arg1)
Dianne Hackbornc4aad012013-02-22 15:05:25 -08003692 && mPendingOverscanInsets.equals(args.arg5)
Romain Guydfab3632012-10-03 14:53:25 -07003693 && mPendingContentInsets.equals(args.arg2)
Adrian Roosfa104232014-06-20 16:10:14 -07003694 && mPendingStableInsets.equals(args.arg6)
Romain Guydfab3632012-10-03 14:53:25 -07003695 && mPendingVisibleInsets.equals(args.arg3)
Filip Gruszczynski2217f612015-05-26 11:32:08 -07003696 && mPendingOutsets.equals(args.arg7)
Jorim Jaggi0fe356e2016-01-05 14:43:25 +01003697 && mPendingBackDropFrame.equals(args.arg8)
Jorim Jaggia4a58ef2016-01-27 02:10:08 -08003698 && args.arg4 == null
Andrii Kulianb047b8b2017-02-08 18:38:26 -08003699 && args.argi1 == 0
3700 && mDisplay.getDisplayId() == args.argi3) {
Jeff Browna175a5b2012-02-15 19:18:31 -08003701 break;
Romain Guycdb86672010-03-18 18:54:50 -07003702 }
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003703 } // fall through...
Jeff Browna175a5b2012-02-15 19:18:31 -08003704 case MSG_RESIZED_REPORT:
3705 if (mAdded) {
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003706 SomeArgs args = (SomeArgs) msg.obj;
3707
Andrii Kulian44607962017-03-16 11:06:24 -07003708 final int displayId = args.argi3;
3709 final boolean displayChanged = mDisplay.getDisplayId() != displayId;
3710 if (displayChanged) {
3711 onMovedToDisplay(displayId);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08003712 }
3713
Andrii Kulian44607962017-03-16 11:06:24 -07003714 final MergedConfiguration mergedConfiguration = (MergedConfiguration) args.arg4;
3715 if (mergedConfiguration != null) {
3716 performConfigurationChange(mergedConfiguration, false /* force */,
3717 displayChanged ? displayId : INVALID_DISPLAY /* same display */);
Jeff Browna175a5b2012-02-15 19:18:31 -08003718 }
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003719
Jorim Jaggi26952d72016-04-01 17:43:14 -07003720 final boolean framesChanged = !mWinFrame.equals(args.arg1)
3721 || !mPendingOverscanInsets.equals(args.arg5)
3722 || !mPendingContentInsets.equals(args.arg2)
3723 || !mPendingStableInsets.equals(args.arg6)
3724 || !mPendingVisibleInsets.equals(args.arg3)
3725 || !mPendingOutsets.equals(args.arg7);
3726
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003727 mWinFrame.set((Rect) args.arg1);
Dianne Hackbornc4aad012013-02-22 15:05:25 -08003728 mPendingOverscanInsets.set((Rect) args.arg5);
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003729 mPendingContentInsets.set((Rect) args.arg2);
Adrian Roosfa104232014-06-20 16:10:14 -07003730 mPendingStableInsets.set((Rect) args.arg6);
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003731 mPendingVisibleInsets.set((Rect) args.arg3);
Filip Gruszczynski2217f612015-05-26 11:32:08 -07003732 mPendingOutsets.set((Rect) args.arg7);
Jorim Jaggia7262a82015-11-03 15:15:40 +01003733 mPendingBackDropFrame.set((Rect) args.arg8);
Jorim Jaggia4a58ef2016-01-27 02:10:08 -08003734 mForceNextWindowRelayout = args.argi1 != 0;
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -08003735 mPendingAlwaysConsumeNavBar = args.argi2 != 0;
Svetoslav Ganov758143e2012-08-06 16:40:27 -07003736
3737 args.recycle();
3738
Jeff Browna175a5b2012-02-15 19:18:31 -08003739 if (msg.what == MSG_RESIZED_REPORT) {
3740 mReportNextDraw = true;
3741 }
Romain Guy59a12ca2011-06-09 17:48:21 -07003742
Jorim Jaggi26952d72016-04-01 17:43:14 -07003743 if (mView != null && framesChanged) {
Yohei Yukawad2e56472015-07-28 17:00:33 -07003744 forceLayout(mView);
3745 }
3746
Jeff Browna175a5b2012-02-15 19:18:31 -08003747 requestLayout();
3748 }
3749 break;
Craig Mautner5702d4d2012-06-30 14:10:16 -07003750 case MSG_WINDOW_MOVED:
3751 if (mAdded) {
3752 final int w = mWinFrame.width();
3753 final int h = mWinFrame.height();
3754 final int l = msg.arg1;
3755 final int t = msg.arg2;
3756 mWinFrame.left = l;
3757 mWinFrame.right = l + w;
3758 mWinFrame.top = t;
3759 mWinFrame.bottom = t + h;
3760
Jorim Jaggia7262a82015-11-03 15:15:40 +01003761 mPendingBackDropFrame.set(mWinFrame);
Winson Chungc7c4dbb2016-10-28 14:33:32 -07003762 maybeHandleWindowMove(mWinFrame);
Craig Mautner5702d4d2012-06-30 14:10:16 -07003763 }
3764 break;
Jeff Browna175a5b2012-02-15 19:18:31 -08003765 case MSG_WINDOW_FOCUS_CHANGED: {
3766 if (mAdded) {
3767 boolean hasWindowFocus = msg.arg1 != 0;
3768 mAttachInfo.mHasWindowFocus = hasWindowFocus;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003769
Jeff Browna175a5b2012-02-15 19:18:31 -08003770 profileRendering(hasWindowFocus);
3771
3772 if (hasWindowFocus) {
3773 boolean inTouchMode = msg.arg2 != 0;
3774 ensureTouchModeLocally(inTouchMode);
3775
Stan Iliev45faba52016-06-28 13:33:15 -04003776 if (mAttachInfo.mThreadedRenderer != null && mSurface.isValid()){
Jeff Browna175a5b2012-02-15 19:18:31 -08003777 mFullRedrawNeeded = true;
Dianne Hackborn64825172011-03-02 21:32:58 -08003778 try {
Alan Viveretteccb11e12014-07-08 16:04:02 -07003779 final WindowManager.LayoutParams lp = mWindowAttributes;
Alan Viverette49a22e82014-07-12 20:01:27 -07003780 final Rect surfaceInsets = lp != null ? lp.surfaceInsets : null;
Stan Iliev45faba52016-06-28 13:33:15 -04003781 mAttachInfo.mThreadedRenderer.initializeIfNeeded(
Alan Viverette50210d92015-05-14 18:05:36 -07003782 mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets);
Igor Murashkina86ab6402013-08-30 12:58:36 -07003783 } catch (OutOfResourcesException e) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003784 Log.e(mTag, "OutOfResourcesException locking surface", e);
Jeff Browna175a5b2012-02-15 19:18:31 -08003785 try {
Jeff Brown98365d72012-08-19 20:30:52 -07003786 if (!mWindowSession.outOfMemory(mWindow)) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003787 Slog.w(mTag, "No processes killed for memory; killing self");
Jeff Browna175a5b2012-02-15 19:18:31 -08003788 Process.killProcess(Process.myPid());
3789 }
3790 } catch (RemoteException ex) {
Dianne Hackborn64825172011-03-02 21:32:58 -08003791 }
Jeff Browna175a5b2012-02-15 19:18:31 -08003792 // Retry in a bit.
3793 sendMessageDelayed(obtainMessage(msg.what, msg.arg1, msg.arg2), 500);
3794 return;
Dianne Hackborn64825172011-03-02 21:32:58 -08003795 }
Dianne Hackborn64825172011-03-02 21:32:58 -08003796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003797 }
Romain Guy8506ab42009-06-11 17:35:47 -07003798
Jeff Browna175a5b2012-02-15 19:18:31 -08003799 mLastWasImTarget = WindowManager.LayoutParams
3800 .mayUseInputMethod(mWindowAttributes.flags);
Romain Guy8506ab42009-06-11 17:35:47 -07003801
Jeff Browna175a5b2012-02-15 19:18:31 -08003802 InputMethodManager imm = InputMethodManager.peekInstance();
Yohei Yukawa5f059652015-05-14 22:16:41 -07003803 if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) {
3804 imm.onPreWindowFocus(mView, hasWindowFocus);
3805 }
Jeff Browna175a5b2012-02-15 19:18:31 -08003806 if (mView != null) {
Jeff Browna175a5b2012-02-15 19:18:31 -08003807 mAttachInfo.mKeyDispatchState.reset();
3808 mView.dispatchWindowFocusChanged(hasWindowFocus);
Dianne Hackborn961cae92013-03-20 14:59:43 -07003809 mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus);
Vladislav Kaznacheevf847ee32016-11-21 14:11:00 -08003810
3811 if (mAttachInfo.mTooltipHost != null) {
3812 mAttachInfo.mTooltipHost.hideTooltip();
3813 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 }
svetoslavganov75986cf2009-05-14 22:28:01 -07003815
Jeff Browna175a5b2012-02-15 19:18:31 -08003816 // Note: must be done after the focus change callbacks,
3817 // so all of the view state is set up correctly.
3818 if (hasWindowFocus) {
keunyoung30f420f2013-08-02 14:23:10 -07003819 if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) {
Yohei Yukawa5f059652015-05-14 22:16:41 -07003820 imm.onPostWindowFocus(mView, mView.findFocus(),
Jeff Browna175a5b2012-02-15 19:18:31 -08003821 mWindowAttributes.softInputMode,
3822 !mHasHadWindowFocus, mWindowAttributes.flags);
3823 }
3824 // Clear the forward bit. We can just do this directly, since
3825 // the window manager doesn't care about it.
3826 mWindowAttributes.softInputMode &=
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003827 ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
Jeff Browna175a5b2012-02-15 19:18:31 -08003828 ((WindowManager.LayoutParams)mView.getLayoutParams())
3829 .softInputMode &=
3830 ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
3831 mHasHadWindowFocus = true;
Vladislav Kaznacheev3787de12016-12-21 10:36:35 -08003832 } else {
3833 if (mPointerCapture) {
3834 handlePointerCaptureChanged(false);
3835 }
Jeff Browna175a5b2012-02-15 19:18:31 -08003836 }
svetoslavganov75986cf2009-05-14 22:28:01 -07003837 }
Jeff Browna175a5b2012-02-15 19:18:31 -08003838 } break;
3839 case MSG_DIE:
3840 doDie();
3841 break;
keunyoung30f420f2013-08-02 14:23:10 -07003842 case MSG_DISPATCH_INPUT_EVENT: {
Jae Seo6a6059a2014-04-17 21:35:29 -07003843 SomeArgs args = (SomeArgs)msg.obj;
3844 InputEvent event = (InputEvent)args.arg1;
3845 InputEventReceiver receiver = (InputEventReceiver)args.arg2;
3846 enqueueInputEvent(event, receiver, 0, true);
3847 args.recycle();
Jeff Browna175a5b2012-02-15 19:18:31 -08003848 } break;
Michael Wright899d7052014-04-23 17:23:39 -07003849 case MSG_SYNTHESIZE_INPUT_EVENT: {
3850 InputEvent event = (InputEvent)msg.obj;
3851 enqueueInputEvent(event, null, QueuedInputEvent.FLAG_UNHANDLED, true);
3852 } break;
Jeff Browna175a5b2012-02-15 19:18:31 -08003853 case MSG_DISPATCH_KEY_FROM_IME: {
3854 if (LOCAL_LOGV) Log.v(
3855 TAG, "Dispatching key "
3856 + msg.obj + " from IME to " + mView);
3857 KeyEvent event = (KeyEvent)msg.obj;
3858 if ((event.getFlags()&KeyEvent.FLAG_FROM_SYSTEM) != 0) {
3859 // The IME is trying to say this event is from the
3860 // system! Bad bad bad!
3861 //noinspection UnusedAssignment
Michael Wright899d7052014-04-23 17:23:39 -07003862 event = KeyEvent.changeFlags(event, event.getFlags() &
3863 ~KeyEvent.FLAG_FROM_SYSTEM);
Jeff Browna175a5b2012-02-15 19:18:31 -08003864 }
3865 enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true);
3866 } break;
Jeff Browna175a5b2012-02-15 19:18:31 -08003867 case MSG_CHECK_FOCUS: {
3868 InputMethodManager imm = InputMethodManager.peekInstance();
3869 if (imm != null) {
3870 imm.checkFocus();
3871 }
3872 } break;
3873 case MSG_CLOSE_SYSTEM_DIALOGS: {
3874 if (mView != null) {
3875 mView.onCloseSystemDialogs((String)msg.obj);
3876 }
3877 } break;
3878 case MSG_DISPATCH_DRAG_EVENT:
3879 case MSG_DISPATCH_DRAG_LOCATION_EVENT: {
3880 DragEvent event = (DragEvent)msg.obj;
3881 event.mLocalState = mLocalDragState; // only present when this app called startDrag()
3882 handleDragEvent(event);
3883 } break;
3884 case MSG_DISPATCH_SYSTEM_UI_VISIBILITY: {
Romain Guyfbb93fa2012-12-03 18:50:35 -08003885 handleDispatchSystemUiVisibilityChanged((SystemUiVisibilityInfo) msg.obj);
Jeff Browna175a5b2012-02-15 19:18:31 -08003886 } break;
3887 case MSG_UPDATE_CONFIGURATION: {
Andrii Kulian44607962017-03-16 11:06:24 -07003888 Configuration config = (Configuration) msg.obj;
3889 if (config.isOtherSeqNewer(
3890 mLastReportedMergedConfiguration.getMergedConfiguration())) {
3891 // If we already have a newer merged config applied - use its global part.
3892 config = mLastReportedMergedConfiguration.getGlobalConfiguration();
Jeff Browna175a5b2012-02-15 19:18:31 -08003893 }
Andrii Kulian44607962017-03-16 11:06:24 -07003894
3895 // Use the newer global config and last reported override config.
3896 mPendingMergedConfiguration.setConfiguration(config,
3897 mLastReportedMergedConfiguration.getOverrideConfiguration());
3898
3899 performConfigurationChange(mPendingMergedConfiguration, false /* force */,
3900 INVALID_DISPLAY /* same display */);
Jeff Browna175a5b2012-02-15 19:18:31 -08003901 } break;
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07003902 case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST: {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07003903 setAccessibilityFocus(null, null);
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07003904 } break;
Dianne Hackborna53de062012-05-08 18:53:51 -07003905 case MSG_INVALIDATE_WORLD: {
Romain Guyf84208f2012-09-13 22:50:18 -07003906 if (mView != null) {
3907 invalidateWorld(mView);
3908 }
Dianne Hackborna53de062012-05-08 18:53:51 -07003909 } break;
Craig Mautner9c795042014-10-28 19:59:59 -07003910 case MSG_DISPATCH_WINDOW_SHOWN: {
3911 handleDispatchWindowShown();
Clara Bayarri75e09792015-07-29 16:20:40 +01003912 } break;
3913 case MSG_REQUEST_KEYBOARD_SHORTCUTS: {
Clara Bayarrifcd7e802016-03-10 12:58:18 +00003914 final IResultReceiver receiver = (IResultReceiver) msg.obj;
3915 final int deviceId = msg.arg1;
3916 handleRequestKeyboardShortcuts(receiver, deviceId);
Clara Bayarri75e09792015-07-29 16:20:40 +01003917 } break;
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08003918 case MSG_UPDATE_POINTER_ICON: {
3919 MotionEvent event = (MotionEvent) msg.obj;
3920 resetPointerIcon(event);
3921 } break;
Vladislav Kaznacheev3787de12016-12-21 10:36:35 -08003922 case MSG_POINTER_CAPTURE_CHANGED: {
3923 final boolean hasCapture = msg.arg1 != 0;
3924 handlePointerCaptureChanged(hasCapture);
3925 } break;
Robert Carr8508bb22017-03-27 15:46:27 -07003926 case MSG_DRAW_FINISHED: {
3927 pendingDrawFinished();
3928 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003929 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003930 }
3931 }
Romain Guy51e4d4d2012-03-15 18:30:47 -07003932
Jeff Browna175a5b2012-02-15 19:18:31 -08003933 final ViewRootHandler mHandler = new ViewRootHandler();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003935 /**
3936 * Something in the current window tells us we need to change the touch mode. For
3937 * example, we are not in touch mode, and the user touches the screen.
3938 *
3939 * If the touch mode has changed, tell the window manager, and handle it locally.
3940 *
3941 * @param inTouchMode Whether we want to be in touch mode.
3942 * @return True if the touch mode changed and focus changed was changed as a result
3943 */
3944 boolean ensureTouchMode(boolean inTouchMode) {
3945 if (DBG) Log.d("touchmode", "ensureTouchMode(" + inTouchMode + "), current "
3946 + "touch mode is " + mAttachInfo.mInTouchMode);
3947 if (mAttachInfo.mInTouchMode == inTouchMode) return false;
3948
3949 // tell the window manager
3950 try {
Matt Wud6bc96d2016-01-14 12:59:24 -08003951 mWindowSession.setInTouchMode(inTouchMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003952 } catch (RemoteException e) {
3953 throw new RuntimeException(e);
3954 }
3955
3956 // handle the change
Romain Guy2d4cff62010-04-09 15:39:00 -07003957 return ensureTouchModeLocally(inTouchMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003958 }
3959
3960 /**
3961 * Ensure that the touch mode for this window is set, and if it is changing,
3962 * take the appropriate action.
3963 * @param inTouchMode Whether we want to be in touch mode.
3964 * @return True if the touch mode changed and focus changed was changed as a result
3965 */
Romain Guy2d4cff62010-04-09 15:39:00 -07003966 private boolean ensureTouchModeLocally(boolean inTouchMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003967 if (DBG) Log.d("touchmode", "ensureTouchModeLocally(" + inTouchMode + "), current "
3968 + "touch mode is " + mAttachInfo.mInTouchMode);
3969
3970 if (mAttachInfo.mInTouchMode == inTouchMode) return false;
3971
3972 mAttachInfo.mInTouchMode = inTouchMode;
3973 mAttachInfo.mTreeObserver.dispatchOnTouchModeChanged(inTouchMode);
3974
Romain Guy2d4cff62010-04-09 15:39:00 -07003975 return (inTouchMode) ? enterTouchMode() : leaveTouchMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003976 }
3977
3978 private boolean enterTouchMode() {
Alan Viveretteed7821a2013-07-24 15:49:23 -07003979 if (mView != null && mView.hasFocus()) {
3980 // note: not relying on mFocusedView here because this could
3981 // be when the window is first being added, and mFocused isn't
3982 // set yet.
3983 final View focused = mView.findFocus();
3984 if (focused != null && !focused.isFocusableInTouchMode()) {
3985 final ViewGroup ancestorToTakeFocus = findAncestorToTakeFocusInTouchMode(focused);
3986 if (ancestorToTakeFocus != null) {
3987 // there is an ancestor that wants focus after its
3988 // descendants that is focusable in touch mode.. give it
3989 // focus
3990 return ancestorToTakeFocus.requestFocus();
3991 } else {
Alan Viverette973f3b42013-08-13 16:57:28 -07003992 // There's nothing to focus. Clear and propagate through the
3993 // hierarchy, but don't attempt to place new focus.
Alan Viverette223622a2013-12-17 13:29:02 -08003994 focused.clearFocusInternal(null, true, false);
Alan Viveretteed7821a2013-07-24 15:49:23 -07003995 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003996 }
3997 }
3998 }
3999 return false;
4000 }
4001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004002 /**
4003 * Find an ancestor of focused that wants focus after its descendants and is
4004 * focusable in touch mode.
4005 * @param focused The currently focused view.
4006 * @return An appropriate view, or null if no such view exists.
4007 */
Romain Guya998dff2012-03-23 18:58:36 -07004008 private static ViewGroup findAncestorToTakeFocusInTouchMode(View focused) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004009 ViewParent parent = focused.getParent();
4010 while (parent instanceof ViewGroup) {
4011 final ViewGroup vgParent = (ViewGroup) parent;
4012 if (vgParent.getDescendantFocusability() == ViewGroup.FOCUS_AFTER_DESCENDANTS
4013 && vgParent.isFocusableInTouchMode()) {
4014 return vgParent;
4015 }
4016 if (vgParent.isRootNamespace()) {
4017 return null;
4018 } else {
4019 parent = vgParent.getParent();
4020 }
4021 }
4022 return null;
4023 }
4024
4025 private boolean leaveTouchMode() {
4026 if (mView != null) {
4027 if (mView.hasFocus()) {
Svetoslav Ganov149567f2013-01-08 15:23:34 -08004028 View focusedView = mView.findFocus();
4029 if (!(focusedView instanceof ViewGroup)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004030 // some view has focus, let it keep it
Svetoslav Ganovcf8a3b82012-04-30 16:49:59 -07004031 return false;
Svetoslav Ganov149567f2013-01-08 15:23:34 -08004032 } else if (((ViewGroup) focusedView).getDescendantFocusability() !=
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004033 ViewGroup.FOCUS_AFTER_DESCENDANTS) {
4034 // some view group has focus, and doesn't prefer its children
4035 // over itself for focus, so let them keep it.
Svetoslav Ganovcf8a3b82012-04-30 16:49:59 -07004036 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004037 }
4038 }
Svetoslav Ganovcf8a3b82012-04-30 16:49:59 -07004039
4040 // find the best view to give focus to in this brave new non-touch-mode
4041 // world
4042 final View focused = focusSearch(null, View.FOCUS_DOWN);
4043 if (focused != null) {
4044 return focused.requestFocus(View.FOCUS_DOWN);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004045 }
4046 }
4047 return false;
4048 }
4049
Jeff Brownf9e989d2013-04-04 23:04:03 -07004050 /**
4051 * Base class for implementing a stage in the chain of responsibility
4052 * for processing input events.
4053 * <p>
4054 * Events are delivered to the stage by the {@link #deliver} method. The stage
4055 * then has the choice of finishing the event or forwarding it to the next stage.
4056 * </p>
4057 */
4058 abstract class InputStage {
4059 private final InputStage mNext;
4060
4061 protected static final int FORWARD = 0;
4062 protected static final int FINISH_HANDLED = 1;
4063 protected static final int FINISH_NOT_HANDLED = 2;
4064
4065 /**
4066 * Creates an input stage.
4067 * @param next The next stage to which events should be forwarded.
4068 */
4069 public InputStage(InputStage next) {
4070 mNext = next;
4071 }
4072
4073 /**
4074 * Delivers an event to be processed.
4075 */
4076 public final void deliver(QueuedInputEvent q) {
4077 if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
4078 forward(q);
Michael Wright17d28ca2013-10-31 17:47:45 -07004079 } else if (shouldDropInputEvent(q)) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004080 finish(q, false);
4081 } else {
4082 apply(q, onProcess(q));
4083 }
4084 }
4085
4086 /**
4087 * Marks the the input event as finished then forwards it to the next stage.
4088 */
4089 protected void finish(QueuedInputEvent q, boolean handled) {
4090 q.mFlags |= QueuedInputEvent.FLAG_FINISHED;
4091 if (handled) {
4092 q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;
4093 }
4094 forward(q);
4095 }
4096
4097 /**
4098 * Forwards the event to the next stage.
4099 */
4100 protected void forward(QueuedInputEvent q) {
4101 onDeliverToNext(q);
4102 }
4103
4104 /**
4105 * Applies a result code from {@link #onProcess} to the specified event.
4106 */
4107 protected void apply(QueuedInputEvent q, int result) {
4108 if (result == FORWARD) {
4109 forward(q);
4110 } else if (result == FINISH_HANDLED) {
4111 finish(q, true);
4112 } else if (result == FINISH_NOT_HANDLED) {
4113 finish(q, false);
4114 } else {
4115 throw new IllegalArgumentException("Invalid result: " + result);
4116 }
4117 }
4118
4119 /**
4120 * Called when an event is ready to be processed.
4121 * @return A result code indicating how the event was handled.
4122 */
4123 protected int onProcess(QueuedInputEvent q) {
4124 return FORWARD;
4125 }
4126
4127 /**
4128 * Called when an event is being delivered to the next stage.
4129 */
4130 protected void onDeliverToNext(QueuedInputEvent q) {
Michael Wright06a79252014-05-05 17:45:29 -07004131 if (DEBUG_INPUT_STAGES) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004132 Log.v(mTag, "Done with " + getClass().getSimpleName() + ". " + q);
Michael Wright06a79252014-05-05 17:45:29 -07004133 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004134 if (mNext != null) {
4135 mNext.deliver(q);
4136 } else {
4137 finishInputEvent(q);
4138 }
4139 }
Jeff Brown5182c782013-10-15 20:31:52 -07004140
Michael Wright17d28ca2013-10-31 17:47:45 -07004141 protected boolean shouldDropInputEvent(QueuedInputEvent q) {
4142 if (mView == null || !mAdded) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004143 Slog.w(mTag, "Dropping event due to root view being removed: " + q.mEvent);
Michael Wright17d28ca2013-10-31 17:47:45 -07004144 return true;
George Mount41725de2015-04-09 08:23:05 -07004145 } else if ((!mAttachInfo.mHasWindowFocus
4146 && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) || mStopped
Joe LaPenna90776de2016-01-22 07:11:49 -08004147 || (mIsAmbientMode && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_BUTTON))
4148 || (mPausedForTransition && !isBack(q.mEvent))) {
Wale Ogunwalec3672cd2014-11-05 15:17:35 -08004149 // This is a focus event and the window doesn't currently have input focus or
4150 // has stopped. This could be an event that came back from the previous stage
4151 // but the window has lost focus or stopped in the meantime.
4152 if (isTerminalInputEvent(q.mEvent)) {
4153 // Don't drop terminal input events, however mark them as canceled.
4154 q.mEvent.cancel();
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004155 Slog.w(mTag, "Cancelling event due to no window focus: " + q.mEvent);
Wale Ogunwalec3672cd2014-11-05 15:17:35 -08004156 return false;
4157 }
4158
4159 // Drop non-terminal input events.
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004160 Slog.w(mTag, "Dropping event due to no window focus: " + q.mEvent);
Michael Wright17d28ca2013-10-31 17:47:45 -07004161 return true;
4162 }
4163 return false;
4164 }
4165
Jeff Brown5182c782013-10-15 20:31:52 -07004166 void dump(String prefix, PrintWriter writer) {
4167 if (mNext != null) {
4168 mNext.dump(prefix, writer);
4169 }
4170 }
George Mount41725de2015-04-09 08:23:05 -07004171
4172 private boolean isBack(InputEvent event) {
4173 if (event instanceof KeyEvent) {
4174 return ((KeyEvent) event).getKeyCode() == KeyEvent.KEYCODE_BACK;
4175 } else {
4176 return false;
4177 }
4178 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004179 }
4180
4181 /**
4182 * Base class for implementing an input pipeline stage that supports
4183 * asynchronous and out-of-order processing of input events.
4184 * <p>
4185 * In addition to what a normal input stage can do, an asynchronous
4186 * input stage may also defer an input event that has been delivered to it
4187 * and finish or forward it later.
4188 * </p>
4189 */
4190 abstract class AsyncInputStage extends InputStage {
4191 private final String mTraceCounter;
4192
4193 private QueuedInputEvent mQueueHead;
4194 private QueuedInputEvent mQueueTail;
4195 private int mQueueLength;
4196
4197 protected static final int DEFER = 3;
4198
4199 /**
4200 * Creates an asynchronous input stage.
4201 * @param next The next stage to which events should be forwarded.
4202 * @param traceCounter The name of a counter to record the size of
4203 * the queue of pending events.
4204 */
4205 public AsyncInputStage(InputStage next, String traceCounter) {
4206 super(next);
4207 mTraceCounter = traceCounter;
4208 }
4209
4210 /**
4211 * Marks the event as deferred, which is to say that it will be handled
4212 * asynchronously. The caller is responsible for calling {@link #forward}
4213 * or {@link #finish} later when it is done handling the event.
4214 */
4215 protected void defer(QueuedInputEvent q) {
4216 q.mFlags |= QueuedInputEvent.FLAG_DEFERRED;
4217 enqueue(q);
4218 }
4219
4220 @Override
4221 protected void forward(QueuedInputEvent q) {
4222 // Clear the deferred flag.
4223 q.mFlags &= ~QueuedInputEvent.FLAG_DEFERRED;
4224
4225 // Fast path if the queue is empty.
4226 QueuedInputEvent curr = mQueueHead;
4227 if (curr == null) {
4228 super.forward(q);
4229 return;
4230 }
4231
4232 // Determine whether the event must be serialized behind any others
4233 // before it can be delivered to the next stage. This is done because
4234 // deferred events might be handled out of order by the stage.
4235 final int deviceId = q.mEvent.getDeviceId();
4236 QueuedInputEvent prev = null;
4237 boolean blocked = false;
4238 while (curr != null && curr != q) {
4239 if (!blocked && deviceId == curr.mEvent.getDeviceId()) {
4240 blocked = true;
4241 }
4242 prev = curr;
4243 curr = curr.mNext;
4244 }
4245
4246 // If the event is blocked, then leave it in the queue to be delivered later.
4247 // Note that the event might not yet be in the queue if it was not previously
4248 // deferred so we will enqueue it if needed.
4249 if (blocked) {
4250 if (curr == null) {
4251 enqueue(q);
4252 }
4253 return;
4254 }
4255
4256 // The event is not blocked. Deliver it immediately.
4257 if (curr != null) {
4258 curr = curr.mNext;
4259 dequeue(q, prev);
4260 }
4261 super.forward(q);
4262
4263 // Dequeuing this event may have unblocked successors. Deliver them.
4264 while (curr != null) {
4265 if (deviceId == curr.mEvent.getDeviceId()) {
4266 if ((curr.mFlags & QueuedInputEvent.FLAG_DEFERRED) != 0) {
4267 break;
4268 }
4269 QueuedInputEvent next = curr.mNext;
4270 dequeue(curr, prev);
4271 super.forward(curr);
4272 curr = next;
4273 } else {
4274 prev = curr;
4275 curr = curr.mNext;
4276 }
4277 }
4278 }
4279
4280 @Override
4281 protected void apply(QueuedInputEvent q, int result) {
4282 if (result == DEFER) {
4283 defer(q);
4284 } else {
4285 super.apply(q, result);
4286 }
4287 }
4288
4289 private void enqueue(QueuedInputEvent q) {
4290 if (mQueueTail == null) {
4291 mQueueHead = q;
4292 mQueueTail = q;
4293 } else {
4294 mQueueTail.mNext = q;
4295 mQueueTail = q;
4296 }
4297
4298 mQueueLength += 1;
4299 Trace.traceCounter(Trace.TRACE_TAG_INPUT, mTraceCounter, mQueueLength);
4300 }
4301
4302 private void dequeue(QueuedInputEvent q, QueuedInputEvent prev) {
4303 if (prev == null) {
4304 mQueueHead = q.mNext;
4305 } else {
4306 prev.mNext = q.mNext;
4307 }
4308 if (mQueueTail == q) {
4309 mQueueTail = prev;
4310 }
4311 q.mNext = null;
4312
4313 mQueueLength -= 1;
4314 Trace.traceCounter(Trace.TRACE_TAG_INPUT, mTraceCounter, mQueueLength);
4315 }
Jeff Brown5182c782013-10-15 20:31:52 -07004316
4317 @Override
4318 void dump(String prefix, PrintWriter writer) {
4319 writer.print(prefix);
4320 writer.print(getClass().getName());
4321 writer.print(": mQueueLength=");
4322 writer.println(mQueueLength);
4323
4324 super.dump(prefix, writer);
4325 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004326 }
4327
4328 /**
4329 * Delivers pre-ime input events to a native activity.
4330 * Does not support pointer events.
4331 */
Michael Wrighta44dd262013-04-10 21:12:00 -07004332 final class NativePreImeInputStage extends AsyncInputStage
4333 implements InputQueue.FinishedInputEventCallback {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004334 public NativePreImeInputStage(InputStage next, String traceCounter) {
4335 super(next, traceCounter);
4336 }
4337
4338 @Override
4339 protected int onProcess(QueuedInputEvent q) {
Michael Wrighta44dd262013-04-10 21:12:00 -07004340 if (mInputQueue != null && q.mEvent instanceof KeyEvent) {
4341 mInputQueue.sendInputEvent(q.mEvent, q, true, this);
4342 return DEFER;
4343 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004344 return FORWARD;
4345 }
Michael Wrighta44dd262013-04-10 21:12:00 -07004346
4347 @Override
4348 public void onFinishedInputEvent(Object token, boolean handled) {
4349 QueuedInputEvent q = (QueuedInputEvent)token;
4350 if (handled) {
4351 finish(q, true);
4352 return;
4353 }
4354 forward(q);
4355 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004356 }
4357
4358 /**
4359 * Delivers pre-ime input events to the view hierarchy.
4360 * Does not support pointer events.
4361 */
4362 final class ViewPreImeInputStage extends InputStage {
4363 public ViewPreImeInputStage(InputStage next) {
4364 super(next);
4365 }
4366
4367 @Override
4368 protected int onProcess(QueuedInputEvent q) {
Jeff Brown481c1572012-03-09 14:41:15 -08004369 if (q.mEvent instanceof KeyEvent) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004370 return processKeyEvent(q);
4371 }
4372 return FORWARD;
4373 }
4374
4375 private int processKeyEvent(QueuedInputEvent q) {
4376 final KeyEvent event = (KeyEvent)q.mEvent;
4377 if (mView.dispatchKeyEventPreIme(event)) {
4378 return FINISH_HANDLED;
4379 }
4380 return FORWARD;
4381 }
4382 }
4383
4384 /**
4385 * Delivers input events to the ime.
4386 * Does not support pointer events.
4387 */
4388 final class ImeInputStage extends AsyncInputStage
4389 implements InputMethodManager.FinishedInputEventCallback {
4390 public ImeInputStage(InputStage next, String traceCounter) {
4391 super(next, traceCounter);
4392 }
4393
4394 @Override
4395 protected int onProcess(QueuedInputEvent q) {
keunyoung30f420f2013-08-02 14:23:10 -07004396 if (mLastWasImTarget && !isInLocalFocusMode()) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004397 InputMethodManager imm = InputMethodManager.peekInstance();
4398 if (imm != null) {
4399 final InputEvent event = q.mEvent;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004400 if (DEBUG_IMF) Log.v(mTag, "Sending input event to IME: " + event);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004401 int result = imm.dispatchInputEvent(event, q, this, mHandler);
4402 if (result == InputMethodManager.DISPATCH_HANDLED) {
4403 return FINISH_HANDLED;
4404 } else if (result == InputMethodManager.DISPATCH_NOT_HANDLED) {
Adam Lesinskic0f6eed2013-10-28 16:03:19 -07004405 // The IME could not handle it, so skip along to the next InputStage
4406 return FORWARD;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004407 } else {
4408 return DEFER; // callback will be invoked later
4409 }
4410 }
4411 }
4412 return FORWARD;
4413 }
4414
4415 @Override
4416 public void onFinishedInputEvent(Object token, boolean handled) {
4417 QueuedInputEvent q = (QueuedInputEvent)token;
4418 if (handled) {
4419 finish(q, true);
4420 return;
4421 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004422 forward(q);
4423 }
4424 }
4425
4426 /**
4427 * Performs early processing of post-ime input events.
4428 */
4429 final class EarlyPostImeInputStage extends InputStage {
4430 public EarlyPostImeInputStage(InputStage next) {
4431 super(next);
4432 }
4433
4434 @Override
4435 protected int onProcess(QueuedInputEvent q) {
4436 if (q.mEvent instanceof KeyEvent) {
4437 return processKeyEvent(q);
Jeff Brown4952dfd2011-11-30 19:23:22 -08004438 } else {
Jeff Brown481c1572012-03-09 14:41:15 -08004439 final int source = q.mEvent.getSource();
4440 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004441 return processPointerEvent(q);
Jeff Brown481c1572012-03-09 14:41:15 -08004442 }
Jeff Brown4952dfd2011-11-30 19:23:22 -08004443 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004444 return FORWARD;
4445 }
4446
4447 private int processKeyEvent(QueuedInputEvent q) {
4448 final KeyEvent event = (KeyEvent)q.mEvent;
4449
Vladislav Kaznacheevf847ee32016-11-21 14:11:00 -08004450 if (mAttachInfo.mTooltipHost != null) {
4451 mAttachInfo.mTooltipHost.handleTooltipKey(event);
4452 }
4453
Jeff Brownf9e989d2013-04-04 23:04:03 -07004454 // If the key's purpose is to exit touch mode then we consume it
4455 // and consider it handled.
4456 if (checkForLeavingTouchModeAndConsume(event)) {
4457 return FINISH_HANDLED;
4458 }
4459
4460 // Make sure the fallback event policy sees all keys that will be
4461 // delivered to the view hierarchy.
4462 mFallbackEventHandler.preDispatchKeyEvent(event);
4463 return FORWARD;
4464 }
4465
4466 private int processPointerEvent(QueuedInputEvent q) {
4467 final MotionEvent event = (MotionEvent)q.mEvent;
4468
4469 // Translate the pointer event for compatibility, if needed.
4470 if (mTranslator != null) {
4471 mTranslator.translateEventInScreenToAppWindow(event);
4472 }
4473
Vladislav Kaznacheev7614cdf2017-02-21 11:57:59 -08004474 // Enter touch mode on down or scroll, if it is coming from a touch screen device,
4475 // exit otherwise.
Jeff Brownf9e989d2013-04-04 23:04:03 -07004476 final int action = event.getAction();
Vladislav Kaznacheev7614cdf2017-02-21 11:57:59 -08004477 if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL) {
4478 ensureTouchMode(event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN));
Jeff Brownf9e989d2013-04-04 23:04:03 -07004479 }
4480
Vladislav Kaznacheevf847ee32016-11-21 14:11:00 -08004481 if (action == MotionEvent.ACTION_DOWN && mAttachInfo.mTooltipHost != null) {
4482 mAttachInfo.mTooltipHost.hideTooltip();
4483 }
4484
Jeff Brownf9e989d2013-04-04 23:04:03 -07004485 // Offset the scroll position.
4486 if (mCurScrollY != 0) {
4487 event.offsetLocation(0, mCurScrollY);
4488 }
4489
4490 // Remember the touch position for possible drag-initiation.
4491 if (event.isTouchEvent()) {
4492 mLastTouchPoint.x = event.getRawX();
4493 mLastTouchPoint.y = event.getRawY();
Vladislav Kaznacheevba761122016-01-22 12:09:45 -08004494 mLastTouchSource = event.getSource();
Jeff Brownf9e989d2013-04-04 23:04:03 -07004495 }
4496 return FORWARD;
Jeff Brown4952dfd2011-11-30 19:23:22 -08004497 }
4498 }
4499
Jeff Brownf9e989d2013-04-04 23:04:03 -07004500 /**
4501 * Delivers post-ime input events to a native activity.
4502 */
Michael Wrighta44dd262013-04-10 21:12:00 -07004503 final class NativePostImeInputStage extends AsyncInputStage
4504 implements InputQueue.FinishedInputEventCallback {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004505 public NativePostImeInputStage(InputStage next, String traceCounter) {
4506 super(next, traceCounter);
4507 }
4508
4509 @Override
4510 protected int onProcess(QueuedInputEvent q) {
Michael Wrighta44dd262013-04-10 21:12:00 -07004511 if (mInputQueue != null) {
4512 mInputQueue.sendInputEvent(q.mEvent, q, false, this);
4513 return DEFER;
4514 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004515 return FORWARD;
4516 }
Michael Wrighta44dd262013-04-10 21:12:00 -07004517
4518 @Override
4519 public void onFinishedInputEvent(Object token, boolean handled) {
4520 QueuedInputEvent q = (QueuedInputEvent)token;
4521 if (handled) {
4522 finish(q, true);
4523 return;
4524 }
4525 forward(q);
4526 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004527 }
4528
4529 /**
4530 * Delivers post-ime input events to the view hierarchy.
4531 */
4532 final class ViewPostImeInputStage extends InputStage {
4533 public ViewPostImeInputStage(InputStage next) {
4534 super(next);
4535 }
4536
4537 @Override
4538 protected int onProcess(QueuedInputEvent q) {
Jeff Brown29c0ed22013-01-14 13:50:37 -08004539 if (q.mEvent instanceof KeyEvent) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004540 return processKeyEvent(q);
Jeff Brown29c0ed22013-01-14 13:50:37 -08004541 } else {
4542 final int source = q.mEvent.getSource();
Jeff Brownf9e989d2013-04-04 23:04:03 -07004543 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
4544 return processPointerEvent(q);
4545 } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
4546 return processTrackballEvent(q);
Jeff Brown29c0ed22013-01-14 13:50:37 -08004547 } else {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004548 return processGenericMotionEvent(q);
Jeff Brown29c0ed22013-01-14 13:50:37 -08004549 }
4550 }
Jeff Brown29c0ed22013-01-14 13:50:37 -08004551 }
Jeff Brown29c0ed22013-01-14 13:50:37 -08004552
Michael Wright9d744c72014-02-18 21:27:42 -08004553 @Override
4554 protected void onDeliverToNext(QueuedInputEvent q) {
4555 if (mUnbufferedInputDispatch
4556 && q.mEvent instanceof MotionEvent
4557 && ((MotionEvent)q.mEvent).isTouchEvent()
4558 && isTerminalInputEvent(q.mEvent)) {
4559 mUnbufferedInputDispatch = false;
4560 scheduleConsumeBatchedInput();
4561 }
4562 super.onDeliverToNext(q);
4563 }
4564
Vadim Tryshev01b0c9e2016-11-21 15:25:01 -08004565 private boolean performFocusNavigation(KeyEvent event) {
4566 int direction = 0;
4567 switch (event.getKeyCode()) {
4568 case KeyEvent.KEYCODE_DPAD_LEFT:
4569 if (event.hasNoModifiers()) {
4570 direction = View.FOCUS_LEFT;
4571 }
4572 break;
4573 case KeyEvent.KEYCODE_DPAD_RIGHT:
4574 if (event.hasNoModifiers()) {
4575 direction = View.FOCUS_RIGHT;
4576 }
4577 break;
4578 case KeyEvent.KEYCODE_DPAD_UP:
4579 if (event.hasNoModifiers()) {
4580 direction = View.FOCUS_UP;
4581 }
4582 break;
4583 case KeyEvent.KEYCODE_DPAD_DOWN:
4584 if (event.hasNoModifiers()) {
4585 direction = View.FOCUS_DOWN;
4586 }
4587 break;
4588 case KeyEvent.KEYCODE_TAB:
4589 if (event.hasNoModifiers()) {
4590 direction = View.FOCUS_FORWARD;
4591 } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
4592 direction = View.FOCUS_BACKWARD;
4593 }
4594 break;
4595 }
4596 if (direction != 0) {
4597 View focused = mView.findFocus();
4598 if (focused != null) {
4599 View v = focused.focusSearch(direction);
4600 if (v != null && v != focused) {
4601 // do the math the get the interesting rect
4602 // of previous focused into the coord system of
4603 // newly focused view
4604 focused.getFocusedRect(mTempRect);
4605 if (mView instanceof ViewGroup) {
4606 ((ViewGroup) mView).offsetDescendantRectToMyCoords(
4607 focused, mTempRect);
4608 ((ViewGroup) mView).offsetRectIntoDescendantCoords(
4609 v, mTempRect);
4610 }
4611 if (v.requestFocus(direction, mTempRect)) {
4612 playSoundEffect(SoundEffectConstants
4613 .getContantForFocusDirection(direction));
4614 return true;
4615 }
4616 }
4617
4618 // Give the focused view a last chance to handle the dpad key.
4619 if (mView.dispatchUnhandledMove(focused, direction)) {
4620 return true;
4621 }
4622 } else {
Evan Rosky37df2db2017-01-24 16:35:52 -08004623 if (mView.restoreDefaultFocus()) {
Vadim Tryshev01b0c9e2016-11-21 15:25:01 -08004624 return true;
4625 }
4626 }
4627 }
4628 return false;
4629 }
4630
Vadim Tryshevb5ced222017-01-17 19:31:35 -08004631 private boolean performKeyboardGroupNavigation(int direction) {
Vadim Tryshev01b0c9e2016-11-21 15:25:01 -08004632 final View focused = mView.findFocus();
Evan Rosky37df2db2017-01-24 16:35:52 -08004633 if (focused == null && mView.restoreDefaultFocus()) {
4634 return true;
4635 }
4636 View cluster = focused.keyboardNavigationClusterSearch(null, direction);
Vadim Tryshev01b0c9e2016-11-21 15:25:01 -08004637
Evan Rosky53fcf112017-01-26 14:37:55 -08004638 // Since requestFocus only takes "real" focus directions (and therefore also
4639 // restoreFocusInCluster), convert forward/backward focus into FOCUS_DOWN.
4640 int realDirection = direction;
4641 if (direction == View.FOCUS_FORWARD || direction == View.FOCUS_BACKWARD) {
4642 realDirection = View.FOCUS_DOWN;
4643 }
4644
Evan Rosky3ac64632017-02-13 18:04:43 -08004645 if (cluster != null && cluster.isRootNamespace()) {
4646 // the default cluster. Try to find a non-clustered view to focus.
4647 if (cluster.restoreFocusNotInCluster()) {
4648 return true;
4649 }
4650 // otherwise skip to next actual cluster
4651 cluster = keyboardNavigationClusterSearch(null, direction);
4652 }
4653
Evan Rosky53fcf112017-01-26 14:37:55 -08004654 if (cluster != null && cluster.restoreFocusInCluster(realDirection)) {
Vadim Tryshev01b0c9e2016-11-21 15:25:01 -08004655 return true;
4656 }
4657
4658 return false;
4659 }
4660
Jeff Brownf9e989d2013-04-04 23:04:03 -07004661 private int processKeyEvent(QueuedInputEvent q) {
4662 final KeyEvent event = (KeyEvent)q.mEvent;
4663
4664 // Deliver the key to the view hierarchy.
4665 if (mView.dispatchKeyEvent(event)) {
4666 return FINISH_HANDLED;
Jeff Brown21bc5c92011-02-28 18:27:14 -08004667 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004668
Michael Wright17d28ca2013-10-31 17:47:45 -07004669 if (shouldDropInputEvent(q)) {
4670 return FINISH_NOT_HANDLED;
4671 }
4672
Vadim Tryshev311a5b52017-01-05 18:54:11 -08004673 int groupNavigationDirection = 0;
Vadim Tryshev01b0c9e2016-11-21 15:25:01 -08004674
Evan Rosky516f9e62017-01-23 16:43:52 -08004675 if (event.getAction() == KeyEvent.ACTION_DOWN
4676 && event.getKeyCode() == KeyEvent.KEYCODE_TAB) {
4677 if (KeyEvent.metaStateHasModifiers(event.getMetaState(), KeyEvent.META_META_ON)) {
Vadim Tryshev311a5b52017-01-05 18:54:11 -08004678 groupNavigationDirection = View.FOCUS_FORWARD;
Evan Rosky516f9e62017-01-23 16:43:52 -08004679 } else if (KeyEvent.metaStateHasModifiers(event.getMetaState(),
4680 KeyEvent.META_META_ON | KeyEvent.META_SHIFT_ON)) {
Vadim Tryshev311a5b52017-01-05 18:54:11 -08004681 groupNavigationDirection = View.FOCUS_BACKWARD;
Vadim Tryshev01b0c9e2016-11-21 15:25:01 -08004682 }
4683 }
4684
Peeyush Agarwale631e322016-10-19 11:41:42 +01004685 // If a modifier is held, try to interpret the key as a shortcut.
Jeff Brownf9e989d2013-04-04 23:04:03 -07004686 if (event.getAction() == KeyEvent.ACTION_DOWN
Peeyush Agarwale631e322016-10-19 11:41:42 +01004687 && !KeyEvent.metaStateHasNoModifiers(event.getMetaState())
Jeff Brownf9e989d2013-04-04 23:04:03 -07004688 && event.getRepeatCount() == 0
Vadim Tryshev01b0c9e2016-11-21 15:25:01 -08004689 && !KeyEvent.isModifierKey(event.getKeyCode())
Vadim Tryshev311a5b52017-01-05 18:54:11 -08004690 && groupNavigationDirection == 0) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004691 if (mView.dispatchKeyShortcutEvent(event)) {
4692 return FINISH_HANDLED;
4693 }
Michael Wright17d28ca2013-10-31 17:47:45 -07004694 if (shouldDropInputEvent(q)) {
4695 return FINISH_NOT_HANDLED;
4696 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004697 }
4698
4699 // Apply the fallback event policy.
4700 if (mFallbackEventHandler.dispatchKeyEvent(event)) {
4701 return FINISH_HANDLED;
4702 }
Michael Wright17d28ca2013-10-31 17:47:45 -07004703 if (shouldDropInputEvent(q)) {
4704 return FINISH_NOT_HANDLED;
4705 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004706
4707 // Handle automatic focus changes.
4708 if (event.getAction() == KeyEvent.ACTION_DOWN) {
Vadim Tryshev311a5b52017-01-05 18:54:11 -08004709 if (groupNavigationDirection != 0) {
Vadim Tryshevb5ced222017-01-17 19:31:35 -08004710 if (performKeyboardGroupNavigation(groupNavigationDirection)) {
Vadim Tryshev01b0c9e2016-11-21 15:25:01 -08004711 return FINISH_HANDLED;
4712 }
4713 } else {
4714 if (performFocusNavigation(event)) {
4715 return FINISH_HANDLED;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004716 }
4717 }
4718 }
4719 return FORWARD;
Jeff Brown21bc5c92011-02-28 18:27:14 -08004720 }
4721
Jeff Brownf9e989d2013-04-04 23:04:03 -07004722 private int processPointerEvent(QueuedInputEvent q) {
4723 final MotionEvent event = (MotionEvent)q.mEvent;
4724
Vladislav Kaznacheev527905e2016-02-16 16:20:56 -08004725 mAttachInfo.mUnbufferedDispatchRequested = false;
Vladislav Kaznacheev527905e2016-02-16 16:20:56 -08004726 mAttachInfo.mHandlingPointerEvent = true;
Vladislav Kaznacheev3787de12016-12-21 10:36:35 -08004727 boolean handled = mView.dispatchPointerEvent(event);
Vladislav Kaznacheev527905e2016-02-16 16:20:56 -08004728 maybeUpdatePointerIcon(event);
Vladislav Kaznacheevf847ee32016-11-21 14:11:00 -08004729 maybeUpdateTooltip(event);
Vladislav Kaznacheev527905e2016-02-16 16:20:56 -08004730 mAttachInfo.mHandlingPointerEvent = false;
4731 if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {
4732 mUnbufferedInputDispatch = true;
4733 if (mConsumeBatchedInputScheduled) {
4734 scheduleConsumeBatchedInputImmediately();
4735 }
4736 }
4737 return handled ? FINISH_HANDLED : FORWARD;
4738 }
4739
4740 private void maybeUpdatePointerIcon(MotionEvent event) {
Michael Wrightf9d9ce772016-05-13 17:44:16 +01004741 if (event.getPointerCount() == 1 && event.isFromSource(InputDevice.SOURCE_MOUSE)) {
Jun Mukai1db53972015-09-11 18:08:31 -07004742 if (event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER
4743 || event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
Michael Wrightf9d9ce772016-05-13 17:44:16 +01004744 // Other apps or the window manager may change the icon type outside of
4745 // this app, therefore the icon type has to be reset on enter/exit event.
4746 mPointerIconType = PointerIcon.TYPE_NOT_SPECIFIED;
Jun Mukai1db53972015-09-11 18:08:31 -07004747 }
4748
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08004749 if (event.getActionMasked() != MotionEvent.ACTION_HOVER_EXIT) {
4750 if (!updatePointerIcon(event) &&
4751 event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE) {
Michael Wrightf9d9ce772016-05-13 17:44:16 +01004752 mPointerIconType = PointerIcon.TYPE_NOT_SPECIFIED;
Jun Mukai1db53972015-09-11 18:08:31 -07004753 }
4754 }
4755 }
Jeff Brown3915bb82010-11-05 15:02:16 -07004756 }
4757
Jeff Brownf9e989d2013-04-04 23:04:03 -07004758 private int processTrackballEvent(QueuedInputEvent q) {
4759 final MotionEvent event = (MotionEvent)q.mEvent;
4760
Vladislav Kaznacheev3787de12016-12-21 10:36:35 -08004761 if (event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE)) {
4762 if (!hasPointerCapture() || mView.dispatchCapturedPointerEvent(event)) {
4763 return FINISH_HANDLED;
4764 }
4765 }
4766
Jeff Brownf9e989d2013-04-04 23:04:03 -07004767 if (mView.dispatchTrackballEvent(event)) {
4768 return FINISH_HANDLED;
4769 }
4770 return FORWARD;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004771 }
4772
Jeff Brownf9e989d2013-04-04 23:04:03 -07004773 private int processGenericMotionEvent(QueuedInputEvent q) {
4774 final MotionEvent event = (MotionEvent)q.mEvent;
Jeff Brown00fa7bd2010-07-02 15:37:36 -07004775
Jeff Brownf9e989d2013-04-04 23:04:03 -07004776 // Deliver the event to the view.
4777 if (mView.dispatchGenericMotionEvent(event)) {
4778 return FINISH_HANDLED;
4779 }
4780 return FORWARD;
Jeff Brown3915bb82010-11-05 15:02:16 -07004781 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07004782 }
4783
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08004784 private void resetPointerIcon(MotionEvent event) {
Michael Wrightf9d9ce772016-05-13 17:44:16 +01004785 mPointerIconType = PointerIcon.TYPE_NOT_SPECIFIED;
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08004786 updatePointerIcon(event);
4787 }
4788
4789 private boolean updatePointerIcon(MotionEvent event) {
Michael Wrightf9d9ce772016-05-13 17:44:16 +01004790 final int pointerIndex = 0;
4791 final float x = event.getX(pointerIndex);
4792 final float y = event.getY(pointerIndex);
Andrii Kulian33c1bc52016-02-29 10:38:59 -08004793 if (mView == null) {
4794 // E.g. click outside a popup to dismiss it
4795 Slog.d(mTag, "updatePointerIcon called after view was removed");
4796 return false;
4797 }
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08004798 if (x < 0 || x >= mView.getWidth() || y < 0 || y >= mView.getHeight()) {
Andrii Kulian33c1bc52016-02-29 10:38:59 -08004799 // E.g. when moving window divider with mouse
4800 Slog.d(mTag, "updatePointerIcon called with position out of bounds");
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08004801 return false;
4802 }
Michael Wrightf9d9ce772016-05-13 17:44:16 +01004803 final PointerIcon pointerIcon = mView.onResolvePointerIcon(event, pointerIndex);
4804 final int pointerType = (pointerIcon != null) ?
4805 pointerIcon.getType() : PointerIcon.TYPE_DEFAULT;
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08004806
Michael Wrightf9d9ce772016-05-13 17:44:16 +01004807 if (mPointerIconType != pointerType) {
4808 mPointerIconType = pointerType;
Vladislav Kaznacheeve40fb272017-01-03 16:45:42 -08004809 mCustomPointerIcon = null;
Michael Wrightf9d9ce772016-05-13 17:44:16 +01004810 if (mPointerIconType != PointerIcon.TYPE_CUSTOM) {
Michael Wrightf9d9ce772016-05-13 17:44:16 +01004811 InputManager.getInstance().setPointerIconType(pointerType);
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08004812 return true;
4813 }
4814 }
Michael Wrightf9d9ce772016-05-13 17:44:16 +01004815 if (mPointerIconType == PointerIcon.TYPE_CUSTOM &&
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08004816 !pointerIcon.equals(mCustomPointerIcon)) {
4817 mCustomPointerIcon = pointerIcon;
4818 InputManager.getInstance().setCustomPointerIcon(mCustomPointerIcon);
4819 }
4820 return true;
4821 }
4822
Vladislav Kaznacheevf847ee32016-11-21 14:11:00 -08004823 private void maybeUpdateTooltip(MotionEvent event) {
4824 if (event.getPointerCount() != 1) {
4825 return;
4826 }
4827 final int action = event.getActionMasked();
4828 if (action != MotionEvent.ACTION_HOVER_ENTER
4829 && action != MotionEvent.ACTION_HOVER_MOVE
4830 && action != MotionEvent.ACTION_HOVER_EXIT) {
4831 return;
4832 }
4833 AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
4834 if (manager.isEnabled() && manager.isTouchExplorationEnabled()) {
4835 return;
4836 }
4837 if (mView == null) {
4838 Slog.d(mTag, "maybeUpdateTooltip called after view was removed");
4839 return;
4840 }
4841 mView.dispatchTooltipHoverEvent(event);
4842 }
4843
Jeff Brownf9e989d2013-04-04 23:04:03 -07004844 /**
Jeff Brown678a1252013-04-09 17:46:25 -07004845 * Performs synthesis of new input events from unhandled input events.
Jeff Brownf9e989d2013-04-04 23:04:03 -07004846 */
4847 final class SyntheticInputStage extends InputStage {
Jeff Brown678a1252013-04-09 17:46:25 -07004848 private final SyntheticTrackballHandler mTrackball = new SyntheticTrackballHandler();
4849 private final SyntheticJoystickHandler mJoystick = new SyntheticJoystickHandler();
4850 private final SyntheticTouchNavigationHandler mTouchNavigation =
4851 new SyntheticTouchNavigationHandler();
Michael Wright899d7052014-04-23 17:23:39 -07004852 private final SyntheticKeyboardHandler mKeyboard = new SyntheticKeyboardHandler();
Jeff Brownf9e989d2013-04-04 23:04:03 -07004853
4854 public SyntheticInputStage() {
4855 super(null);
Jeff Brown21bc5c92011-02-28 18:27:14 -08004856 }
4857
Jeff Brownf9e989d2013-04-04 23:04:03 -07004858 @Override
4859 protected int onProcess(QueuedInputEvent q) {
4860 q.mFlags |= QueuedInputEvent.FLAG_RESYNTHESIZED;
4861 if (q.mEvent instanceof MotionEvent) {
Jeff Brown678a1252013-04-09 17:46:25 -07004862 final MotionEvent event = (MotionEvent)q.mEvent;
4863 final int source = event.getSource();
Jeff Brownf9e989d2013-04-04 23:04:03 -07004864 if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
Jeff Brown678a1252013-04-09 17:46:25 -07004865 mTrackball.process(event);
4866 return FINISH_HANDLED;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004867 } else if ((source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
Jeff Brown678a1252013-04-09 17:46:25 -07004868 mJoystick.process(event);
4869 return FINISH_HANDLED;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004870 } else if ((source & InputDevice.SOURCE_TOUCH_NAVIGATION)
4871 == InputDevice.SOURCE_TOUCH_NAVIGATION) {
Jeff Brown678a1252013-04-09 17:46:25 -07004872 mTouchNavigation.process(event);
4873 return FINISH_HANDLED;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004874 }
Michael Wright899d7052014-04-23 17:23:39 -07004875 } else if ((q.mFlags & QueuedInputEvent.FLAG_UNHANDLED) != 0) {
4876 mKeyboard.process((KeyEvent)q.mEvent);
4877 return FINISH_HANDLED;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004878 }
Michael Wright899d7052014-04-23 17:23:39 -07004879
Jeff Brownf9e989d2013-04-04 23:04:03 -07004880 return FORWARD;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004881 }
4882
Jeff Brownf9e989d2013-04-04 23:04:03 -07004883 @Override
4884 protected void onDeliverToNext(QueuedInputEvent q) {
4885 if ((q.mFlags & QueuedInputEvent.FLAG_RESYNTHESIZED) == 0) {
4886 // Cancel related synthetic events if any prior stage has handled the event.
4887 if (q.mEvent instanceof MotionEvent) {
Jeff Brown678a1252013-04-09 17:46:25 -07004888 final MotionEvent event = (MotionEvent)q.mEvent;
4889 final int source = event.getSource();
Jeff Brownf9e989d2013-04-04 23:04:03 -07004890 if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
Jeff Brown678a1252013-04-09 17:46:25 -07004891 mTrackball.cancel(event);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004892 } else if ((source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
Jeff Brown678a1252013-04-09 17:46:25 -07004893 mJoystick.cancel(event);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004894 } else if ((source & InputDevice.SOURCE_TOUCH_NAVIGATION)
4895 == InputDevice.SOURCE_TOUCH_NAVIGATION) {
Jeff Brown678a1252013-04-09 17:46:25 -07004896 mTouchNavigation.cancel(event);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004897 }
4898 }
4899 }
4900 super.onDeliverToNext(q);
4901 }
Jeff Brown678a1252013-04-09 17:46:25 -07004902 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07004903
Jeff Brown678a1252013-04-09 17:46:25 -07004904 /**
4905 * Creates dpad events from unhandled trackball movements.
4906 */
4907 final class SyntheticTrackballHandler {
4908 private final TrackballAxis mX = new TrackballAxis();
4909 private final TrackballAxis mY = new TrackballAxis();
4910 private long mLastTime;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004911
Jeff Brown678a1252013-04-09 17:46:25 -07004912 public void process(MotionEvent event) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004913 // Translate the trackball event into DPAD keys and try to deliver those.
Jeff Brownf9e989d2013-04-04 23:04:03 -07004914 long curTime = SystemClock.uptimeMillis();
Jeff Brown678a1252013-04-09 17:46:25 -07004915 if ((mLastTime + MAX_TRACKBALL_DELAY) < curTime) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07004916 // It has been too long since the last movement,
4917 // so restart at the beginning.
Jeff Brown678a1252013-04-09 17:46:25 -07004918 mX.reset(0);
4919 mY.reset(0);
4920 mLastTime = curTime;
Jeff Brownf9e989d2013-04-04 23:04:03 -07004921 }
4922
4923 final int action = event.getAction();
4924 final int metaState = event.getMetaState();
4925 switch (action) {
4926 case MotionEvent.ACTION_DOWN:
Jeff Brown678a1252013-04-09 17:46:25 -07004927 mX.reset(2);
4928 mY.reset(2);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004929 enqueueInputEvent(new KeyEvent(curTime, curTime,
4930 KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, 0, metaState,
4931 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
4932 InputDevice.SOURCE_KEYBOARD));
4933 break;
4934 case MotionEvent.ACTION_UP:
Jeff Brown678a1252013-04-09 17:46:25 -07004935 mX.reset(2);
4936 mY.reset(2);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004937 enqueueInputEvent(new KeyEvent(curTime, curTime,
4938 KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, 0, metaState,
4939 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
4940 InputDevice.SOURCE_KEYBOARD));
4941 break;
4942 }
4943
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004944 if (DEBUG_TRACKBALL) Log.v(mTag, "TB X=" + mX.position + " step="
Jeff Brown678a1252013-04-09 17:46:25 -07004945 + mX.step + " dir=" + mX.dir + " acc=" + mX.acceleration
Jeff Brownf9e989d2013-04-04 23:04:03 -07004946 + " move=" + event.getX()
Jeff Brown678a1252013-04-09 17:46:25 -07004947 + " / Y=" + mY.position + " step="
4948 + mY.step + " dir=" + mY.dir + " acc=" + mY.acceleration
Jeff Brownf9e989d2013-04-04 23:04:03 -07004949 + " move=" + event.getY());
Jeff Brown678a1252013-04-09 17:46:25 -07004950 final float xOff = mX.collect(event.getX(), event.getEventTime(), "X");
4951 final float yOff = mY.collect(event.getY(), event.getEventTime(), "Y");
Jeff Brownf9e989d2013-04-04 23:04:03 -07004952
4953 // Generate DPAD events based on the trackball movement.
4954 // We pick the axis that has moved the most as the direction of
4955 // the DPAD. When we generate DPAD events for one axis, then the
4956 // other axis is reset -- we don't want to perform DPAD jumps due
4957 // to slight movements in the trackball when making major movements
4958 // along the other axis.
4959 int keycode = 0;
4960 int movement = 0;
4961 float accel = 1;
4962 if (xOff > yOff) {
Jeff Brown678a1252013-04-09 17:46:25 -07004963 movement = mX.generate();
Jeff Brownf9e989d2013-04-04 23:04:03 -07004964 if (movement != 0) {
4965 keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_RIGHT
4966 : KeyEvent.KEYCODE_DPAD_LEFT;
Jeff Brown678a1252013-04-09 17:46:25 -07004967 accel = mX.acceleration;
4968 mY.reset(2);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004969 }
4970 } else if (yOff > 0) {
Jeff Brown678a1252013-04-09 17:46:25 -07004971 movement = mY.generate();
Jeff Brownf9e989d2013-04-04 23:04:03 -07004972 if (movement != 0) {
4973 keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_DOWN
4974 : KeyEvent.KEYCODE_DPAD_UP;
Jeff Brown678a1252013-04-09 17:46:25 -07004975 accel = mY.acceleration;
4976 mX.reset(2);
Jeff Brownf9e989d2013-04-04 23:04:03 -07004977 }
4978 }
4979
4980 if (keycode != 0) {
4981 if (movement < 0) movement = -movement;
4982 int accelMovement = (int)(movement * accel);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004983 if (DEBUG_TRACKBALL) Log.v(mTag, "Move: movement=" + movement
Jeff Brownf9e989d2013-04-04 23:04:03 -07004984 + " accelMovement=" + accelMovement
4985 + " accel=" + accel);
4986 if (accelMovement > movement) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004987 if (DEBUG_TRACKBALL) Log.v(mTag, "Delivering fake DPAD: "
Jeff Brownf9e989d2013-04-04 23:04:03 -07004988 + keycode);
4989 movement--;
4990 int repeatCount = accelMovement - movement;
4991 enqueueInputEvent(new KeyEvent(curTime, curTime,
4992 KeyEvent.ACTION_MULTIPLE, keycode, repeatCount, metaState,
4993 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
4994 InputDevice.SOURCE_KEYBOARD));
4995 }
4996 while (movement > 0) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08004997 if (DEBUG_TRACKBALL) Log.v(mTag, "Delivering fake DPAD: "
Jeff Brownf9e989d2013-04-04 23:04:03 -07004998 + keycode);
4999 movement--;
5000 curTime = SystemClock.uptimeMillis();
5001 enqueueInputEvent(new KeyEvent(curTime, curTime,
5002 KeyEvent.ACTION_DOWN, keycode, 0, metaState,
5003 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
5004 InputDevice.SOURCE_KEYBOARD));
5005 enqueueInputEvent(new KeyEvent(curTime, curTime,
5006 KeyEvent.ACTION_UP, keycode, 0, metaState,
5007 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
5008 InputDevice.SOURCE_KEYBOARD));
5009 }
Jeff Brown678a1252013-04-09 17:46:25 -07005010 mLastTime = curTime;
Jeff Brownf9e989d2013-04-04 23:04:03 -07005011 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07005012 }
5013
Jeff Brown678a1252013-04-09 17:46:25 -07005014 public void cancel(MotionEvent event) {
5015 mLastTime = Integer.MIN_VALUE;
Jeff Brown3915bb82010-11-05 15:02:16 -07005016
Jeff Brownf9e989d2013-04-04 23:04:03 -07005017 // If we reach this, we consumed a trackball event.
5018 // Because we will not translate the trackball event into a key event,
5019 // touch mode will not exit, so we exit touch mode here.
5020 if (mView != null && mAdded) {
5021 ensureTouchMode(false);
Jeff Brown00fa7bd2010-07-02 15:37:36 -07005022 }
5023 }
Jeff Brown678a1252013-04-09 17:46:25 -07005024 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005025
Jeff Brown678a1252013-04-09 17:46:25 -07005026 /**
5027 * Maintains state information for a single trackball axis, generating
5028 * discrete (DPAD) movements based on raw trackball motion.
5029 */
5030 static final class TrackballAxis {
5031 /**
5032 * The maximum amount of acceleration we will apply.
5033 */
5034 static final float MAX_ACCELERATION = 20;
5035
5036 /**
5037 * The maximum amount of time (in milliseconds) between events in order
5038 * for us to consider the user to be doing fast trackball movements,
5039 * and thus apply an acceleration.
5040 */
5041 static final long FAST_MOVE_TIME = 150;
5042
5043 /**
5044 * Scaling factor to the time (in milliseconds) between events to how
5045 * much to multiple/divide the current acceleration. When movement
5046 * is < FAST_MOVE_TIME this multiplies the acceleration; when >
5047 * FAST_MOVE_TIME it divides it.
5048 */
5049 static final float ACCEL_MOVE_SCALING_FACTOR = (1.0f/40);
5050
5051 static final float FIRST_MOVEMENT_THRESHOLD = 0.5f;
5052 static final float SECOND_CUMULATIVE_MOVEMENT_THRESHOLD = 2.0f;
5053 static final float SUBSEQUENT_INCREMENTAL_MOVEMENT_THRESHOLD = 1.0f;
5054
5055 float position;
5056 float acceleration = 1;
5057 long lastMoveTime = 0;
5058 int step;
5059 int dir;
5060 int nonAccelMovement;
5061
5062 void reset(int _step) {
5063 position = 0;
5064 acceleration = 1;
5065 lastMoveTime = 0;
5066 step = _step;
5067 dir = 0;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005068 }
5069
Jeff Brown678a1252013-04-09 17:46:25 -07005070 /**
5071 * Add trackball movement into the state. If the direction of movement
5072 * has been reversed, the state is reset before adding the
5073 * movement (so that you don't have to compensate for any previously
5074 * collected movement before see the result of the movement in the
5075 * new direction).
5076 *
5077 * @return Returns the absolute value of the amount of movement
5078 * collected so far.
5079 */
5080 float collect(float off, long time, String axis) {
5081 long normTime;
5082 if (off > 0) {
5083 normTime = (long)(off * FAST_MOVE_TIME);
5084 if (dir < 0) {
5085 if (DEBUG_TRACKBALL) Log.v(TAG, axis + " reversed to positive!");
5086 position = 0;
5087 step = 0;
5088 acceleration = 1;
5089 lastMoveTime = 0;
5090 }
5091 dir = 1;
5092 } else if (off < 0) {
5093 normTime = (long)((-off) * FAST_MOVE_TIME);
5094 if (dir > 0) {
5095 if (DEBUG_TRACKBALL) Log.v(TAG, axis + " reversed to negative!");
5096 position = 0;
5097 step = 0;
5098 acceleration = 1;
5099 lastMoveTime = 0;
5100 }
5101 dir = -1;
5102 } else {
5103 normTime = 0;
5104 }
5105
5106 // The number of milliseconds between each movement that is
5107 // considered "normal" and will not result in any acceleration
5108 // or deceleration, scaled by the offset we have here.
5109 if (normTime > 0) {
5110 long delta = time - lastMoveTime;
5111 lastMoveTime = time;
5112 float acc = acceleration;
5113 if (delta < normTime) {
5114 // The user is scrolling rapidly, so increase acceleration.
5115 float scale = (normTime-delta) * ACCEL_MOVE_SCALING_FACTOR;
5116 if (scale > 1) acc *= scale;
5117 if (DEBUG_TRACKBALL) Log.v(TAG, axis + " accelerate: off="
5118 + off + " normTime=" + normTime + " delta=" + delta
5119 + " scale=" + scale + " acc=" + acc);
5120 acceleration = acc < MAX_ACCELERATION ? acc : MAX_ACCELERATION;
5121 } else {
5122 // The user is scrolling slowly, so decrease acceleration.
5123 float scale = (delta-normTime) * ACCEL_MOVE_SCALING_FACTOR;
5124 if (scale > 1) acc /= scale;
5125 if (DEBUG_TRACKBALL) Log.v(TAG, axis + " deccelerate: off="
5126 + off + " normTime=" + normTime + " delta=" + delta
5127 + " scale=" + scale + " acc=" + acc);
5128 acceleration = acc > 1 ? acc : 1;
5129 }
5130 }
5131 position += off;
5132 return Math.abs(position);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005133 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005134
Jeff Brown678a1252013-04-09 17:46:25 -07005135 /**
5136 * Generate the number of discrete movement events appropriate for
5137 * the currently collected trackball movement.
5138 *
5139 * @return Returns the number of discrete movements, either positive
5140 * or negative, or 0 if there is not enough trackball movement yet
5141 * for a discrete movement.
5142 */
5143 int generate() {
5144 int movement = 0;
5145 nonAccelMovement = 0;
5146 do {
5147 final int dir = position >= 0 ? 1 : -1;
5148 switch (step) {
5149 // If we are going to execute the first step, then we want
5150 // to do this as soon as possible instead of waiting for
5151 // a full movement, in order to make things look responsive.
5152 case 0:
5153 if (Math.abs(position) < FIRST_MOVEMENT_THRESHOLD) {
5154 return movement;
5155 }
5156 movement += dir;
5157 nonAccelMovement += dir;
5158 step = 1;
5159 break;
5160 // If we have generated the first movement, then we need
5161 // to wait for the second complete trackball motion before
5162 // generating the second discrete movement.
5163 case 1:
5164 if (Math.abs(position) < SECOND_CUMULATIVE_MOVEMENT_THRESHOLD) {
5165 return movement;
5166 }
5167 movement += dir;
5168 nonAccelMovement += dir;
5169 position -= SECOND_CUMULATIVE_MOVEMENT_THRESHOLD * dir;
5170 step = 2;
5171 break;
5172 // After the first two, we generate discrete movements
5173 // consistently with the trackball, applying an acceleration
5174 // if the trackball is moving quickly. This is a simple
5175 // acceleration on top of what we already compute based
5176 // on how quickly the wheel is being turned, to apply
5177 // a longer increasing acceleration to continuous movement
5178 // in one direction.
5179 default:
5180 if (Math.abs(position) < SUBSEQUENT_INCREMENTAL_MOVEMENT_THRESHOLD) {
5181 return movement;
5182 }
5183 movement += dir;
5184 position -= dir * SUBSEQUENT_INCREMENTAL_MOVEMENT_THRESHOLD;
5185 float acc = acceleration;
5186 acc *= 1.1f;
5187 acceleration = acc < MAX_ACCELERATION ? acc : acceleration;
5188 break;
5189 }
5190 } while (true);
5191 }
5192 }
5193
5194 /**
5195 * Creates dpad events from unhandled joystick movements.
5196 */
5197 final class SyntheticJoystickHandler extends Handler {
Michael Wright9adca062014-03-19 11:51:26 -07005198 private final static String TAG = "SyntheticJoystickHandler";
Jeff Brown678a1252013-04-09 17:46:25 -07005199 private final static int MSG_ENQUEUE_X_AXIS_KEY_REPEAT = 1;
5200 private final static int MSG_ENQUEUE_Y_AXIS_KEY_REPEAT = 2;
5201
5202 private int mLastXDirection;
5203 private int mLastYDirection;
5204 private int mLastXKeyCode;
5205 private int mLastYKeyCode;
5206
5207 public SyntheticJoystickHandler() {
5208 super(true);
5209 }
5210
5211 @Override
5212 public void handleMessage(Message msg) {
5213 switch (msg.what) {
5214 case MSG_ENQUEUE_X_AXIS_KEY_REPEAT:
5215 case MSG_ENQUEUE_Y_AXIS_KEY_REPEAT: {
5216 KeyEvent oldEvent = (KeyEvent)msg.obj;
5217 KeyEvent e = KeyEvent.changeTimeRepeat(oldEvent,
5218 SystemClock.uptimeMillis(),
5219 oldEvent.getRepeatCount() + 1);
5220 if (mAttachInfo.mHasWindowFocus) {
5221 enqueueInputEvent(e);
5222 Message m = obtainMessage(msg.what, e);
5223 m.setAsynchronous(true);
5224 sendMessageDelayed(m, ViewConfiguration.getKeyRepeatDelay());
5225 }
5226 } break;
5227 }
5228 }
5229
5230 public void process(MotionEvent event) {
Michael Wright9adca062014-03-19 11:51:26 -07005231 switch(event.getActionMasked()) {
5232 case MotionEvent.ACTION_CANCEL:
5233 cancel(event);
5234 break;
5235 case MotionEvent.ACTION_MOVE:
5236 update(event, true);
5237 break;
5238 default:
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005239 Log.w(mTag, "Unexpected action: " + event.getActionMasked());
Michael Wright9adca062014-03-19 11:51:26 -07005240 }
Jeff Brown678a1252013-04-09 17:46:25 -07005241 }
5242
Michael Wright9adca062014-03-19 11:51:26 -07005243 private void cancel(MotionEvent event) {
5244 removeMessages(MSG_ENQUEUE_X_AXIS_KEY_REPEAT);
5245 removeMessages(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT);
Jeff Brown678a1252013-04-09 17:46:25 -07005246 update(event, false);
5247 }
5248
5249 private void update(MotionEvent event, boolean synthesizeNewKeys) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07005250 final long time = event.getEventTime();
5251 final int metaState = event.getMetaState();
5252 final int deviceId = event.getDeviceId();
5253 final int source = event.getSource();
5254
5255 int xDirection = joystickAxisValueToDirection(
5256 event.getAxisValue(MotionEvent.AXIS_HAT_X));
5257 if (xDirection == 0) {
5258 xDirection = joystickAxisValueToDirection(event.getX());
Jeff Browncb1404e2011-01-15 18:14:15 -08005259 }
5260
Jeff Brownf9e989d2013-04-04 23:04:03 -07005261 int yDirection = joystickAxisValueToDirection(
5262 event.getAxisValue(MotionEvent.AXIS_HAT_Y));
5263 if (yDirection == 0) {
5264 yDirection = joystickAxisValueToDirection(event.getY());
5265 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005266
Jeff Brown678a1252013-04-09 17:46:25 -07005267 if (xDirection != mLastXDirection) {
5268 if (mLastXKeyCode != 0) {
5269 removeMessages(MSG_ENQUEUE_X_AXIS_KEY_REPEAT);
Jeff Brownf9e989d2013-04-04 23:04:03 -07005270 enqueueInputEvent(new KeyEvent(time, time,
Jeff Brown678a1252013-04-09 17:46:25 -07005271 KeyEvent.ACTION_UP, mLastXKeyCode, 0, metaState,
Jeff Brownf9e989d2013-04-04 23:04:03 -07005272 deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
Jeff Brown678a1252013-04-09 17:46:25 -07005273 mLastXKeyCode = 0;
Jeff Brownf9e989d2013-04-04 23:04:03 -07005274 }
5275
Jeff Brown678a1252013-04-09 17:46:25 -07005276 mLastXDirection = xDirection;
Jeff Brownf9e989d2013-04-04 23:04:03 -07005277
5278 if (xDirection != 0 && synthesizeNewKeys) {
Jeff Brown678a1252013-04-09 17:46:25 -07005279 mLastXKeyCode = xDirection > 0
Jeff Brownf9e989d2013-04-04 23:04:03 -07005280 ? KeyEvent.KEYCODE_DPAD_RIGHT : KeyEvent.KEYCODE_DPAD_LEFT;
5281 final KeyEvent e = new KeyEvent(time, time,
Jeff Brown678a1252013-04-09 17:46:25 -07005282 KeyEvent.ACTION_DOWN, mLastXKeyCode, 0, metaState,
Jeff Brownf9e989d2013-04-04 23:04:03 -07005283 deviceId, 0, KeyEvent.FLAG_FALLBACK, source);
5284 enqueueInputEvent(e);
Jeff Brown678a1252013-04-09 17:46:25 -07005285 Message m = obtainMessage(MSG_ENQUEUE_X_AXIS_KEY_REPEAT, e);
Jeff Brownf9e989d2013-04-04 23:04:03 -07005286 m.setAsynchronous(true);
Michael Wrightb9618522013-04-10 15:20:56 -07005287 sendMessageDelayed(m, ViewConfiguration.getKeyRepeatTimeout());
Jeff Brownf9e989d2013-04-04 23:04:03 -07005288 }
5289 }
5290
Jeff Brown678a1252013-04-09 17:46:25 -07005291 if (yDirection != mLastYDirection) {
5292 if (mLastYKeyCode != 0) {
5293 removeMessages(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT);
Jeff Brownf9e989d2013-04-04 23:04:03 -07005294 enqueueInputEvent(new KeyEvent(time, time,
Jeff Brown678a1252013-04-09 17:46:25 -07005295 KeyEvent.ACTION_UP, mLastYKeyCode, 0, metaState,
Jeff Brownf9e989d2013-04-04 23:04:03 -07005296 deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
Jeff Brown678a1252013-04-09 17:46:25 -07005297 mLastYKeyCode = 0;
Jeff Brownf9e989d2013-04-04 23:04:03 -07005298 }
5299
Jeff Brown678a1252013-04-09 17:46:25 -07005300 mLastYDirection = yDirection;
Jeff Brownf9e989d2013-04-04 23:04:03 -07005301
5302 if (yDirection != 0 && synthesizeNewKeys) {
Jeff Brown678a1252013-04-09 17:46:25 -07005303 mLastYKeyCode = yDirection > 0
Jeff Brownf9e989d2013-04-04 23:04:03 -07005304 ? KeyEvent.KEYCODE_DPAD_DOWN : KeyEvent.KEYCODE_DPAD_UP;
5305 final KeyEvent e = new KeyEvent(time, time,
Jeff Brown678a1252013-04-09 17:46:25 -07005306 KeyEvent.ACTION_DOWN, mLastYKeyCode, 0, metaState,
Jeff Brownf9e989d2013-04-04 23:04:03 -07005307 deviceId, 0, KeyEvent.FLAG_FALLBACK, source);
5308 enqueueInputEvent(e);
Jeff Brown678a1252013-04-09 17:46:25 -07005309 Message m = obtainMessage(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT, e);
Jeff Brownf9e989d2013-04-04 23:04:03 -07005310 m.setAsynchronous(true);
Jeff Brown678a1252013-04-09 17:46:25 -07005311 sendMessageDelayed(m, ViewConfiguration.getKeyRepeatTimeout());
Jeff Brownf9e989d2013-04-04 23:04:03 -07005312 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005313 }
5314 }
5315
Jeff Brownf9e989d2013-04-04 23:04:03 -07005316 private int joystickAxisValueToDirection(float value) {
5317 if (value >= 0.5f) {
5318 return 1;
5319 } else if (value <= -0.5f) {
5320 return -1;
5321 } else {
5322 return 0;
Jeff Browncb1404e2011-01-15 18:14:15 -08005323 }
5324 }
Jeff Brown678a1252013-04-09 17:46:25 -07005325 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005326
Jeff Brown678a1252013-04-09 17:46:25 -07005327 /**
5328 * Creates dpad events from unhandled touch navigation movements.
5329 */
5330 final class SyntheticTouchNavigationHandler extends Handler {
Jeff Brown4dac9012013-04-10 01:03:19 -07005331 private static final String LOCAL_TAG = "SyntheticTouchNavigationHandler";
5332 private static final boolean LOCAL_DEBUG = false;
Jeff Brown678a1252013-04-09 17:46:25 -07005333
Jeff Brown4dac9012013-04-10 01:03:19 -07005334 // Assumed nominal width and height in millimeters of a touch navigation pad,
5335 // if no resolution information is available from the input system.
5336 private static final float DEFAULT_WIDTH_MILLIMETERS = 48;
5337 private static final float DEFAULT_HEIGHT_MILLIMETERS = 48;
Jeff Brown678a1252013-04-09 17:46:25 -07005338
Jeff Brown4dac9012013-04-10 01:03:19 -07005339 /* TODO: These constants should eventually be moved to ViewConfiguration. */
Jeff Brown678a1252013-04-09 17:46:25 -07005340
Jeff Brown4dac9012013-04-10 01:03:19 -07005341 // The nominal distance traveled to move by one unit.
5342 private static final int TICK_DISTANCE_MILLIMETERS = 12;
5343
5344 // Minimum and maximum fling velocity in ticks per second.
5345 // The minimum velocity should be set such that we perform enough ticks per
5346 // second that the fling appears to be fluid. For example, if we set the minimum
5347 // to 2 ticks per second, then there may be up to half a second delay between the next
5348 // to last and last ticks which is noticeably discrete and jerky. This value should
5349 // probably not be set to anything less than about 4.
5350 // If fling accuracy is a problem then consider tuning the tick distance instead.
5351 private static final float MIN_FLING_VELOCITY_TICKS_PER_SECOND = 6f;
5352 private static final float MAX_FLING_VELOCITY_TICKS_PER_SECOND = 20f;
5353
5354 // Fling velocity decay factor applied after each new key is emitted.
5355 // This parameter controls the deceleration and overall duration of the fling.
5356 // The fling stops automatically when its velocity drops below the minimum
5357 // fling velocity defined above.
5358 private static final float FLING_TICK_DECAY = 0.8f;
5359
5360 /* The input device that we are tracking. */
5361
5362 private int mCurrentDeviceId = -1;
5363 private int mCurrentSource;
5364 private boolean mCurrentDeviceSupported;
5365
5366 /* Configuration for the current input device. */
5367
Jeff Brown4dac9012013-04-10 01:03:19 -07005368 // The scaled tick distance. A movement of this amount should generally translate
5369 // into a single dpad event in a given direction.
5370 private float mConfigTickDistance;
5371
5372 // The minimum and maximum scaled fling velocity.
5373 private float mConfigMinFlingVelocity;
5374 private float mConfigMaxFlingVelocity;
5375
5376 /* Tracking state. */
5377
5378 // The velocity tracker for detecting flings.
5379 private VelocityTracker mVelocityTracker;
5380
5381 // The active pointer id, or -1 if none.
5382 private int mActivePointerId = -1;
5383
John Reck79d81e62013-11-05 13:26:57 -08005384 // Location where tracking started.
Jeff Brown4dac9012013-04-10 01:03:19 -07005385 private float mStartX;
5386 private float mStartY;
5387
5388 // Most recently observed position.
5389 private float mLastX;
5390 private float mLastY;
5391
5392 // Accumulated movement delta since the last direction key was sent.
Jeff Brown678a1252013-04-09 17:46:25 -07005393 private float mAccumulatedX;
5394 private float mAccumulatedY;
5395
Jeff Brown4dac9012013-04-10 01:03:19 -07005396 // Set to true if any movement was delivered to the app.
5397 // Implies that tap slop was exceeded.
5398 private boolean mConsumedMovement;
Jeff Brown678a1252013-04-09 17:46:25 -07005399
Jeff Brown4dac9012013-04-10 01:03:19 -07005400 // The most recently sent key down event.
5401 // The keycode remains set until the direction changes or a fling ends
5402 // so that repeated key events may be generated as required.
5403 private long mPendingKeyDownTime;
5404 private int mPendingKeyCode = KeyEvent.KEYCODE_UNKNOWN;
5405 private int mPendingKeyRepeatCount;
5406 private int mPendingKeyMetaState;
Jeff Brown678a1252013-04-09 17:46:25 -07005407
Jeff Brown4dac9012013-04-10 01:03:19 -07005408 // The current fling velocity while a fling is in progress.
5409 private boolean mFlinging;
5410 private float mFlingVelocity;
Jeff Brown678a1252013-04-09 17:46:25 -07005411
5412 public SyntheticTouchNavigationHandler() {
5413 super(true);
Jeff Brown678a1252013-04-09 17:46:25 -07005414 }
5415
5416 public void process(MotionEvent event) {
Jeff Brown4dac9012013-04-10 01:03:19 -07005417 // Update the current device information.
5418 final long time = event.getEventTime();
5419 final int deviceId = event.getDeviceId();
5420 final int source = event.getSource();
5421 if (mCurrentDeviceId != deviceId || mCurrentSource != source) {
5422 finishKeys(time);
5423 finishTracking(time);
5424 mCurrentDeviceId = deviceId;
5425 mCurrentSource = source;
5426 mCurrentDeviceSupported = false;
5427 InputDevice device = event.getDevice();
5428 if (device != null) {
5429 // In order to support an input device, we must know certain
5430 // characteristics about it, such as its size and resolution.
5431 InputDevice.MotionRange xRange = device.getMotionRange(MotionEvent.AXIS_X);
5432 InputDevice.MotionRange yRange = device.getMotionRange(MotionEvent.AXIS_Y);
5433 if (xRange != null && yRange != null) {
5434 mCurrentDeviceSupported = true;
Jeff Brown678a1252013-04-09 17:46:25 -07005435
Jeff Brown4dac9012013-04-10 01:03:19 -07005436 // Infer the resolution if it not actually known.
5437 float xRes = xRange.getResolution();
5438 if (xRes <= 0) {
5439 xRes = xRange.getRange() / DEFAULT_WIDTH_MILLIMETERS;
5440 }
5441 float yRes = yRange.getResolution();
5442 if (yRes <= 0) {
5443 yRes = yRange.getRange() / DEFAULT_HEIGHT_MILLIMETERS;
5444 }
5445 float nominalRes = (xRes + yRes) * 0.5f;
Jeff Brown678a1252013-04-09 17:46:25 -07005446
Jeff Brown4dac9012013-04-10 01:03:19 -07005447 // Precompute all of the configuration thresholds we will need.
Jeff Brown4dac9012013-04-10 01:03:19 -07005448 mConfigTickDistance = TICK_DISTANCE_MILLIMETERS * nominalRes;
5449 mConfigMinFlingVelocity =
5450 MIN_FLING_VELOCITY_TICKS_PER_SECOND * mConfigTickDistance;
5451 mConfigMaxFlingVelocity =
5452 MAX_FLING_VELOCITY_TICKS_PER_SECOND * mConfigTickDistance;
5453
5454 if (LOCAL_DEBUG) {
5455 Log.d(LOCAL_TAG, "Configured device " + mCurrentDeviceId
5456 + " (" + Integer.toHexString(mCurrentSource) + "): "
Jeff Brown4dac9012013-04-10 01:03:19 -07005457 + ", mConfigTickDistance=" + mConfigTickDistance
5458 + ", mConfigMinFlingVelocity=" + mConfigMinFlingVelocity
5459 + ", mConfigMaxFlingVelocity=" + mConfigMaxFlingVelocity);
5460 }
5461 }
5462 }
Jeff Brown678a1252013-04-09 17:46:25 -07005463 }
Jeff Brown4dac9012013-04-10 01:03:19 -07005464 if (!mCurrentDeviceSupported) {
Jeff Brown678a1252013-04-09 17:46:25 -07005465 return;
5466 }
5467
Jeff Brown4dac9012013-04-10 01:03:19 -07005468 // Handle the event.
5469 final int action = event.getActionMasked();
5470 switch (action) {
Jeff Brown678a1252013-04-09 17:46:25 -07005471 case MotionEvent.ACTION_DOWN: {
Jeff Brown4dac9012013-04-10 01:03:19 -07005472 boolean caughtFling = mFlinging;
5473 finishKeys(time);
5474 finishTracking(time);
5475 mActivePointerId = event.getPointerId(0);
5476 mVelocityTracker = VelocityTracker.obtain();
5477 mVelocityTracker.addMovement(event);
Jeff Brown4dac9012013-04-10 01:03:19 -07005478 mStartX = event.getX();
5479 mStartY = event.getY();
5480 mLastX = mStartX;
5481 mLastY = mStartY;
Jeff Brown678a1252013-04-09 17:46:25 -07005482 mAccumulatedX = 0;
5483 mAccumulatedY = 0;
Jeff Brown4dac9012013-04-10 01:03:19 -07005484
5485 // If we caught a fling, then pretend that the tap slop has already
5486 // been exceeded to suppress taps whose only purpose is to stop the fling.
5487 mConsumedMovement = caughtFling;
Jeff Brown678a1252013-04-09 17:46:25 -07005488 break;
5489 }
5490
Jeff Brown4dac9012013-04-10 01:03:19 -07005491 case MotionEvent.ACTION_MOVE:
Jeff Brown678a1252013-04-09 17:46:25 -07005492 case MotionEvent.ACTION_UP: {
Jeff Brown4dac9012013-04-10 01:03:19 -07005493 if (mActivePointerId < 0) {
5494 break;
5495 }
5496 final int index = event.findPointerIndex(mActivePointerId);
5497 if (index < 0) {
5498 finishKeys(time);
5499 finishTracking(time);
5500 break;
5501 }
Jeff Brown678a1252013-04-09 17:46:25 -07005502
Jeff Brown4dac9012013-04-10 01:03:19 -07005503 mVelocityTracker.addMovement(event);
5504 final float x = event.getX(index);
5505 final float y = event.getY(index);
5506 mAccumulatedX += x - mLastX;
5507 mAccumulatedY += y - mLastY;
5508 mLastX = x;
5509 mLastY = y;
5510
5511 // Consume any accumulated movement so far.
5512 final int metaState = event.getMetaState();
5513 consumeAccumulatedMovement(time, metaState);
5514
5515 // Detect taps and flings.
5516 if (action == MotionEvent.ACTION_UP) {
Michael Wright88d7f792013-08-27 15:45:42 -07005517 if (mConsumedMovement && mPendingKeyCode != KeyEvent.KEYCODE_UNKNOWN) {
Jeff Brown4dac9012013-04-10 01:03:19 -07005518 // It might be a fling.
5519 mVelocityTracker.computeCurrentVelocity(1000, mConfigMaxFlingVelocity);
5520 final float vx = mVelocityTracker.getXVelocity(mActivePointerId);
5521 final float vy = mVelocityTracker.getYVelocity(mActivePointerId);
5522 if (!startFling(time, vx, vy)) {
5523 finishKeys(time);
Jeff Brown678a1252013-04-09 17:46:25 -07005524 }
5525 }
Jeff Brown4dac9012013-04-10 01:03:19 -07005526 finishTracking(time);
Jeff Brown678a1252013-04-09 17:46:25 -07005527 }
Jeff Brown4dac9012013-04-10 01:03:19 -07005528 break;
5529 }
5530
5531 case MotionEvent.ACTION_CANCEL: {
5532 finishKeys(time);
5533 finishTracking(time);
Jeff Brown678a1252013-04-09 17:46:25 -07005534 break;
5535 }
5536 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005537 }
Jeff Brown4dac9012013-04-10 01:03:19 -07005538
5539 public void cancel(MotionEvent event) {
5540 if (mCurrentDeviceId == event.getDeviceId()
5541 && mCurrentSource == event.getSource()) {
5542 final long time = event.getEventTime();
5543 finishKeys(time);
5544 finishTracking(time);
5545 }
5546 }
5547
5548 private void finishKeys(long time) {
5549 cancelFling();
5550 sendKeyUp(time);
5551 }
5552
5553 private void finishTracking(long time) {
5554 if (mActivePointerId >= 0) {
5555 mActivePointerId = -1;
5556 mVelocityTracker.recycle();
5557 mVelocityTracker = null;
5558 }
5559 }
5560
5561 private void consumeAccumulatedMovement(long time, int metaState) {
5562 final float absX = Math.abs(mAccumulatedX);
5563 final float absY = Math.abs(mAccumulatedY);
5564 if (absX >= absY) {
5565 if (absX >= mConfigTickDistance) {
5566 mAccumulatedX = consumeAccumulatedMovement(time, metaState, mAccumulatedX,
5567 KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT);
5568 mAccumulatedY = 0;
5569 mConsumedMovement = true;
5570 }
5571 } else {
5572 if (absY >= mConfigTickDistance) {
5573 mAccumulatedY = consumeAccumulatedMovement(time, metaState, mAccumulatedY,
5574 KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN);
5575 mAccumulatedX = 0;
5576 mConsumedMovement = true;
5577 }
5578 }
5579 }
5580
5581 private float consumeAccumulatedMovement(long time, int metaState,
5582 float accumulator, int negativeKeyCode, int positiveKeyCode) {
5583 while (accumulator <= -mConfigTickDistance) {
5584 sendKeyDownOrRepeat(time, negativeKeyCode, metaState);
5585 accumulator += mConfigTickDistance;
5586 }
5587 while (accumulator >= mConfigTickDistance) {
5588 sendKeyDownOrRepeat(time, positiveKeyCode, metaState);
5589 accumulator -= mConfigTickDistance;
5590 }
5591 return accumulator;
5592 }
5593
5594 private void sendKeyDownOrRepeat(long time, int keyCode, int metaState) {
5595 if (mPendingKeyCode != keyCode) {
5596 sendKeyUp(time);
5597 mPendingKeyDownTime = time;
5598 mPendingKeyCode = keyCode;
5599 mPendingKeyRepeatCount = 0;
5600 } else {
5601 mPendingKeyRepeatCount += 1;
5602 }
5603 mPendingKeyMetaState = metaState;
5604
5605 // Note: Normally we would pass FLAG_LONG_PRESS when the repeat count is 1
5606 // but it doesn't quite make sense when simulating the events in this way.
5607 if (LOCAL_DEBUG) {
5608 Log.d(LOCAL_TAG, "Sending key down: keyCode=" + mPendingKeyCode
5609 + ", repeatCount=" + mPendingKeyRepeatCount
5610 + ", metaState=" + Integer.toHexString(mPendingKeyMetaState));
5611 }
5612 enqueueInputEvent(new KeyEvent(mPendingKeyDownTime, time,
5613 KeyEvent.ACTION_DOWN, mPendingKeyCode, mPendingKeyRepeatCount,
5614 mPendingKeyMetaState, mCurrentDeviceId,
5615 KeyEvent.FLAG_FALLBACK, mCurrentSource));
5616 }
5617
5618 private void sendKeyUp(long time) {
5619 if (mPendingKeyCode != KeyEvent.KEYCODE_UNKNOWN) {
5620 if (LOCAL_DEBUG) {
5621 Log.d(LOCAL_TAG, "Sending key up: keyCode=" + mPendingKeyCode
5622 + ", metaState=" + Integer.toHexString(mPendingKeyMetaState));
5623 }
5624 enqueueInputEvent(new KeyEvent(mPendingKeyDownTime, time,
5625 KeyEvent.ACTION_UP, mPendingKeyCode, 0, mPendingKeyMetaState,
5626 mCurrentDeviceId, 0, KeyEvent.FLAG_FALLBACK,
5627 mCurrentSource));
5628 mPendingKeyCode = KeyEvent.KEYCODE_UNKNOWN;
5629 }
5630 }
5631
5632 private boolean startFling(long time, float vx, float vy) {
5633 if (LOCAL_DEBUG) {
5634 Log.d(LOCAL_TAG, "Considering fling: vx=" + vx + ", vy=" + vy
5635 + ", min=" + mConfigMinFlingVelocity);
5636 }
5637
5638 // Flings must be oriented in the same direction as the preceding movements.
5639 switch (mPendingKeyCode) {
5640 case KeyEvent.KEYCODE_DPAD_LEFT:
5641 if (-vx >= mConfigMinFlingVelocity
5642 && Math.abs(vy) < mConfigMinFlingVelocity) {
5643 mFlingVelocity = -vx;
5644 break;
5645 }
5646 return false;
5647
5648 case KeyEvent.KEYCODE_DPAD_RIGHT:
5649 if (vx >= mConfigMinFlingVelocity
5650 && Math.abs(vy) < mConfigMinFlingVelocity) {
5651 mFlingVelocity = vx;
5652 break;
5653 }
5654 return false;
5655
5656 case KeyEvent.KEYCODE_DPAD_UP:
5657 if (-vy >= mConfigMinFlingVelocity
5658 && Math.abs(vx) < mConfigMinFlingVelocity) {
5659 mFlingVelocity = -vy;
5660 break;
5661 }
5662 return false;
5663
5664 case KeyEvent.KEYCODE_DPAD_DOWN:
5665 if (vy >= mConfigMinFlingVelocity
5666 && Math.abs(vx) < mConfigMinFlingVelocity) {
5667 mFlingVelocity = vy;
5668 break;
5669 }
5670 return false;
5671 }
5672
5673 // Post the first fling event.
5674 mFlinging = postFling(time);
5675 return mFlinging;
5676 }
5677
5678 private boolean postFling(long time) {
5679 // The idea here is to estimate the time when the pointer would have
5680 // traveled one tick distance unit given the current fling velocity.
5681 // This effect creates continuity of motion.
5682 if (mFlingVelocity >= mConfigMinFlingVelocity) {
5683 long delay = (long)(mConfigTickDistance / mFlingVelocity * 1000);
5684 postAtTime(mFlingRunnable, time + delay);
5685 if (LOCAL_DEBUG) {
5686 Log.d(LOCAL_TAG, "Posted fling: velocity="
5687 + mFlingVelocity + ", delay=" + delay
5688 + ", keyCode=" + mPendingKeyCode);
5689 }
5690 return true;
5691 }
5692 return false;
5693 }
5694
5695 private void cancelFling() {
5696 if (mFlinging) {
5697 removeCallbacks(mFlingRunnable);
5698 mFlinging = false;
5699 }
5700 }
5701
5702 private final Runnable mFlingRunnable = new Runnable() {
5703 @Override
5704 public void run() {
5705 final long time = SystemClock.uptimeMillis();
5706 sendKeyDownOrRepeat(time, mPendingKeyCode, mPendingKeyMetaState);
5707 mFlingVelocity *= FLING_TICK_DECAY;
5708 if (!postFling(time)) {
5709 mFlinging = false;
5710 finishKeys(time);
5711 }
5712 }
5713 };
Jeff Browncb1404e2011-01-15 18:14:15 -08005714 }
5715
Michael Wright899d7052014-04-23 17:23:39 -07005716 final class SyntheticKeyboardHandler {
5717 public void process(KeyEvent event) {
5718 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) != 0) {
5719 return;
5720 }
5721
5722 final KeyCharacterMap kcm = event.getKeyCharacterMap();
5723 final int keyCode = event.getKeyCode();
5724 final int metaState = event.getMetaState();
5725
5726 // Check for fallback actions specified by the key character map.
5727 KeyCharacterMap.FallbackAction fallbackAction =
5728 kcm.getFallbackAction(keyCode, metaState);
5729 if (fallbackAction != null) {
5730 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
5731 KeyEvent fallbackEvent = KeyEvent.obtain(
5732 event.getDownTime(), event.getEventTime(),
5733 event.getAction(), fallbackAction.keyCode,
5734 event.getRepeatCount(), fallbackAction.metaState,
5735 event.getDeviceId(), event.getScanCode(),
5736 flags, event.getSource(), null);
5737 fallbackAction.recycle();
5738 enqueueInputEvent(fallbackEvent);
5739 }
5740 }
5741 }
5742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005743 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005744 * Returns true if the key is used for keyboard navigation.
5745 * @param keyEvent The key event.
5746 * @return True if the key is used for keyboard navigation.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005747 */
Jeff Brown4e6319b2010-12-13 10:36:51 -08005748 private static boolean isNavigationKey(KeyEvent keyEvent) {
5749 switch (keyEvent.getKeyCode()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005750 case KeyEvent.KEYCODE_DPAD_LEFT:
5751 case KeyEvent.KEYCODE_DPAD_RIGHT:
5752 case KeyEvent.KEYCODE_DPAD_UP:
5753 case KeyEvent.KEYCODE_DPAD_DOWN:
Jeff Brown4e6319b2010-12-13 10:36:51 -08005754 case KeyEvent.KEYCODE_DPAD_CENTER:
5755 case KeyEvent.KEYCODE_PAGE_UP:
5756 case KeyEvent.KEYCODE_PAGE_DOWN:
5757 case KeyEvent.KEYCODE_MOVE_HOME:
5758 case KeyEvent.KEYCODE_MOVE_END:
5759 case KeyEvent.KEYCODE_TAB:
5760 case KeyEvent.KEYCODE_SPACE:
5761 case KeyEvent.KEYCODE_ENTER:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005762 return true;
5763 }
5764 return false;
5765 }
5766
5767 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005768 * Returns true if the key is used for typing.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005769 * @param keyEvent The key event.
Jeff Brown4e6319b2010-12-13 10:36:51 -08005770 * @return True if the key is used for typing.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005771 */
Jeff Brown4e6319b2010-12-13 10:36:51 -08005772 private static boolean isTypingKey(KeyEvent keyEvent) {
5773 return keyEvent.getUnicodeChar() > 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005774 }
5775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005776 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005777 * 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 -08005778 * @param event The key event.
5779 * @return Whether this key event should be consumed (meaning the act of
5780 * leaving touch mode alone is considered the event).
5781 */
5782 private boolean checkForLeavingTouchModeAndConsume(KeyEvent event) {
Jeff Brown4e6319b2010-12-13 10:36:51 -08005783 // Only relevant in touch mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005784 if (!mAttachInfo.mInTouchMode) {
5785 return false;
5786 }
5787
Jeff Brown4e6319b2010-12-13 10:36:51 -08005788 // Only consider leaving touch mode on DOWN or MULTIPLE actions, never on UP.
5789 final int action = event.getAction();
5790 if (action != KeyEvent.ACTION_DOWN && action != KeyEvent.ACTION_MULTIPLE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 return false;
5792 }
5793
Jeff Brown4e6319b2010-12-13 10:36:51 -08005794 // Don't leave touch mode if the IME told us not to.
5795 if ((event.getFlags() & KeyEvent.FLAG_KEEP_TOUCH_MODE) != 0) {
5796 return false;
5797 }
5798
5799 // If the key can be used for keyboard navigation then leave touch mode
5800 // and select a focused view if needed (in ensureTouchMode).
5801 // When a new focused view is selected, we consume the navigation key because
5802 // navigation doesn't make much sense unless a view already has focus so
5803 // the key's purpose is to set focus.
5804 if (isNavigationKey(event)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005805 return ensureTouchMode(false);
5806 }
Jeff Brown4e6319b2010-12-13 10:36:51 -08005807
5808 // If the key can be used for typing then leave touch mode
5809 // and select a focused view if needed (in ensureTouchMode).
5810 // Always allow the view to process the typing key.
5811 if (isTypingKey(event)) {
5812 ensureTouchMode(false);
5813 return false;
5814 }
5815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005816 return false;
5817 }
5818
Christopher Tatea53146c2010-09-07 11:57:52 -07005819 /* drag/drop */
Christopher Tate407b4e92010-11-30 17:14:08 -08005820 void setLocalDragState(Object obj) {
5821 mLocalDragState = obj;
5822 }
5823
Christopher Tatea53146c2010-09-07 11:57:52 -07005824 private void handleDragEvent(DragEvent event) {
5825 // From the root, only drag start/end/location are dispatched. entered/exited
5826 // are determined and dispatched by the viewgroup hierarchy, who then report
5827 // that back here for ultimate reporting back to the framework.
5828 if (mView != null && mAdded) {
5829 final int what = event.mAction;
5830
Vladislav Kaznacheev7fe1f792016-07-14 17:15:02 -07005831 // Cache the drag description when the operation starts, then fill it in
5832 // on subsequent calls as a convenience
5833 if (what == DragEvent.ACTION_DRAG_STARTED) {
5834 mCurrentDragView = null; // Start the current-recipient tracking
5835 mDragDescription = event.mClipDescription;
5836 } else {
Vladislav Kaznacheevcd84cfa2016-07-26 15:17:49 -07005837 if (what == DragEvent.ACTION_DRAG_ENDED) {
5838 mDragDescription = null;
5839 }
Vladislav Kaznacheev7fe1f792016-07-14 17:15:02 -07005840 event.mClipDescription = mDragDescription;
5841 }
5842
Christopher Tatea53146c2010-09-07 11:57:52 -07005843 if (what == DragEvent.ACTION_DRAG_EXITED) {
5844 // A direct EXITED event means that the window manager knows we've just crossed
5845 // a window boundary, so the current drag target within this one must have
Vadim Tryshev1edc6daf2016-09-15 16:19:15 -07005846 // just been exited. Send the EXITED notification to the current drag view, if any.
Vadim Tryshev45bee6b2016-09-19 11:00:37 -07005847 if (View.sCascadedDragDrop) {
Vadim Tryshevef128112016-09-16 14:05:53 -07005848 mView.dispatchDragEnterExitInPreN(event);
5849 }
Vadim Tryshev1edc6daf2016-09-15 16:19:15 -07005850 setDragFocus(null, event);
Christopher Tatea53146c2010-09-07 11:57:52 -07005851 } else {
Christopher Tatea53146c2010-09-07 11:57:52 -07005852 // For events with a [screen] location, translate into window coordinates
5853 if ((what == DragEvent.ACTION_DRAG_LOCATION) || (what == DragEvent.ACTION_DROP)) {
5854 mDragPoint.set(event.mX, event.mY);
5855 if (mTranslator != null) {
5856 mTranslator.translatePointInScreenToAppWindow(mDragPoint);
5857 }
5858
5859 if (mCurScrollY != 0) {
5860 mDragPoint.offset(0, mCurScrollY);
5861 }
5862
5863 event.mX = mDragPoint.x;
5864 event.mY = mDragPoint.y;
5865 }
5866
5867 // Remember who the current drag target is pre-dispatch
5868 final View prevDragView = mCurrentDragView;
5869
Vadim Tryshev69733172016-09-30 17:25:30 -07005870 if (what == DragEvent.ACTION_DROP && event.mClipData != null) {
5871 event.mClipData.prepareToEnterProcess();
Vladislav Kaznacheev854d3f22016-08-11 10:19:36 -07005872 }
5873
Christopher Tatea53146c2010-09-07 11:57:52 -07005874 // Now dispatch the drag/drop event
Chris Tated4533f12010-10-19 15:15:08 -07005875 boolean result = mView.dispatchDragEvent(event);
Christopher Tatea53146c2010-09-07 11:57:52 -07005876
Vadim Tryshev1edc6daf2016-09-15 16:19:15 -07005877 if (what == DragEvent.ACTION_DRAG_LOCATION && !event.mEventHandlerWasCalled) {
5878 // If the LOCATION event wasn't delivered to any handler, no view now has a drag
5879 // focus.
5880 setDragFocus(null, event);
5881 }
5882
Christopher Tatea53146c2010-09-07 11:57:52 -07005883 // If we changed apparent drag target, tell the OS about it
5884 if (prevDragView != mCurrentDragView) {
5885 try {
5886 if (prevDragView != null) {
Jeff Brown98365d72012-08-19 20:30:52 -07005887 mWindowSession.dragRecipientExited(mWindow);
Christopher Tatea53146c2010-09-07 11:57:52 -07005888 }
5889 if (mCurrentDragView != null) {
Jeff Brown98365d72012-08-19 20:30:52 -07005890 mWindowSession.dragRecipientEntered(mWindow);
Christopher Tatea53146c2010-09-07 11:57:52 -07005891 }
5892 } catch (RemoteException e) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005893 Slog.e(mTag, "Unable to note drag target change");
Christopher Tatea53146c2010-09-07 11:57:52 -07005894 }
Christopher Tatea53146c2010-09-07 11:57:52 -07005895 }
Chris Tated4533f12010-10-19 15:15:08 -07005896
Christopher Tate407b4e92010-11-30 17:14:08 -08005897 // Report the drop result when we're done
Chris Tated4533f12010-10-19 15:15:08 -07005898 if (what == DragEvent.ACTION_DROP) {
5899 try {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005900 Log.i(mTag, "Reporting drop result: " + result);
Jeff Brown98365d72012-08-19 20:30:52 -07005901 mWindowSession.reportDropResult(mWindow, result);
Chris Tated4533f12010-10-19 15:15:08 -07005902 } catch (RemoteException e) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08005903 Log.e(mTag, "Unable to report drop result");
Chris Tated4533f12010-10-19 15:15:08 -07005904 }
5905 }
Christopher Tate407b4e92010-11-30 17:14:08 -08005906
Vladislav Kaznacheev82063912015-11-20 14:20:13 -08005907 // When the drag operation ends, reset drag-related state
Christopher Tate407b4e92010-11-30 17:14:08 -08005908 if (what == DragEvent.ACTION_DRAG_ENDED) {
Vadim Tryshev1edc6daf2016-09-15 16:19:15 -07005909 mCurrentDragView = null;
Christopher Tate407b4e92010-11-30 17:14:08 -08005910 setLocalDragState(null);
Vladislav Kaznacheev82063912015-11-20 14:20:13 -08005911 mAttachInfo.mDragToken = null;
Vladislav Kaznacheev4f639742015-11-18 13:21:35 -08005912 if (mAttachInfo.mDragSurface != null) {
5913 mAttachInfo.mDragSurface.release();
5914 mAttachInfo.mDragSurface = null;
5915 }
Christopher Tate407b4e92010-11-30 17:14:08 -08005916 }
Christopher Tatea53146c2010-09-07 11:57:52 -07005917 }
5918 }
5919 event.recycle();
5920 }
5921
Dianne Hackborn9a230e02011-10-06 11:51:27 -07005922 public void handleDispatchSystemUiVisibilityChanged(SystemUiVisibilityInfo args) {
5923 if (mSeq != args.seq) {
5924 // The sequence has changed, so we need to update our value and make
5925 // sure to do a traversal afterward so the window manager is given our
5926 // most recent data.
5927 mSeq = args.seq;
5928 mAttachInfo.mForceReportNewAttributes = true;
Igor Murashkina86ab6402013-08-30 12:58:36 -07005929 scheduleTraversals();
Joe Onorato14782f72011-01-25 19:53:17 -08005930 }
Dianne Hackborn9a230e02011-10-06 11:51:27 -07005931 if (mView == null) return;
5932 if (args.localChanges != 0) {
Dianne Hackborn9a230e02011-10-06 11:51:27 -07005933 mView.updateLocalSystemUiVisibility(args.localValue, args.localChanges);
Dianne Hackborn9a230e02011-10-06 11:51:27 -07005934 }
Chris Craikd36a81f2014-07-17 10:16:51 -07005935
5936 int visibility = args.globalVisibility&View.SYSTEM_UI_CLEARABLE_FLAGS;
5937 if (visibility != mAttachInfo.mGlobalSystemUiVisibility) {
5938 mAttachInfo.mGlobalSystemUiVisibility = visibility;
5939 mView.dispatchSystemUiVisibilityChanged(visibility);
Dianne Hackborncf675782012-05-10 15:07:24 -07005940 }
Joe Onorato664644d2011-01-23 17:53:23 -08005941 }
5942
Phil Weaver964c68e2016-10-27 16:22:05 -07005943 /**
5944 * Notify that the window title changed
5945 */
5946 public void onWindowTitleChanged() {
5947 mAttachInfo.mForceReportNewAttributes = true;
5948 }
5949
Craig Mautner9c795042014-10-28 19:59:59 -07005950 public void handleDispatchWindowShown() {
5951 mAttachInfo.mTreeObserver.dispatchOnWindowShown();
5952 }
5953
Clara Bayarrifcd7e802016-03-10 12:58:18 +00005954 public void handleRequestKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
Clara Bayarri75e09792015-07-29 16:20:40 +01005955 Bundle data = new Bundle();
5956 ArrayList<KeyboardShortcutGroup> list = new ArrayList<>();
5957 if (mView != null) {
Clara Bayarrifcd7e802016-03-10 12:58:18 +00005958 mView.requestKeyboardShortcuts(list, deviceId);
Clara Bayarri75e09792015-07-29 16:20:40 +01005959 }
5960 data.putParcelableArrayList(WindowManager.PARCEL_KEY_SHORTCUTS_ARRAY, list);
5961 try {
5962 receiver.send(0, data);
5963 } catch (RemoteException e) {
5964 }
5965 }
5966
Christopher Tate2c095f32010-10-04 14:13:40 -07005967 public void getLastTouchPoint(Point outLocation) {
5968 outLocation.x = (int) mLastTouchPoint.x;
5969 outLocation.y = (int) mLastTouchPoint.y;
5970 }
5971
Vladislav Kaznacheevba761122016-01-22 12:09:45 -08005972 public int getLastTouchSource() {
5973 return mLastTouchSource;
5974 }
5975
Vadim Tryshev1edc6daf2016-09-15 16:19:15 -07005976 public void setDragFocus(View newDragTarget, DragEvent event) {
Vadim Tryshev45bee6b2016-09-19 11:00:37 -07005977 if (mCurrentDragView != newDragTarget && !View.sCascadedDragDrop) {
Vadim Tryshev1edc6daf2016-09-15 16:19:15 -07005978 // Send EXITED and ENTERED notifications to the old and new drag focus views.
5979
5980 final float tx = event.mX;
5981 final float ty = event.mY;
5982 final int action = event.mAction;
Vadim Trysheva61efa42016-09-28 15:15:52 -07005983 final ClipData td = event.mClipData;
Vadim Tryshev1edc6daf2016-09-15 16:19:15 -07005984 // Position should not be available for ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED.
5985 event.mX = 0;
5986 event.mY = 0;
Vadim Trysheva61efa42016-09-28 15:15:52 -07005987 event.mClipData = null;
Vadim Tryshev1edc6daf2016-09-15 16:19:15 -07005988
5989 if (mCurrentDragView != null) {
5990 event.mAction = DragEvent.ACTION_DRAG_EXITED;
5991 mCurrentDragView.callDragEventHandler(event);
Vadim Tryshev1edc6daf2016-09-15 16:19:15 -07005992 }
5993
Vadim Tryshev1edc6daf2016-09-15 16:19:15 -07005994 if (newDragTarget != null) {
5995 event.mAction = DragEvent.ACTION_DRAG_ENTERED;
5996 newDragTarget.callDragEventHandler(event);
Vadim Tryshev1edc6daf2016-09-15 16:19:15 -07005997 }
5998
5999 event.mAction = action;
6000 event.mX = tx;
6001 event.mY = ty;
Vadim Trysheva61efa42016-09-28 15:15:52 -07006002 event.mClipData = td;
Christopher Tatea53146c2010-09-07 11:57:52 -07006003 }
Vadim Tryshevef128112016-09-16 14:05:53 -07006004
6005 mCurrentDragView = newDragTarget;
Christopher Tatea53146c2010-09-07 11:57:52 -07006006 }
6007
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006008 private AudioManager getAudioManager() {
6009 if (mView == null) {
6010 throw new IllegalStateException("getAudioManager called when there is no mView");
6011 }
6012 if (mAudioManager == null) {
6013 mAudioManager = (AudioManager) mView.getContext().getSystemService(Context.AUDIO_SERVICE);
6014 }
6015 return mAudioManager;
6016 }
6017
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006018 public AccessibilityInteractionController getAccessibilityInteractionController() {
6019 if (mView == null) {
6020 throw new IllegalStateException("getAccessibilityInteractionController"
6021 + " called when there is no mView");
6022 }
Gilles Debunne5ac84422011-10-19 09:35:58 -07006023 if (mAccessibilityInteractionController == null) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006024 mAccessibilityInteractionController = new AccessibilityInteractionController(this);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006025 }
Gilles Debunne5ac84422011-10-19 09:35:58 -07006026 return mAccessibilityInteractionController;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006027 }
6028
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07006029 private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
6030 boolean insetsPending) throws RemoteException {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07006031
6032 float appScale = mAttachInfo.mApplicationScale;
Mitsuru Oshima3d914922009-05-13 22:29:15 -07006033 boolean restore = false;
Mitsuru Oshima64f59342009-06-21 00:03:11 -07006034 if (params != null && mTranslator != null) {
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006035 restore = true;
6036 params.backup();
Mitsuru Oshima64f59342009-06-21 00:03:11 -07006037 mTranslator.translateWindowLayout(params);
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07006038 }
Mitsuru Oshima64f59342009-06-21 00:03:11 -07006039 if (params != null) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08006040 if (DBG) Log.d(mTag, "WindowLayout in layoutWindow:" + params);
Mitsuru Oshima3d914922009-05-13 22:29:15 -07006041 }
Andrii Kulian44607962017-03-16 11:06:24 -07006042 mPendingMergedConfiguration.getMergedConfiguration().seq = 0;
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08006043 //Log.d(mTag, ">>>>>> CALLING relayout");
Dianne Hackborn180c4842011-09-13 12:39:25 -07006044 if (params != null && mOrigWindowType != params.type) {
6045 // For compatibility with old apps, don't crash here.
Michael Wright5bd69e62015-05-14 14:48:08 +01006046 if (mTargetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08006047 Slog.w(mTag, "Window type can not be changed after "
Dianne Hackborn180c4842011-09-13 12:39:25 -07006048 + "the window is added; ignoring change of " + mView);
6049 params.type = mOrigWindowType;
6050 }
6051 }
Jeff Brown98365d72012-08-19 20:30:52 -07006052 int relayoutResult = mWindowSession.relayout(
Dianne Hackborn9a230e02011-10-06 11:51:27 -07006053 mWindow, mSeq, params,
Dianne Hackborn189ee182010-12-02 21:48:53 -08006054 (int) (mView.getMeasuredWidth() * appScale + 0.5f),
6055 (int) (mView.getMeasuredHeight() * appScale + 0.5f),
Jeff Brown98365d72012-08-19 20:30:52 -07006056 viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
Dianne Hackbornc4aad012013-02-22 15:05:25 -08006057 mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
Andrii Kulian44607962017-03-16 11:06:24 -07006058 mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame,
6059 mPendingMergedConfiguration, mSurface);
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -08006060
6061 mPendingAlwaysConsumeNavBar =
6062 (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR) != 0;
6063
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08006064 //Log.d(mTag, "<<<<<< BACK FROM relayout");
Mitsuru Oshima3d914922009-05-13 22:29:15 -07006065 if (restore) {
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006066 params.restore();
Mitsuru Oshima3d914922009-05-13 22:29:15 -07006067 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07006068
Mitsuru Oshima64f59342009-06-21 00:03:11 -07006069 if (mTranslator != null) {
6070 mTranslator.translateRectInScreenToAppWinFrame(mWinFrame);
Dianne Hackbornc4aad012013-02-22 15:05:25 -08006071 mTranslator.translateRectInScreenToAppWindow(mPendingOverscanInsets);
Mitsuru Oshima64f59342009-06-21 00:03:11 -07006072 mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets);
6073 mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets);
Adrian Roosfa104232014-06-20 16:10:14 -07006074 mTranslator.translateRectInScreenToAppWindow(mPendingStableInsets);
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07006075 }
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07006076 return relayoutResult;
6077 }
Romain Guy8506ab42009-06-11 17:35:47 -07006078
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07006079 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006080 * {@inheritDoc}
6081 */
Igor Murashkina86ab6402013-08-30 12:58:36 -07006082 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006083 public void playSoundEffect(int effectId) {
6084 checkThread();
6085
Jean-Michel Trivi13b18fd2010-05-05 09:18:15 -07006086 try {
6087 final AudioManager audioManager = getAudioManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006088
Jean-Michel Trivi13b18fd2010-05-05 09:18:15 -07006089 switch (effectId) {
6090 case SoundEffectConstants.CLICK:
6091 audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
6092 return;
6093 case SoundEffectConstants.NAVIGATION_DOWN:
6094 audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN);
6095 return;
6096 case SoundEffectConstants.NAVIGATION_LEFT:
6097 audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT);
6098 return;
6099 case SoundEffectConstants.NAVIGATION_RIGHT:
6100 audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT);
6101 return;
6102 case SoundEffectConstants.NAVIGATION_UP:
6103 audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP);
6104 return;
6105 default:
6106 throw new IllegalArgumentException("unknown effect id " + effectId +
6107 " not defined in " + SoundEffectConstants.class.getCanonicalName());
6108 }
6109 } catch (IllegalStateException e) {
6110 // Exception thrown by getAudioManager() when mView is null
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08006111 Log.e(mTag, "FATAL EXCEPTION when attempting to play sound effect: " + e);
Jean-Michel Trivi13b18fd2010-05-05 09:18:15 -07006112 e.printStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006113 }
6114 }
6115
6116 /**
6117 * {@inheritDoc}
6118 */
Igor Murashkina86ab6402013-08-30 12:58:36 -07006119 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006120 public boolean performHapticFeedback(int effectId, boolean always) {
6121 try {
Jeff Brown98365d72012-08-19 20:30:52 -07006122 return mWindowSession.performHapticFeedback(mWindow, effectId, always);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006123 } catch (RemoteException e) {
6124 return false;
6125 }
6126 }
6127
6128 /**
6129 * {@inheritDoc}
6130 */
Igor Murashkina86ab6402013-08-30 12:58:36 -07006131 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006132 public View focusSearch(View focused, int direction) {
6133 checkThread();
6134 if (!(mView instanceof ViewGroup)) {
6135 return null;
6136 }
6137 return FocusFinder.getInstance().findNextFocus((ViewGroup) mView, focused, direction);
6138 }
6139
Vadim Tryshev01b0c9e2016-11-21 15:25:01 -08006140 /**
6141 * {@inheritDoc}
6142 */
6143 @Override
Evan Rosky57223312017-02-08 14:42:45 -08006144 public View keyboardNavigationClusterSearch(View currentCluster,
6145 @FocusDirection int direction) {
Vadim Tryshev01b0c9e2016-11-21 15:25:01 -08006146 checkThread();
Vadim Tryshevb5ced222017-01-17 19:31:35 -08006147 return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
6148 mView, currentCluster, direction);
Vadim Tryshev01b0c9e2016-11-21 15:25:01 -08006149 }
6150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006151 public void debug() {
6152 mView.debug();
6153 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07006154
Jeff Brown5182c782013-10-15 20:31:52 -07006155 public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
6156 String innerPrefix = prefix + " ";
6157 writer.print(prefix); writer.println("ViewRoot:");
6158 writer.print(innerPrefix); writer.print("mAdded="); writer.print(mAdded);
6159 writer.print(" mRemoved="); writer.println(mRemoved);
6160 writer.print(innerPrefix); writer.print("mConsumeBatchedInputScheduled=");
6161 writer.println(mConsumeBatchedInputScheduled);
Michael Wright9d744c72014-02-18 21:27:42 -08006162 writer.print(innerPrefix); writer.print("mConsumeBatchedInputImmediatelyScheduled=");
6163 writer.println(mConsumeBatchedInputImmediatelyScheduled);
Jeff Brown5182c782013-10-15 20:31:52 -07006164 writer.print(innerPrefix); writer.print("mPendingInputEventCount=");
6165 writer.println(mPendingInputEventCount);
6166 writer.print(innerPrefix); writer.print("mProcessInputEventsScheduled=");
6167 writer.println(mProcessInputEventsScheduled);
6168 writer.print(innerPrefix); writer.print("mTraversalScheduled=");
6169 writer.print(mTraversalScheduled);
Daniel Koulomzin087ae472015-12-16 17:52:25 -05006170 writer.print(innerPrefix); writer.print("mIsAmbientMode=");
6171 writer.print(mIsAmbientMode);
Jeff Brown5182c782013-10-15 20:31:52 -07006172 if (mTraversalScheduled) {
6173 writer.print(" (barrier="); writer.print(mTraversalBarrier); writer.println(")");
6174 } else {
6175 writer.println();
6176 }
6177 mFirstInputStage.dump(innerPrefix, writer);
6178
6179 mChoreographer.dump(prefix, writer);
6180
6181 writer.print(prefix); writer.println("View Hierarchy:");
6182 dumpViewHierarchy(innerPrefix, writer, mView);
6183 }
6184
6185 private void dumpViewHierarchy(String prefix, PrintWriter writer, View view) {
6186 writer.print(prefix);
6187 if (view == null) {
6188 writer.println("null");
6189 return;
6190 }
6191 writer.println(view.toString());
6192 if (!(view instanceof ViewGroup)) {
6193 return;
6194 }
6195 ViewGroup grp = (ViewGroup)view;
6196 final int N = grp.getChildCount();
6197 if (N <= 0) {
6198 return;
6199 }
6200 prefix = prefix + " ";
6201 for (int i=0; i<N; i++) {
6202 dumpViewHierarchy(prefix, writer, grp.getChildAt(i));
6203 }
6204 }
6205
Romain Guy211370f2012-02-01 16:10:55 -08006206 public void dumpGfxInfo(int[] info) {
Romain Guy54ab3472012-06-14 12:52:53 -07006207 info[0] = info[1] = 0;
Romain Guy65b345f2011-07-27 18:51:50 -07006208 if (mView != null) {
6209 getGfxInfo(mView, info);
Romain Guy65b345f2011-07-27 18:51:50 -07006210 }
6211 }
6212
Romain Guya998dff2012-03-23 18:58:36 -07006213 private static void getGfxInfo(View view, int[] info) {
Chris Craik64a12e12014-03-28 18:12:12 -07006214 RenderNode renderNode = view.mRenderNode;
Romain Guy65b345f2011-07-27 18:51:50 -07006215 info[0]++;
Chris Craik64a12e12014-03-28 18:12:12 -07006216 if (renderNode != null) {
John Reckfe5e7b72014-05-23 17:42:28 -07006217 info[1] += renderNode.getDebugSize();
Romain Guy65b345f2011-07-27 18:51:50 -07006218 }
6219
6220 if (view instanceof ViewGroup) {
6221 ViewGroup group = (ViewGroup) view;
6222
6223 int count = group.getChildCount();
6224 for (int i = 0; i < count; i++) {
6225 getGfxInfo(group.getChildAt(i), info);
6226 }
6227 }
6228 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006229
Craig Mautner8f303ad2013-06-14 11:32:22 -07006230 /**
6231 * @param immediate True, do now if not in traversal. False, put on queue and do later.
6232 * @return True, request has been queued. False, request has been completed.
6233 */
6234 boolean die(boolean immediate) {
Craig Mautnerdf2390a2012-08-29 20:59:22 -07006235 // Make sure we do execute immediately if we are in the middle of a traversal or the damage
6236 // done by dispatchDetachedFromWindow will cause havoc on return.
6237 if (immediate && !mIsInTraversal) {
Dianne Hackborn94d69142009-09-28 22:14:42 -07006238 doDie();
Craig Mautner8f303ad2013-06-14 11:32:22 -07006239 return false;
Dianne Hackborn94d69142009-09-28 22:14:42 -07006240 }
Craig Mautner8f303ad2013-06-14 11:32:22 -07006241
6242 if (!mIsDrawing) {
6243 destroyHardwareRenderer();
6244 } else {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08006245 Log.e(mTag, "Attempting to destroy the window while drawing!\n" +
Craig Mautner8f303ad2013-06-14 11:32:22 -07006246 " window=" + this + ", title=" + mWindowAttributes.getTitle());
6247 }
6248 mHandler.sendEmptyMessage(MSG_DIE);
6249 return true;
Dianne Hackborn94d69142009-09-28 22:14:42 -07006250 }
6251
6252 void doDie() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006253 checkThread();
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08006254 if (LOCAL_LOGV) Log.v(mTag, "DIE in " + this + " of " + mSurface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006255 synchronized (this) {
Craig Mautner8f303ad2013-06-14 11:32:22 -07006256 if (mRemoved) {
6257 return;
6258 }
6259 mRemoved = true;
Romain Guy16260e72011-09-01 14:26:11 -07006260 if (mAdded) {
Romain Guy16260e72011-09-01 14:26:11 -07006261 dispatchDetachedFromWindow();
6262 }
6263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006264 if (mAdded && !mFirst) {
Romain Guy29d89972010-09-22 16:10:57 -07006265 destroyHardwareRenderer();
6266
Romain Guyedbca122012-04-04 18:25:53 -07006267 if (mView != null) {
6268 int viewVisibility = mView.getVisibility();
6269 boolean viewVisibilityChanged = mViewVisibility != viewVisibility;
6270 if (mWindowAttributesChanged || viewVisibilityChanged) {
6271 // If layout params have been changed, first give them
6272 // to the window manager to make sure it has the correct
6273 // animation info.
6274 try {
6275 if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
Jeff Brown98365d72012-08-19 20:30:52 -07006276 & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
6277 mWindowSession.finishDrawing(mWindow);
Romain Guyedbca122012-04-04 18:25:53 -07006278 }
6279 } catch (RemoteException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006280 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006281 }
Craig Mautner8f303ad2013-06-14 11:32:22 -07006282
Romain Guyedbca122012-04-04 18:25:53 -07006283 mSurface.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006285 }
Romain Guyedbca122012-04-04 18:25:53 -07006286
6287 mAdded = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006288 }
Craig Mautner05eb7302013-06-03 17:24:21 -07006289 WindowManagerGlobal.getInstance().doRemoveView(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006290 }
6291
Dianne Hackborn5fd21692011-06-07 14:09:47 -07006292 public void requestUpdateConfiguration(Configuration config) {
Jeff Browna175a5b2012-02-15 19:18:31 -08006293 Message msg = mHandler.obtainMessage(MSG_UPDATE_CONFIGURATION, config);
6294 mHandler.sendMessage(msg);
Dianne Hackborn5fd21692011-06-07 14:09:47 -07006295 }
6296
Dianne Hackborna53de062012-05-08 18:53:51 -07006297 public void loadSystemProperties() {
Romain Guy5bb3c732012-11-29 17:52:58 -08006298 mHandler.post(new Runnable() {
6299 @Override
6300 public void run() {
6301 // Profiling
6302 mProfileRendering = SystemProperties.getBoolean(PROPERTY_PROFILE_RENDERING, false);
6303 profileRendering(mAttachInfo.mHasWindowFocus);
6304
6305 // Hardware rendering
Stan Iliev45faba52016-06-28 13:33:15 -04006306 if (mAttachInfo.mThreadedRenderer != null) {
6307 if (mAttachInfo.mThreadedRenderer.loadSystemProperties()) {
Romain Guy5bb3c732012-11-29 17:52:58 -08006308 invalidate();
6309 }
6310 }
6311
6312 // Layout debugging
6313 boolean layout = SystemProperties.getBoolean(View.DEBUG_LAYOUT_PROPERTY, false);
6314 if (layout != mAttachInfo.mDebugLayout) {
6315 mAttachInfo.mDebugLayout = layout;
6316 if (!mHandler.hasMessages(MSG_INVALIDATE_WORLD)) {
6317 mHandler.sendEmptyMessageDelayed(MSG_INVALIDATE_WORLD, 200);
6318 }
6319 }
Dianne Hackborna53de062012-05-08 18:53:51 -07006320 }
Romain Guy5bb3c732012-11-29 17:52:58 -08006321 });
Dianne Hackborna53de062012-05-08 18:53:51 -07006322 }
6323
Romain Guy29d89972010-09-22 16:10:57 -07006324 private void destroyHardwareRenderer() {
Stan Iliev45faba52016-06-28 13:33:15 -04006325 ThreadedRenderer hardwareRenderer = mAttachInfo.mThreadedRenderer;
Romain Guya998dff2012-03-23 18:58:36 -07006326
6327 if (hardwareRenderer != null) {
6328 if (mView != null) {
6329 hardwareRenderer.destroyHardwareResources(mView);
6330 }
John Reckf47a5942014-06-30 16:20:04 -07006331 hardwareRenderer.destroy();
Romain Guya998dff2012-03-23 18:58:36 -07006332 hardwareRenderer.setRequested(false);
6333
Stan Iliev45faba52016-06-28 13:33:15 -04006334 mAttachInfo.mThreadedRenderer = null;
Chris Craikd36a81f2014-07-17 10:16:51 -07006335 mAttachInfo.mHardwareAccelerated = false;
Romain Guy29d89972010-09-22 16:10:57 -07006336 }
6337 }
6338
Andrii Kulian44607962017-03-16 11:06:24 -07006339 private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
Filip Gruszczynski2217f612015-05-26 11:32:08 -07006340 Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
Andrii Kulian44607962017-03-16 11:06:24 -07006341 MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006342 boolean alwaysConsumeNavBar, int displayId) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08006343 if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString()
Svetoslav Ganov758143e2012-08-06 16:40:27 -07006344 + " contentInsets=" + contentInsets.toShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006345 + " visibleInsets=" + visibleInsets.toShortString()
Chong Zhangd153c4f2015-11-06 20:26:40 -08006346 + " reportDraw=" + reportDraw
6347 + " backDropFrame=" + backDropFrame);
Chong Zhangdcee1de2015-10-06 10:26:00 -07006348
6349 // Tell all listeners that we are resizing the window so that the chrome can get
6350 // updated as fast as possible on a separate thread,
6351 if (mDragResizing) {
Jorim Jaggi9511b0f2016-01-29 19:12:44 -08006352 boolean fullscreen = frame.equals(backDropFrame);
Chong Zhangdcee1de2015-10-06 10:26:00 -07006353 synchronized (mWindowCallbacks) {
6354 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
Jorim Jaggi9511b0f2016-01-29 19:12:44 -08006355 mWindowCallbacks.get(i).onWindowSizeIsChanging(backDropFrame, fullscreen,
6356 visibleInsets, stableInsets);
Chong Zhangdcee1de2015-10-06 10:26:00 -07006357 }
6358 }
6359 }
6360
Svetoslav Ganov758143e2012-08-06 16:40:27 -07006361 Message msg = mHandler.obtainMessage(reportDraw ? MSG_RESIZED_REPORT : MSG_RESIZED);
Mitsuru Oshima64f59342009-06-21 00:03:11 -07006362 if (mTranslator != null) {
Svetoslav Ganov758143e2012-08-06 16:40:27 -07006363 mTranslator.translateRectInScreenToAppWindow(frame);
Dianne Hackbornc4aad012013-02-22 15:05:25 -08006364 mTranslator.translateRectInScreenToAppWindow(overscanInsets);
Dianne Hackborn3556c9a2012-05-04 16:31:25 -07006365 mTranslator.translateRectInScreenToAppWindow(contentInsets);
Mitsuru Oshima64f59342009-06-21 00:03:11 -07006366 mTranslator.translateRectInScreenToAppWindow(visibleInsets);
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07006367 }
Svetoslav Ganov758143e2012-08-06 16:40:27 -07006368 SomeArgs args = SomeArgs.obtain();
6369 final boolean sameProcessCall = (Binder.getCallingPid() == android.os.Process.myPid());
6370 args.arg1 = sameProcessCall ? new Rect(frame) : frame;
6371 args.arg2 = sameProcessCall ? new Rect(contentInsets) : contentInsets;
6372 args.arg3 = sameProcessCall ? new Rect(visibleInsets) : visibleInsets;
Andrii Kulian44607962017-03-16 11:06:24 -07006373 args.arg4 = sameProcessCall && mergedConfiguration != null
6374 ? new MergedConfiguration(mergedConfiguration) : null;
Dianne Hackbornc4aad012013-02-22 15:05:25 -08006375 args.arg5 = sameProcessCall ? new Rect(overscanInsets) : overscanInsets;
Adrian Roosfa104232014-06-20 16:10:14 -07006376 args.arg6 = sameProcessCall ? new Rect(stableInsets) : stableInsets;
Filip Gruszczynski2217f612015-05-26 11:32:08 -07006377 args.arg7 = sameProcessCall ? new Rect(outsets) : outsets;
Jorim Jaggia7262a82015-11-03 15:15:40 +01006378 args.arg8 = sameProcessCall ? new Rect(backDropFrame) : backDropFrame;
Jorim Jaggia4a58ef2016-01-27 02:10:08 -08006379 args.argi1 = forceLayout ? 1 : 0;
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -08006380 args.argi2 = alwaysConsumeNavBar ? 1 : 0;
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006381 args.argi3 = displayId;
Svetoslav Ganov758143e2012-08-06 16:40:27 -07006382 msg.obj = args;
Jeff Browna175a5b2012-02-15 19:18:31 -08006383 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006384 }
Chet Haase1f4786b2011-11-02 10:51:52 -07006385
Craig Mautner5702d4d2012-06-30 14:10:16 -07006386 public void dispatchMoved(int newX, int newY) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08006387 if (DEBUG_LAYOUT) Log.v(mTag, "Window moved " + this + ": newX=" + newX + " newY=" + newY);
Craig Mautner5702d4d2012-06-30 14:10:16 -07006388 if (mTranslator != null) {
6389 PointF point = new PointF(newX, newY);
6390 mTranslator.translatePointInScreenToAppWindow(point);
6391 newX = (int) (point.x + 0.5);
6392 newY = (int) (point.y + 0.5);
6393 }
6394 Message msg = mHandler.obtainMessage(MSG_WINDOW_MOVED, newX, newY);
6395 mHandler.sendMessage(msg);
6396 }
6397
Jeff Brown4952dfd2011-11-30 19:23:22 -08006398 /**
6399 * Represents a pending input event that is waiting in a queue.
6400 *
6401 * Input events are processed in serial order by the timestamp specified by
Romain Guy211370f2012-02-01 16:10:55 -08006402 * {@link InputEvent#getEventTimeNano()}. In general, the input dispatcher delivers
Jeff Brown4952dfd2011-11-30 19:23:22 -08006403 * one input event to the application at a time and waits for the application
6404 * to finish handling it before delivering the next one.
6405 *
6406 * However, because the application or IME can synthesize and inject multiple
6407 * key events at a time without going through the input dispatcher, we end up
6408 * needing a queue on the application's side.
6409 */
6410 private static final class QueuedInputEvent {
Jeff Brownf9e989d2013-04-04 23:04:03 -07006411 public static final int FLAG_DELIVER_POST_IME = 1 << 0;
6412 public static final int FLAG_DEFERRED = 1 << 1;
6413 public static final int FLAG_FINISHED = 1 << 2;
6414 public static final int FLAG_FINISHED_HANDLED = 1 << 3;
6415 public static final int FLAG_RESYNTHESIZED = 1 << 4;
Michael Wright899d7052014-04-23 17:23:39 -07006416 public static final int FLAG_UNHANDLED = 1 << 5;
Jeff Brown4952dfd2011-11-30 19:23:22 -08006417
6418 public QueuedInputEvent mNext;
6419
6420 public InputEvent mEvent;
Jeff Brown32cbc38552011-12-01 14:01:49 -08006421 public InputEventReceiver mReceiver;
Jeff Brown4952dfd2011-11-30 19:23:22 -08006422 public int mFlags;
Jeff Brownf9e989d2013-04-04 23:04:03 -07006423
6424 public boolean shouldSkipIme() {
6425 if ((mFlags & FLAG_DELIVER_POST_IME) != 0) {
6426 return true;
6427 }
6428 return mEvent instanceof MotionEvent
Prashant Malanifecbc672016-07-22 15:38:05 -07006429 && (mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)
6430 || mEvent.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER));
Jeff Brownf9e989d2013-04-04 23:04:03 -07006431 }
Michael Wright899d7052014-04-23 17:23:39 -07006432
6433 public boolean shouldSendToSynthesizer() {
6434 if ((mFlags & FLAG_UNHANDLED) != 0) {
6435 return true;
6436 }
6437
6438 return false;
6439 }
Michael Wright06a79252014-05-05 17:45:29 -07006440
6441 @Override
6442 public String toString() {
6443 StringBuilder sb = new StringBuilder("QueuedInputEvent{flags=");
6444 boolean hasPrevious = false;
6445 hasPrevious = flagToString("DELIVER_POST_IME", FLAG_DELIVER_POST_IME, hasPrevious, sb);
6446 hasPrevious = flagToString("DEFERRED", FLAG_DEFERRED, hasPrevious, sb);
6447 hasPrevious = flagToString("FINISHED", FLAG_FINISHED, hasPrevious, sb);
6448 hasPrevious = flagToString("FINISHED_HANDLED", FLAG_FINISHED_HANDLED, hasPrevious, sb);
6449 hasPrevious = flagToString("RESYNTHESIZED", FLAG_RESYNTHESIZED, hasPrevious, sb);
6450 hasPrevious = flagToString("UNHANDLED", FLAG_UNHANDLED, hasPrevious, sb);
6451 if (!hasPrevious) {
6452 sb.append("0");
6453 }
6454 sb.append(", hasNextQueuedEvent=" + (mEvent != null ? "true" : "false"));
6455 sb.append(", hasInputEventReceiver=" + (mReceiver != null ? "true" : "false"));
6456 sb.append(", mEvent=" + mEvent + "}");
6457 return sb.toString();
6458 }
6459
6460 private boolean flagToString(String name, int flag,
6461 boolean hasPrevious, StringBuilder sb) {
6462 if ((mFlags & flag) != 0) {
6463 if (hasPrevious) {
6464 sb.append("|");
6465 }
6466 sb.append(name);
6467 return true;
6468 }
6469 return hasPrevious;
6470 }
Jeff Brown4952dfd2011-11-30 19:23:22 -08006471 }
6472
6473 private QueuedInputEvent obtainQueuedInputEvent(InputEvent event,
Jeff Brown32cbc38552011-12-01 14:01:49 -08006474 InputEventReceiver receiver, int flags) {
Jeff Brown4952dfd2011-11-30 19:23:22 -08006475 QueuedInputEvent q = mQueuedInputEventPool;
6476 if (q != null) {
6477 mQueuedInputEventPoolSize -= 1;
6478 mQueuedInputEventPool = q.mNext;
6479 q.mNext = null;
6480 } else {
6481 q = new QueuedInputEvent();
Jeff Brown46b9ac02010-04-22 18:58:52 -07006482 }
6483
Jeff Brown4952dfd2011-11-30 19:23:22 -08006484 q.mEvent = event;
Jeff Brown32cbc38552011-12-01 14:01:49 -08006485 q.mReceiver = receiver;
Jeff Brown4952dfd2011-11-30 19:23:22 -08006486 q.mFlags = flags;
Jeff Brown4952dfd2011-11-30 19:23:22 -08006487 return q;
6488 }
6489
6490 private void recycleQueuedInputEvent(QueuedInputEvent q) {
6491 q.mEvent = null;
Jeff Brown32cbc38552011-12-01 14:01:49 -08006492 q.mReceiver = null;
Jeff Brown4952dfd2011-11-30 19:23:22 -08006493
6494 if (mQueuedInputEventPoolSize < MAX_QUEUED_INPUT_EVENT_POOL_SIZE) {
6495 mQueuedInputEventPoolSize += 1;
6496 q.mNext = mQueuedInputEventPool;
6497 mQueuedInputEventPool = q;
6498 }
6499 }
6500
Jeff Brownf9261d22012-02-03 13:49:15 -08006501 void enqueueInputEvent(InputEvent event) {
6502 enqueueInputEvent(event, null, 0, false);
6503 }
6504
Jeff Brown4952dfd2011-11-30 19:23:22 -08006505 void enqueueInputEvent(InputEvent event,
Jeff Brownf9261d22012-02-03 13:49:15 -08006506 InputEventReceiver receiver, int flags, boolean processImmediately) {
Michael Wright5bd69e62015-05-14 14:48:08 +01006507 adjustInputEventForCompatibility(event);
Jeff Brown32cbc38552011-12-01 14:01:49 -08006508 QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
Jeff Brown4952dfd2011-11-30 19:23:22 -08006509
Jeff Brown4952dfd2011-11-30 19:23:22 -08006510 // Always enqueue the input event in order, regardless of its time stamp.
6511 // We do this because the application or the IME may inject key events
6512 // in response to touch events and we want to ensure that the injected keys
6513 // are processed in the order they were received and we cannot trust that
6514 // the time stamp of injected events are monotonic.
Michael Wrightc8a7e542013-03-20 17:58:33 -07006515 QueuedInputEvent last = mPendingInputEventTail;
Jeff Brown4952dfd2011-11-30 19:23:22 -08006516 if (last == null) {
Michael Wrightc8a7e542013-03-20 17:58:33 -07006517 mPendingInputEventHead = q;
6518 mPendingInputEventTail = q;
Jeff Brown4952dfd2011-11-30 19:23:22 -08006519 } else {
Jeff Brown4952dfd2011-11-30 19:23:22 -08006520 last.mNext = q;
Michael Wrightc8a7e542013-03-20 17:58:33 -07006521 mPendingInputEventTail = q;
Jeff Brown4952dfd2011-11-30 19:23:22 -08006522 }
Michael Wright95ae9422013-03-14 10:58:50 -07006523 mPendingInputEventCount += 1;
6524 Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
6525 mPendingInputEventCount);
Jeff Brown4952dfd2011-11-30 19:23:22 -08006526
Jeff Brownf9261d22012-02-03 13:49:15 -08006527 if (processImmediately) {
6528 doProcessInputEvents();
6529 } else {
6530 scheduleProcessInputEvents();
6531 }
Jeff Brown4952dfd2011-11-30 19:23:22 -08006532 }
6533
6534 private void scheduleProcessInputEvents() {
Jeff Brown96e942d2011-11-30 19:55:01 -08006535 if (!mProcessInputEventsScheduled) {
6536 mProcessInputEventsScheduled = true;
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006537 Message msg = mHandler.obtainMessage(MSG_PROCESS_INPUT_EVENTS);
6538 msg.setAsynchronous(true);
6539 mHandler.sendMessage(msg);
Jeff Brown4952dfd2011-11-30 19:23:22 -08006540 }
6541 }
6542
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006543 void doProcessInputEvents() {
Jeff Brownf9e989d2013-04-04 23:04:03 -07006544 // Deliver all pending input events in the queue.
Michael Wrightc8a7e542013-03-20 17:58:33 -07006545 while (mPendingInputEventHead != null) {
6546 QueuedInputEvent q = mPendingInputEventHead;
6547 mPendingInputEventHead = q.mNext;
6548 if (mPendingInputEventHead == null) {
6549 mPendingInputEventTail = null;
6550 }
Jeff Brown4952dfd2011-11-30 19:23:22 -08006551 q.mNext = null;
Jeff Brown29c0ed22013-01-14 13:50:37 -08006552
Michael Wright95ae9422013-03-14 10:58:50 -07006553 mPendingInputEventCount -= 1;
6554 Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
6555 mPendingInputEventCount);
6556
John Reckba6adf62015-02-19 14:36:50 -08006557 long eventTime = q.mEvent.getEventTimeNano();
6558 long oldestEventTime = eventTime;
6559 if (q.mEvent instanceof MotionEvent) {
6560 MotionEvent me = (MotionEvent)q.mEvent;
6561 if (me.getHistorySize() > 0) {
6562 oldestEventTime = me.getHistoricalEventTimeNano(0);
6563 }
6564 }
6565 mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
6566
Jeff Brownf9e989d2013-04-04 23:04:03 -07006567 deliverInputEvent(q);
Jeff Brown4952dfd2011-11-30 19:23:22 -08006568 }
6569
6570 // We are done processing all input events that we can process right now
6571 // so we can clear the pending flag immediately.
Jeff Brown96e942d2011-11-30 19:55:01 -08006572 if (mProcessInputEventsScheduled) {
6573 mProcessInputEventsScheduled = false;
Jeff Browna175a5b2012-02-15 19:18:31 -08006574 mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
Jeff Brown4952dfd2011-11-30 19:23:22 -08006575 }
6576 }
6577
Jeff Brownf9e989d2013-04-04 23:04:03 -07006578 private void deliverInputEvent(QueuedInputEvent q) {
Michael Wrightd2c3adc2014-02-18 22:50:50 -08006579 Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
6580 q.mEvent.getSequenceNumber());
6581 if (mInputEventConsistencyVerifier != null) {
6582 mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
6583 }
Michael Wrightc8a7e542013-03-20 17:58:33 -07006584
Michael Wright899d7052014-04-23 17:23:39 -07006585 InputStage stage;
6586 if (q.shouldSendToSynthesizer()) {
6587 stage = mSyntheticInputStage;
6588 } else {
6589 stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
6590 }
6591
Michael Wrightd2c3adc2014-02-18 22:50:50 -08006592 if (stage != null) {
6593 stage.deliver(q);
6594 } else {
6595 finishInputEvent(q);
Michael Wrightbf020962013-03-28 17:27:50 -07006596 }
Michael Wrightbf020962013-03-28 17:27:50 -07006597 }
6598
Jeff Brownf9e989d2013-04-04 23:04:03 -07006599 private void finishInputEvent(QueuedInputEvent q) {
Michael Wrightd2c3adc2014-02-18 22:50:50 -08006600 Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
6601 q.mEvent.getSequenceNumber());
Michael Wright9d744c72014-02-18 21:27:42 -08006602
Jeff Brown32cbc38552011-12-01 14:01:49 -08006603 if (q.mReceiver != null) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07006604 boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0;
Jeff Brown32cbc38552011-12-01 14:01:49 -08006605 q.mReceiver.finishInputEvent(q.mEvent, handled);
Jeff Brown92cc2d82011-12-02 01:19:47 -08006606 } else {
6607 q.mEvent.recycleIfNeededAfterDispatch();
Jeff Brown4952dfd2011-11-30 19:23:22 -08006608 }
6609
6610 recycleQueuedInputEvent(q);
Jeff Brown29c0ed22013-01-14 13:50:37 -08006611 }
Jeff Brown4952dfd2011-11-30 19:23:22 -08006612
Michael Wright5bd69e62015-05-14 14:48:08 +01006613 private void adjustInputEventForCompatibility(InputEvent e) {
Dianne Hackborn0e3de6c2015-07-29 15:20:21 -07006614 if (mTargetSdkVersion < Build.VERSION_CODES.M && e instanceof MotionEvent) {
Michael Wright5bd69e62015-05-14 14:48:08 +01006615 MotionEvent motion = (MotionEvent) e;
6616 final int mask =
6617 MotionEvent.BUTTON_STYLUS_PRIMARY | MotionEvent.BUTTON_STYLUS_SECONDARY;
6618 final int buttonState = motion.getButtonState();
6619 final int compatButtonState = (buttonState & mask) >> 4;
6620 if (compatButtonState != 0) {
6621 motion.setButtonState(buttonState | compatButtonState);
6622 }
6623 }
6624 }
6625
Jeff Brownf9e989d2013-04-04 23:04:03 -07006626 static boolean isTerminalInputEvent(InputEvent event) {
Jeff Brown29c0ed22013-01-14 13:50:37 -08006627 if (event instanceof KeyEvent) {
6628 final KeyEvent keyEvent = (KeyEvent)event;
6629 return keyEvent.getAction() == KeyEvent.ACTION_UP;
6630 } else {
6631 final MotionEvent motionEvent = (MotionEvent)event;
6632 final int action = motionEvent.getAction();
6633 return action == MotionEvent.ACTION_UP
6634 || action == MotionEvent.ACTION_CANCEL
6635 || action == MotionEvent.ACTION_HOVER_EXIT;
Jeff Brown4952dfd2011-11-30 19:23:22 -08006636 }
6637 }
6638
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006639 void scheduleConsumeBatchedInput() {
6640 if (!mConsumeBatchedInputScheduled) {
6641 mConsumeBatchedInputScheduled = true;
6642 mChoreographer.postCallback(Choreographer.CALLBACK_INPUT,
6643 mConsumedBatchedInputRunnable, null);
Jeff Brown4a06c802012-02-15 15:06:01 -08006644 }
6645 }
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006646
6647 void unscheduleConsumeBatchedInput() {
6648 if (mConsumeBatchedInputScheduled) {
6649 mConsumeBatchedInputScheduled = false;
6650 mChoreographer.removeCallbacks(Choreographer.CALLBACK_INPUT,
6651 mConsumedBatchedInputRunnable, null);
6652 }
6653 }
6654
Michael Wright9d744c72014-02-18 21:27:42 -08006655 void scheduleConsumeBatchedInputImmediately() {
6656 if (!mConsumeBatchedInputImmediatelyScheduled) {
6657 unscheduleConsumeBatchedInput();
6658 mConsumeBatchedInputImmediatelyScheduled = true;
6659 mHandler.post(mConsumeBatchedInputImmediatelyRunnable);
6660 }
6661 }
6662
Jeff Brown771526c2012-04-27 15:13:25 -07006663 void doConsumeBatchedInput(long frameTimeNanos) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006664 if (mConsumeBatchedInputScheduled) {
6665 mConsumeBatchedInputScheduled = false;
Jeff Brown330314c2012-04-27 02:20:22 -07006666 if (mInputEventReceiver != null) {
Michael Wright9d744c72014-02-18 21:27:42 -08006667 if (mInputEventReceiver.consumeBatchedInputEvents(frameTimeNanos)
6668 && frameTimeNanos != -1) {
Michael Wright62ce65d2013-10-25 14:50:36 -07006669 // If we consumed a batch here, we want to go ahead and schedule the
6670 // consumption of batched input events on the next frame. Otherwise, we would
6671 // wait until we have more input events pending and might get starved by other
Michael Wright9d744c72014-02-18 21:27:42 -08006672 // things occurring in the process. If the frame time is -1, however, then
6673 // we're in a non-batching mode, so there's no need to schedule this.
Michael Wright62ce65d2013-10-25 14:50:36 -07006674 scheduleConsumeBatchedInput();
6675 }
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006676 }
Jeff Brown330314c2012-04-27 02:20:22 -07006677 doProcessInputEvents();
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006678 }
6679 }
6680
6681 final class TraversalRunnable implements Runnable {
6682 @Override
6683 public void run() {
6684 doTraversal();
6685 }
6686 }
6687 final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
Jeff Brown4a06c802012-02-15 15:06:01 -08006688
Jeff Brown32cbc38552011-12-01 14:01:49 -08006689 final class WindowInputEventReceiver extends InputEventReceiver {
6690 public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
6691 super(inputChannel, looper);
Jeff Brown46b9ac02010-04-22 18:58:52 -07006692 }
Jeff Brown32cbc38552011-12-01 14:01:49 -08006693
6694 @Override
6695 public void onInputEvent(InputEvent event) {
Jeff Brownf9261d22012-02-03 13:49:15 -08006696 enqueueInputEvent(event, this, 0, true);
Jeff Brown32cbc38552011-12-01 14:01:49 -08006697 }
Jeff Brown072ec962012-02-07 14:46:57 -08006698
6699 @Override
6700 public void onBatchedInputEventPending() {
Michael Wright9d744c72014-02-18 21:27:42 -08006701 if (mUnbufferedInputDispatch) {
6702 super.onBatchedInputEventPending();
6703 } else {
6704 scheduleConsumeBatchedInput();
6705 }
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006706 }
6707
6708 @Override
6709 public void dispose() {
6710 unscheduleConsumeBatchedInput();
6711 super.dispose();
Jeff Brown072ec962012-02-07 14:46:57 -08006712 }
Jeff Brown32cbc38552011-12-01 14:01:49 -08006713 }
6714 WindowInputEventReceiver mInputEventReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006715
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006716 final class ConsumeBatchedInputRunnable implements Runnable {
6717 @Override
6718 public void run() {
Jeff Brown771526c2012-04-27 15:13:25 -07006719 doConsumeBatchedInput(mChoreographer.getFrameTimeNanos());
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006720 }
6721 }
6722 final ConsumeBatchedInputRunnable mConsumedBatchedInputRunnable =
6723 new ConsumeBatchedInputRunnable();
6724 boolean mConsumeBatchedInputScheduled;
6725
Michael Wright9d744c72014-02-18 21:27:42 -08006726 final class ConsumeBatchedInputImmediatelyRunnable implements Runnable {
6727 @Override
6728 public void run() {
6729 doConsumeBatchedInput(-1);
6730 }
6731 }
6732 final ConsumeBatchedInputImmediatelyRunnable mConsumeBatchedInputImmediatelyRunnable =
6733 new ConsumeBatchedInputImmediatelyRunnable();
6734 boolean mConsumeBatchedInputImmediatelyScheduled;
6735
Jeff Brown6cb7b462012-03-05 13:21:17 -08006736 final class InvalidateOnAnimationRunnable implements Runnable {
6737 private boolean mPosted;
Igor Murashkina86ab6402013-08-30 12:58:36 -07006738 private final ArrayList<View> mViews = new ArrayList<View>();
6739 private final ArrayList<AttachInfo.InvalidateInfo> mViewRects =
Jeff Brown6cb7b462012-03-05 13:21:17 -08006740 new ArrayList<AttachInfo.InvalidateInfo>();
6741 private View[] mTempViews;
6742 private AttachInfo.InvalidateInfo[] mTempViewRects;
6743
6744 public void addView(View view) {
6745 synchronized (this) {
6746 mViews.add(view);
6747 postIfNeededLocked();
6748 }
6749 }
6750
6751 public void addViewRect(AttachInfo.InvalidateInfo info) {
6752 synchronized (this) {
6753 mViewRects.add(info);
6754 postIfNeededLocked();
6755 }
6756 }
6757
6758 public void removeView(View view) {
6759 synchronized (this) {
6760 mViews.remove(view);
6761
6762 for (int i = mViewRects.size(); i-- > 0; ) {
6763 AttachInfo.InvalidateInfo info = mViewRects.get(i);
6764 if (info.target == view) {
6765 mViewRects.remove(i);
Svetoslav Ganovabae2a12012-11-27 16:59:37 -08006766 info.recycle();
Jeff Brown6cb7b462012-03-05 13:21:17 -08006767 }
6768 }
6769
6770 if (mPosted && mViews.isEmpty() && mViewRects.isEmpty()) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006771 mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, this, null);
Jeff Brown6cb7b462012-03-05 13:21:17 -08006772 mPosted = false;
6773 }
6774 }
6775 }
6776
6777 @Override
6778 public void run() {
6779 final int viewCount;
6780 final int viewRectCount;
6781 synchronized (this) {
6782 mPosted = false;
6783
6784 viewCount = mViews.size();
6785 if (viewCount != 0) {
6786 mTempViews = mViews.toArray(mTempViews != null
6787 ? mTempViews : new View[viewCount]);
6788 mViews.clear();
6789 }
6790
6791 viewRectCount = mViewRects.size();
6792 if (viewRectCount != 0) {
6793 mTempViewRects = mViewRects.toArray(mTempViewRects != null
6794 ? mTempViewRects : new AttachInfo.InvalidateInfo[viewRectCount]);
6795 mViewRects.clear();
6796 }
6797 }
6798
6799 for (int i = 0; i < viewCount; i++) {
6800 mTempViews[i].invalidate();
Adam Powell3e3c4ee2012-05-16 17:34:21 -07006801 mTempViews[i] = null;
Jeff Brown6cb7b462012-03-05 13:21:17 -08006802 }
6803
6804 for (int i = 0; i < viewRectCount; i++) {
6805 final View.AttachInfo.InvalidateInfo info = mTempViewRects[i];
6806 info.target.invalidate(info.left, info.top, info.right, info.bottom);
Svetoslav Ganovabae2a12012-11-27 16:59:37 -08006807 info.recycle();
Jeff Brown6cb7b462012-03-05 13:21:17 -08006808 }
6809 }
6810
6811 private void postIfNeededLocked() {
6812 if (!mPosted) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -07006813 mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null);
Jeff Brown6cb7b462012-03-05 13:21:17 -08006814 mPosted = true;
6815 }
6816 }
6817 }
6818 final InvalidateOnAnimationRunnable mInvalidateOnAnimationRunnable =
6819 new InvalidateOnAnimationRunnable();
6820
Jeff Browna175a5b2012-02-15 19:18:31 -08006821 public void dispatchInvalidateDelayed(View view, long delayMilliseconds) {
6822 Message msg = mHandler.obtainMessage(MSG_INVALIDATE, view);
6823 mHandler.sendMessageDelayed(msg, delayMilliseconds);
6824 }
6825
Jeff Browna175a5b2012-02-15 19:18:31 -08006826 public void dispatchInvalidateRectDelayed(AttachInfo.InvalidateInfo info,
6827 long delayMilliseconds) {
6828 final Message msg = mHandler.obtainMessage(MSG_INVALIDATE_RECT, info);
6829 mHandler.sendMessageDelayed(msg, delayMilliseconds);
6830 }
6831
Jeff Brown6cb7b462012-03-05 13:21:17 -08006832 public void dispatchInvalidateOnAnimation(View view) {
6833 mInvalidateOnAnimationRunnable.addView(view);
6834 }
6835
6836 public void dispatchInvalidateRectOnAnimation(AttachInfo.InvalidateInfo info) {
6837 mInvalidateOnAnimationRunnable.addViewRect(info);
6838 }
6839
6840 public void cancelInvalidate(View view) {
6841 mHandler.removeMessages(MSG_INVALIDATE, view);
6842 // fixme: might leak the AttachInfo.InvalidateInfo objects instead of returning
6843 // them to the pool
6844 mHandler.removeMessages(MSG_INVALIDATE_RECT, view);
6845 mInvalidateOnAnimationRunnable.removeView(view);
6846 }
6847
keunyoung30f420f2013-08-02 14:23:10 -07006848 public void dispatchInputEvent(InputEvent event) {
Jae Seo6a6059a2014-04-17 21:35:29 -07006849 dispatchInputEvent(event, null);
6850 }
6851
6852 public void dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {
6853 SomeArgs args = SomeArgs.obtain();
6854 args.arg1 = event;
6855 args.arg2 = receiver;
6856 Message msg = mHandler.obtainMessage(MSG_DISPATCH_INPUT_EVENT, args);
Jeff Browne0dbd002012-02-15 19:34:58 -08006857 msg.setAsynchronous(true);
Jeff Browna175a5b2012-02-15 19:18:31 -08006858 mHandler.sendMessage(msg);
6859 }
6860
Michael Wright899d7052014-04-23 17:23:39 -07006861 public void synthesizeInputEvent(InputEvent event) {
6862 Message msg = mHandler.obtainMessage(MSG_SYNTHESIZE_INPUT_EVENT, event);
6863 msg.setAsynchronous(true);
6864 mHandler.sendMessage(msg);
6865 }
6866
Jeff Browna175a5b2012-02-15 19:18:31 -08006867 public void dispatchKeyFromIme(KeyEvent event) {
6868 Message msg = mHandler.obtainMessage(MSG_DISPATCH_KEY_FROM_IME, event);
Jeff Browne0dbd002012-02-15 19:34:58 -08006869 msg.setAsynchronous(true);
Jeff Browna175a5b2012-02-15 19:18:31 -08006870 mHandler.sendMessage(msg);
Jeff Browncb1404e2011-01-15 18:14:15 -08006871 }
6872
Michael Wright899d7052014-04-23 17:23:39 -07006873 /**
6874 * Reinject unhandled {@link InputEvent}s in order to synthesize fallbacks events.
6875 *
6876 * Note that it is the responsibility of the caller of this API to recycle the InputEvent it
6877 * passes in.
6878 */
Michael Wright3da28342014-04-22 17:00:11 -07006879 public void dispatchUnhandledInputEvent(InputEvent event) {
Michael Wright899d7052014-04-23 17:23:39 -07006880 if (event instanceof MotionEvent) {
6881 event = MotionEvent.obtain((MotionEvent) event);
Michael Wright3da28342014-04-22 17:00:11 -07006882 }
Michael Wright899d7052014-04-23 17:23:39 -07006883 synthesizeInputEvent(event);
Michael Wright3da28342014-04-22 17:00:11 -07006884 }
6885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006886 public void dispatchAppVisibility(boolean visible) {
Jeff Browna175a5b2012-02-15 19:18:31 -08006887 Message msg = mHandler.obtainMessage(MSG_DISPATCH_APP_VISIBILITY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006888 msg.arg1 = visible ? 1 : 0;
Jeff Browna175a5b2012-02-15 19:18:31 -08006889 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006890 }
6891
6892 public void dispatchGetNewSurface() {
Jeff Browna175a5b2012-02-15 19:18:31 -08006893 Message msg = mHandler.obtainMessage(MSG_DISPATCH_GET_NEW_SURFACE);
6894 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006895 }
6896
6897 public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
6898 Message msg = Message.obtain();
Jeff Browna175a5b2012-02-15 19:18:31 -08006899 msg.what = MSG_WINDOW_FOCUS_CHANGED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006900 msg.arg1 = hasFocus ? 1 : 0;
6901 msg.arg2 = inTouchMode ? 1 : 0;
Jeff Browna175a5b2012-02-15 19:18:31 -08006902 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006903 }
6904
Craig Mautner9c795042014-10-28 19:59:59 -07006905 public void dispatchWindowShown() {
6906 mHandler.sendEmptyMessage(MSG_DISPATCH_WINDOW_SHOWN);
6907 }
6908
Dianne Hackbornffa42482009-09-23 22:20:11 -07006909 public void dispatchCloseSystemDialogs(String reason) {
6910 Message msg = Message.obtain();
Jeff Browna175a5b2012-02-15 19:18:31 -08006911 msg.what = MSG_CLOSE_SYSTEM_DIALOGS;
Dianne Hackbornffa42482009-09-23 22:20:11 -07006912 msg.obj = reason;
Jeff Browna175a5b2012-02-15 19:18:31 -08006913 mHandler.sendMessage(msg);
Dianne Hackbornffa42482009-09-23 22:20:11 -07006914 }
Christopher Tatea53146c2010-09-07 11:57:52 -07006915
6916 public void dispatchDragEvent(DragEvent event) {
Chris Tate91e9bb32010-10-12 12:58:43 -07006917 final int what;
6918 if (event.getAction() == DragEvent.ACTION_DRAG_LOCATION) {
Jeff Browna175a5b2012-02-15 19:18:31 -08006919 what = MSG_DISPATCH_DRAG_LOCATION_EVENT;
6920 mHandler.removeMessages(what);
Chris Tate91e9bb32010-10-12 12:58:43 -07006921 } else {
Jeff Browna175a5b2012-02-15 19:18:31 -08006922 what = MSG_DISPATCH_DRAG_EVENT;
Chris Tate91e9bb32010-10-12 12:58:43 -07006923 }
Jeff Browna175a5b2012-02-15 19:18:31 -08006924 Message msg = mHandler.obtainMessage(what, event);
6925 mHandler.sendMessage(msg);
Christopher Tatea53146c2010-09-07 11:57:52 -07006926 }
6927
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08006928 public void updatePointerIcon(float x, float y) {
6929 final int what = MSG_UPDATE_POINTER_ICON;
6930 mHandler.removeMessages(what);
6931 final long now = SystemClock.uptimeMillis();
6932 final MotionEvent event = MotionEvent.obtain(
6933 0, now, MotionEvent.ACTION_HOVER_MOVE, x, y, 0);
6934 Message msg = mHandler.obtainMessage(what, event);
6935 mHandler.sendMessage(msg);
6936 }
6937
Dianne Hackborn9a230e02011-10-06 11:51:27 -07006938 public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
6939 int localValue, int localChanges) {
6940 SystemUiVisibilityInfo args = new SystemUiVisibilityInfo();
6941 args.seq = seq;
6942 args.globalVisibility = globalVisibility;
6943 args.localValue = localValue;
6944 args.localChanges = localChanges;
Jeff Browna175a5b2012-02-15 19:18:31 -08006945 mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPATCH_SYSTEM_UI_VISIBILITY, args));
6946 }
6947
6948 public void dispatchCheckFocus() {
6949 if (!mHandler.hasMessages(MSG_CHECK_FOCUS)) {
6950 // This will result in a call to checkFocus() below.
6951 mHandler.sendEmptyMessage(MSG_CHECK_FOCUS);
6952 }
Joe Onorato664644d2011-01-23 17:53:23 -08006953 }
6954
Clara Bayarrifcd7e802016-03-10 12:58:18 +00006955 public void dispatchRequestKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
6956 mHandler.obtainMessage(
6957 MSG_REQUEST_KEYBOARD_SHORTCUTS, deviceId, 0, receiver).sendToTarget();
Clara Bayarri75e09792015-07-29 16:20:40 +01006958 }
6959
Vladislav Kaznacheev3787de12016-12-21 10:36:35 -08006960 public void dispatchPointerCaptureChanged(boolean on) {
6961 final int what = MSG_POINTER_CAPTURE_CHANGED;
6962 mHandler.removeMessages(what);
6963 Message msg = mHandler.obtainMessage(what);
6964 msg.arg1 = on ? 1 : 0;
6965 mHandler.sendMessage(msg);
6966 }
6967
svetoslavganov75986cf2009-05-14 22:28:01 -07006968 /**
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07006969 * Post a callback to send a
6970 * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
Svetoslav Ganova0156172011-06-26 17:55:44 -07006971 * This event is send at most once every
6972 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07006973 */
Alan Viverette77e9a282013-09-12 17:16:09 -07006974 private void postSendWindowContentChangedCallback(View source, int changeType) {
Svetoslav Ganova0156172011-06-26 17:55:44 -07006975 if (mSendWindowContentChangedAccessibilityEvent == null) {
6976 mSendWindowContentChangedAccessibilityEvent =
6977 new SendWindowContentChangedAccessibilityEvent();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07006978 }
Alan Viverette77e9a282013-09-12 17:16:09 -07006979 mSendWindowContentChangedAccessibilityEvent.runOrPost(source, changeType);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07006980 }
6981
6982 /**
6983 * Remove a posted callback to send a
6984 * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
6985 */
6986 private void removeSendWindowContentChangedCallback() {
Svetoslav Ganova0156172011-06-26 17:55:44 -07006987 if (mSendWindowContentChangedAccessibilityEvent != null) {
Jeff Browna175a5b2012-02-15 19:18:31 -08006988 mHandler.removeCallbacks(mSendWindowContentChangedAccessibilityEvent);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07006989 }
6990 }
6991
Igor Murashkina86ab6402013-08-30 12:58:36 -07006992 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006993 public boolean showContextMenuForChild(View originalView) {
6994 return false;
6995 }
6996
Igor Murashkina86ab6402013-08-30 12:58:36 -07006997 @Override
Oren Blasberged391262015-09-01 12:12:51 -07006998 public boolean showContextMenuForChild(View originalView, float x, float y) {
6999 return false;
7000 }
7001
7002 @Override
Adam Powell6e346362010-07-23 10:18:23 -07007003 public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback) {
7004 return null;
7005 }
7006
Igor Murashkina86ab6402013-08-30 12:58:36 -07007007 @Override
Clara Bayarri4423d912015-03-02 19:42:48 +00007008 public ActionMode startActionModeForChild(
7009 View originalView, ActionMode.Callback callback, int type) {
7010 return null;
7011 }
7012
7013 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014 public void createContextMenu(ContextMenu menu) {
7015 }
7016
Igor Murashkina86ab6402013-08-30 12:58:36 -07007017 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007018 public void childDrawableStateChanged(View child) {
7019 }
7020
Igor Murashkina86ab6402013-08-30 12:58:36 -07007021 @Override
Svetoslav Ganov736c2752011-04-22 18:30:36 -07007022 public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) {
George Mount41725de2015-04-09 08:23:05 -07007023 if (mView == null || mStopped || mPausedForTransition) {
Svetoslav Ganov736c2752011-04-22 18:30:36 -07007024 return false;
7025 }
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07007026 // Intercept accessibility focus events fired by virtual nodes to keep
7027 // track of accessibility focus position in such nodes.
Svetoslav Ganov791fd312012-05-14 15:12:30 -07007028 final int eventType = event.getEventType();
7029 switch (eventType) {
7030 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07007031 final long sourceNodeId = event.getSourceNodeId();
7032 final int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(
7033 sourceNodeId);
7034 View source = mView.findViewByAccessibilityId(accessibilityViewId);
7035 if (source != null) {
7036 AccessibilityNodeProvider provider = source.getAccessibilityNodeProvider();
7037 if (provider != null) {
Svetoslavb3ba1d42014-09-26 15:20:40 -07007038 final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
7039 sourceNodeId);
7040 final AccessibilityNodeInfo node;
Phil Weaverf00cd142017-03-03 13:44:00 -08007041 node = provider.createAccessibilityNodeInfo(virtualNodeId);
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07007042 setAccessibilityFocus(source, node);
7043 }
Svetoslav Ganov791fd312012-05-14 15:12:30 -07007044 }
Svetoslav Ganov791fd312012-05-14 15:12:30 -07007045 } break;
7046 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07007047 final long sourceNodeId = event.getSourceNodeId();
7048 final int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(
7049 sourceNodeId);
7050 View source = mView.findViewByAccessibilityId(accessibilityViewId);
7051 if (source != null) {
7052 AccessibilityNodeProvider provider = source.getAccessibilityNodeProvider();
7053 if (provider != null) {
7054 setAccessibilityFocus(null, null);
7055 }
Svetoslav Ganov791fd312012-05-14 15:12:30 -07007056 }
Svetoslav Ganov791fd312012-05-14 15:12:30 -07007057 } break;
Svetoslavf0c758b2014-09-03 17:47:37 -07007058
7059
7060 case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
Alan Viverette34457f52015-03-25 13:09:20 -07007061 handleWindowContentChangedEvent(event);
Svetoslavf0c758b2014-09-03 17:47:37 -07007062 } break;
Svetoslav Ganov791fd312012-05-14 15:12:30 -07007063 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007064 mAccessibilityManager.sendAccessibilityEvent(event);
Svetoslav Ganov736c2752011-04-22 18:30:36 -07007065 return true;
7066 }
7067
Alan Viverette34457f52015-03-25 13:09:20 -07007068 /**
7069 * Updates the focused virtual view, when necessary, in response to a
7070 * content changed event.
7071 * <p>
7072 * This is necessary to get updated bounds after a position change.
7073 *
7074 * @param event an accessibility event of type
7075 * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}
7076 */
7077 private void handleWindowContentChangedEvent(AccessibilityEvent event) {
Alan Viverette25acc7e2015-05-19 11:32:08 -07007078 final View focusedHost = mAccessibilityFocusedHost;
7079 if (focusedHost == null || mAccessibilityFocusedVirtualView == null) {
7080 // No virtual view focused, nothing to do here.
Alan Viverette34457f52015-03-25 13:09:20 -07007081 return;
7082 }
7083
Alan Viverette25acc7e2015-05-19 11:32:08 -07007084 final AccessibilityNodeProvider provider = focusedHost.getAccessibilityNodeProvider();
Alan Viverette34457f52015-03-25 13:09:20 -07007085 if (provider == null) {
Alan Viverette25acc7e2015-05-19 11:32:08 -07007086 // Error state: virtual view with no provider. Clear focus.
7087 mAccessibilityFocusedHost = null;
7088 mAccessibilityFocusedVirtualView = null;
Phil Weavere37cfab2016-04-07 21:01:57 -07007089 focusedHost.clearAccessibilityFocusNoCallbacks(0);
Alan Viverette34457f52015-03-25 13:09:20 -07007090 return;
7091 }
7092
7093 // We only care about change types that may affect the bounds of the
7094 // focused virtual view.
7095 final int changes = event.getContentChangeTypes();
7096 if ((changes & AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE) == 0
7097 && changes != AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED) {
7098 return;
7099 }
7100
7101 final long eventSourceNodeId = event.getSourceNodeId();
7102 final int changedViewId = AccessibilityNodeInfo.getAccessibilityViewId(eventSourceNodeId);
7103
7104 // Search up the tree for subtree containment.
7105 boolean hostInSubtree = false;
7106 View root = mAccessibilityFocusedHost;
7107 while (root != null && !hostInSubtree) {
7108 if (changedViewId == root.getAccessibilityViewId()) {
7109 hostInSubtree = true;
7110 } else {
7111 final ViewParent parent = root.getParent();
7112 if (parent instanceof View) {
7113 root = (View) parent;
7114 } else {
7115 root = null;
7116 }
7117 }
7118 }
7119
7120 // We care only about changes in subtrees containing the host view.
7121 if (!hostInSubtree) {
7122 return;
7123 }
7124
7125 final long focusedSourceNodeId = mAccessibilityFocusedVirtualView.getSourceNodeId();
7126 int focusedChildId = AccessibilityNodeInfo.getVirtualDescendantId(focusedSourceNodeId);
Alan Viverette34457f52015-03-25 13:09:20 -07007127
7128 // Refresh the node for the focused virtual view.
Alan Viverettea7ea65e2015-05-15 11:30:21 -07007129 final Rect oldBounds = mTempRect;
7130 mAccessibilityFocusedVirtualView.getBoundsInScreen(oldBounds);
Alan Viverette34457f52015-03-25 13:09:20 -07007131 mAccessibilityFocusedVirtualView = provider.createAccessibilityNodeInfo(focusedChildId);
Alan Viverette25acc7e2015-05-19 11:32:08 -07007132 if (mAccessibilityFocusedVirtualView == null) {
7133 // Error state: The node no longer exists. Clear focus.
7134 mAccessibilityFocusedHost = null;
Phil Weavere37cfab2016-04-07 21:01:57 -07007135 focusedHost.clearAccessibilityFocusNoCallbacks(0);
Alan Viverette25acc7e2015-05-19 11:32:08 -07007136
7137 // This will probably fail, but try to keep the provider's internal
7138 // state consistent by clearing focus.
7139 provider.performAction(focusedChildId,
7140 AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS.getId(), null);
Alan Viverettea7ea65e2015-05-15 11:30:21 -07007141 invalidateRectOnScreen(oldBounds);
Alan Viverette25acc7e2015-05-19 11:32:08 -07007142 } else {
7143 // The node was refreshed, invalidate bounds if necessary.
7144 final Rect newBounds = mAccessibilityFocusedVirtualView.getBoundsInScreen();
7145 if (!oldBounds.equals(newBounds)) {
7146 oldBounds.union(newBounds);
7147 invalidateRectOnScreen(oldBounds);
7148 }
Alan Viverettea7ea65e2015-05-15 11:30:21 -07007149 }
Alan Viverette34457f52015-03-25 13:09:20 -07007150 }
7151
Svetoslav Ganov42138042012-03-20 11:51:39 -07007152 @Override
Alan Viverette77e9a282013-09-12 17:16:09 -07007153 public void notifySubtreeAccessibilityStateChanged(View child, View source, int changeType) {
7154 postSendWindowContentChangedCallback(source, changeType);
Svetoslav Ganov42138042012-03-20 11:51:39 -07007155 }
7156
Fabrice Di Meglio9dd4c5c2013-02-08 18:15:07 -08007157 @Override
7158 public boolean canResolveLayoutDirection() {
7159 return true;
7160 }
7161
7162 @Override
7163 public boolean isLayoutDirectionResolved() {
7164 return true;
7165 }
7166
7167 @Override
7168 public int getLayoutDirection() {
7169 return View.LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7170 }
7171
7172 @Override
7173 public boolean canResolveTextDirection() {
7174 return true;
7175 }
7176
7177 @Override
7178 public boolean isTextDirectionResolved() {
7179 return true;
7180 }
7181
7182 @Override
7183 public int getTextDirection() {
7184 return View.TEXT_DIRECTION_RESOLVED_DEFAULT;
7185 }
7186
7187 @Override
7188 public boolean canResolveTextAlignment() {
7189 return true;
7190 }
7191
7192 @Override
7193 public boolean isTextAlignmentResolved() {
7194 return true;
7195 }
7196
7197 @Override
7198 public int getTextAlignment() {
7199 return View.TEXT_ALIGNMENT_RESOLVED_DEFAULT;
7200 }
7201
Svetoslav Ganov42138042012-03-20 11:51:39 -07007202 private View getCommonPredecessor(View first, View second) {
Chris Craikd36a81f2014-07-17 10:16:51 -07007203 if (mTempHashSet == null) {
7204 mTempHashSet = new HashSet<View>();
Svetoslav Ganov42138042012-03-20 11:51:39 -07007205 }
Chris Craikd36a81f2014-07-17 10:16:51 -07007206 HashSet<View> seen = mTempHashSet;
7207 seen.clear();
7208 View firstCurrent = first;
7209 while (firstCurrent != null) {
7210 seen.add(firstCurrent);
7211 ViewParent firstCurrentParent = firstCurrent.mParent;
7212 if (firstCurrentParent instanceof View) {
7213 firstCurrent = (View) firstCurrentParent;
7214 } else {
7215 firstCurrent = null;
7216 }
7217 }
7218 View secondCurrent = second;
7219 while (secondCurrent != null) {
7220 if (seen.contains(secondCurrent)) {
7221 seen.clear();
7222 return secondCurrent;
7223 }
7224 ViewParent secondCurrentParent = secondCurrent.mParent;
7225 if (secondCurrentParent instanceof View) {
7226 secondCurrent = (View) secondCurrentParent;
7227 } else {
7228 secondCurrent = null;
7229 }
7230 }
7231 seen.clear();
Svetoslav Ganov42138042012-03-20 11:51:39 -07007232 return null;
7233 }
7234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007235 void checkThread() {
7236 if (mThread != Thread.currentThread()) {
7237 throw new CalledFromWrongThreadException(
7238 "Only the original thread that created a view hierarchy can touch its views.");
7239 }
7240 }
7241
Igor Murashkina86ab6402013-08-30 12:58:36 -07007242 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007243 public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
Joe Onoratoc6cc0f82011-04-12 11:53:13 -07007244 // ViewAncestor never intercepts touch event, so this can be a no-op
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007245 }
7246
Igor Murashkina86ab6402013-08-30 12:58:36 -07007247 @Override
Svetoslav Ganov1cf70bb2012-08-06 10:53:34 -07007248 public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
Yigit Boyard62d5e92016-01-19 18:56:20 -08007249 if (rectangle == null) {
7250 return scrollToRectOrFocus(null, immediate);
7251 }
7252 rectangle.offset(child.getLeft() - child.getScrollX(),
7253 child.getTop() - child.getScrollY());
Svetoslav Ganov1cf70bb2012-08-06 10:53:34 -07007254 final boolean scrolled = scrollToRectOrFocus(rectangle, immediate);
Yigit Boyard62d5e92016-01-19 18:56:20 -08007255 mTempRect.set(rectangle);
7256 mTempRect.offset(0, -mCurScrollY);
7257 mTempRect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
7258 try {
7259 mWindowSession.onRectangleOnScreenRequested(mWindow, mTempRect);
7260 } catch (RemoteException re) {
7261 /* ignore */
Svetoslav Ganov1cf70bb2012-08-06 10:53:34 -07007262 }
7263 return scrolled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007264 }
Romain Guy8506ab42009-06-11 17:35:47 -07007265
Igor Murashkina86ab6402013-08-30 12:58:36 -07007266 @Override
Adam Powell539ee872012-02-03 19:00:49 -08007267 public void childHasTransientStateChanged(View child, boolean hasTransientState) {
7268 // Do nothing.
7269 }
7270
Adam Powell10ba2772014-04-15 09:46:51 -07007271 @Override
7272 public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
7273 return false;
7274 }
7275
7276 @Override
7277 public void onStopNestedScroll(View target) {
7278 }
7279
7280 @Override
7281 public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) {
7282 }
7283
7284 @Override
7285 public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
7286 int dxUnconsumed, int dyUnconsumed) {
7287 }
7288
7289 @Override
7290 public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
7291 }
7292
7293 @Override
Adam Powellb36e4f92014-05-01 10:23:33 -07007294 public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
Adam Powell10ba2772014-04-15 09:46:51 -07007295 return false;
7296 }
7297
Adam Powellb72be592014-07-16 21:41:31 -07007298 @Override
7299 public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
7300 return false;
7301 }
7302
Adam Powellb6ab0982015-01-07 17:00:12 -08007303 @Override
7304 public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle args) {
7305 return false;
7306 }
7307
Jorim Jaggib774e552015-08-24 14:52:45 -07007308 /**
7309 * Force the window to report its next draw.
7310 * <p>
7311 * This method is only supposed to be used to speed up the interaction from SystemUI and window
7312 * manager when waiting for the first frame to be drawn when turning on the screen. DO NOT USE
7313 * unless you fully understand this interaction.
7314 * @hide
7315 */
7316 public void setReportNextDraw() {
7317 mReportNextDraw = true;
7318 invalidate();
7319 }
7320
Craig Mautnerbc57cd12013-08-19 15:47:42 -07007321 void changeCanvasOpacity(boolean opaque) {
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08007322 Log.d(mTag, "changeCanvasOpacity: opaque=" + opaque);
Stan Iliev45faba52016-06-28 13:33:15 -04007323 if (mAttachInfo.mThreadedRenderer != null) {
7324 mAttachInfo.mThreadedRenderer.setOpaque(opaque);
John Reck63a06672014-05-07 13:45:54 -07007325 }
Craig Mautnerbc57cd12013-08-19 15:47:42 -07007326 }
7327
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07007328 class TakenSurfaceHolder extends BaseSurfaceHolder {
7329 @Override
7330 public boolean onAllowLockCanvas() {
7331 return mDrawingAllowed;
7332 }
7333
7334 @Override
7335 public void onRelayoutContainer() {
7336 // Not currently interesting -- from changing between fixed and layout size.
7337 }
7338
Igor Murashkina86ab6402013-08-30 12:58:36 -07007339 @Override
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07007340 public void setFormat(int format) {
7341 ((RootViewSurfaceTaker)mView).setSurfaceFormat(format);
7342 }
7343
Igor Murashkina86ab6402013-08-30 12:58:36 -07007344 @Override
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07007345 public void setType(int type) {
7346 ((RootViewSurfaceTaker)mView).setSurfaceType(type);
7347 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07007348
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07007349 @Override
7350 public void onUpdateSurface() {
7351 // We take care of format and type changes on our own.
7352 throw new IllegalStateException("Shouldn't be here");
7353 }
7354
Igor Murashkina86ab6402013-08-30 12:58:36 -07007355 @Override
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07007356 public boolean isCreating() {
7357 return mIsCreating;
7358 }
7359
7360 @Override
7361 public void setFixedSize(int width, int height) {
7362 throw new UnsupportedOperationException(
7363 "Currently only support sizing from layout");
7364 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07007365
7366 @Override
Dianne Hackborndc8a7f62010-05-10 11:29:34 -07007367 public void setKeepScreenOn(boolean screenOn) {
7368 ((RootViewSurfaceTaker)mView).setSurfaceKeepScreenOn(screenOn);
7369 }
7370 }
Romain Guy8506ab42009-06-11 17:35:47 -07007371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007372 static class W extends IWindow.Stub {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07007373 private final WeakReference<ViewRootImpl> mViewAncestor;
Jeff Brown98365d72012-08-19 20:30:52 -07007374 private final IWindowSession mWindowSession;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007375
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07007376 W(ViewRootImpl viewAncestor) {
7377 mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
Jeff Brown98365d72012-08-19 20:30:52 -07007378 mWindowSession = viewAncestor.mWindowSession;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007379 }
7380
Igor Murashkina86ab6402013-08-30 12:58:36 -07007381 @Override
Dianne Hackbornc4aad012013-02-22 15:05:25 -08007382 public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Filip Gruszczynski2217f612015-05-26 11:32:08 -07007383 Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
Andrii Kulian44607962017-03-16 11:06:24 -07007384 MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
Andrii Kulianb047b8b2017-02-08 18:38:26 -08007385 boolean alwaysConsumeNavBar, int displayId) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07007386 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007387 if (viewAncestor != null) {
Dianne Hackbornc4aad012013-02-22 15:05:25 -08007388 viewAncestor.dispatchResized(frame, overscanInsets, contentInsets,
Andrii Kulian44607962017-03-16 11:06:24 -07007389 visibleInsets, stableInsets, outsets, reportDraw, mergedConfiguration,
7390 backDropFrame, forceLayout, alwaysConsumeNavBar, displayId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007391 }
7392 }
7393
Craig Mautner5702d4d2012-06-30 14:10:16 -07007394 @Override
7395 public void moved(int newX, int newY) {
7396 final ViewRootImpl viewAncestor = mViewAncestor.get();
7397 if (viewAncestor != null) {
7398 viewAncestor.dispatchMoved(newX, newY);
7399 }
7400 }
7401
Igor Murashkina86ab6402013-08-30 12:58:36 -07007402 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007403 public void dispatchAppVisibility(boolean visible) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07007404 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007405 if (viewAncestor != null) {
7406 viewAncestor.dispatchAppVisibility(visible);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007407 }
7408 }
7409
Igor Murashkina86ab6402013-08-30 12:58:36 -07007410 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007411 public void dispatchGetNewSurface() {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07007412 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007413 if (viewAncestor != null) {
7414 viewAncestor.dispatchGetNewSurface();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007415 }
7416 }
7417
Igor Murashkina86ab6402013-08-30 12:58:36 -07007418 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007419 public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07007420 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007421 if (viewAncestor != null) {
7422 viewAncestor.windowFocusChanged(hasFocus, inTouchMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007423 }
7424 }
7425
7426 private static int checkCallingPermission(String permission) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08007428 return ActivityManager.getService().checkPermission(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007429 permission, Binder.getCallingPid(), Binder.getCallingUid());
7430 } catch (RemoteException e) {
7431 return PackageManager.PERMISSION_DENIED;
7432 }
7433 }
7434
Igor Murashkina86ab6402013-08-30 12:58:36 -07007435 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007436 public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07007437 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007438 if (viewAncestor != null) {
7439 final View view = viewAncestor.mView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007440 if (view != null) {
7441 if (checkCallingPermission(Manifest.permission.DUMP) !=
7442 PackageManager.PERMISSION_GRANTED) {
7443 throw new SecurityException("Insufficient permissions to invoke"
7444 + " executeCommand() from pid=" + Binder.getCallingPid()
7445 + ", uid=" + Binder.getCallingUid());
7446 }
7447
7448 OutputStream clientStream = null;
7449 try {
7450 clientStream = new ParcelFileDescriptor.AutoCloseOutputStream(out);
7451 ViewDebug.dispatchCommand(view, command, parameters, clientStream);
7452 } catch (IOException e) {
7453 e.printStackTrace();
7454 } finally {
7455 if (clientStream != null) {
7456 try {
7457 clientStream.close();
7458 } catch (IOException e) {
7459 e.printStackTrace();
7460 }
7461 }
7462 }
7463 }
7464 }
7465 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07007466
7467 @Override
Dianne Hackbornffa42482009-09-23 22:20:11 -07007468 public void closeSystemDialogs(String reason) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07007469 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007470 if (viewAncestor != null) {
7471 viewAncestor.dispatchCloseSystemDialogs(reason);
Dianne Hackbornffa42482009-09-23 22:20:11 -07007472 }
7473 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07007474
7475 @Override
Marco Nelissenbf6956b2009-11-09 15:21:13 -08007476 public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
7477 boolean sync) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07007478 if (sync) {
7479 try {
Jeff Brown98365d72012-08-19 20:30:52 -07007480 mWindowSession.wallpaperOffsetsComplete(asBinder());
Dianne Hackborn19382ac2009-09-11 21:13:37 -07007481 } catch (RemoteException e) {
7482 }
7483 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07007484 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007485
Igor Murashkina86ab6402013-08-30 12:58:36 -07007486 @Override
Dianne Hackborn75804932009-10-20 20:15:20 -07007487 public void dispatchWallpaperCommand(String action, int x, int y,
7488 int z, Bundle extras, boolean sync) {
7489 if (sync) {
7490 try {
Jeff Brown98365d72012-08-19 20:30:52 -07007491 mWindowSession.wallpaperCommandComplete(asBinder(), null);
Dianne Hackborn75804932009-10-20 20:15:20 -07007492 } catch (RemoteException e) {
7493 }
7494 }
7495 }
Christopher Tatea53146c2010-09-07 11:57:52 -07007496
7497 /* Drag/drop */
Igor Murashkina86ab6402013-08-30 12:58:36 -07007498 @Override
Christopher Tatea53146c2010-09-07 11:57:52 -07007499 public void dispatchDragEvent(DragEvent event) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07007500 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007501 if (viewAncestor != null) {
7502 viewAncestor.dispatchDragEvent(event);
Christopher Tatea53146c2010-09-07 11:57:52 -07007503 }
7504 }
Joe Onorato664644d2011-01-23 17:53:23 -08007505
Igor Murashkina86ab6402013-08-30 12:58:36 -07007506 @Override
Vladislav Kaznacheevec6a4472016-01-22 12:21:52 -08007507 public void updatePointerIcon(float x, float y) {
7508 final ViewRootImpl viewAncestor = mViewAncestor.get();
7509 if (viewAncestor != null) {
7510 viewAncestor.updatePointerIcon(x, y);
7511 }
7512 }
7513
7514 @Override
Dianne Hackborn9a230e02011-10-06 11:51:27 -07007515 public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
7516 int localValue, int localChanges) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07007517 final ViewRootImpl viewAncestor = mViewAncestor.get();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007518 if (viewAncestor != null) {
Dianne Hackborn9a230e02011-10-06 11:51:27 -07007519 viewAncestor.dispatchSystemUiVisibilityChanged(seq, globalVisibility,
7520 localValue, localChanges);
Joe Onorato664644d2011-01-23 17:53:23 -08007521 }
7522 }
Dianne Hackborn12d3a942012-04-27 14:16:30 -07007523
Igor Murashkina86ab6402013-08-30 12:58:36 -07007524 @Override
Craig Mautner9c795042014-10-28 19:59:59 -07007525 public void dispatchWindowShown() {
7526 final ViewRootImpl viewAncestor = mViewAncestor.get();
7527 if (viewAncestor != null) {
7528 viewAncestor.dispatchWindowShown();
7529 }
7530 }
Clara Bayarri75e09792015-07-29 16:20:40 +01007531
7532 @Override
Clara Bayarrifcd7e802016-03-10 12:58:18 +00007533 public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
7534 ViewRootImpl viewAncestor = mViewAncestor.get();
7535 if (viewAncestor != null) {
7536 viewAncestor.dispatchRequestKeyboardShortcuts(receiver, deviceId);
7537 }
Clara Bayarri75e09792015-07-29 16:20:40 +01007538 }
Vladislav Kaznacheev3787de12016-12-21 10:36:35 -08007539
7540 @Override
7541 public void dispatchPointerCaptureChanged(boolean hasCapture) {
7542 final ViewRootImpl viewAncestor = mViewAncestor.get();
7543 if (viewAncestor != null) {
7544 viewAncestor.dispatchPointerCaptureChanged(hasCapture);
7545 }
7546 }
7547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007548 }
7549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007550 public static final class CalledFromWrongThreadException extends AndroidRuntimeException {
7551 public CalledFromWrongThreadException(String msg) {
7552 super(msg);
7553 }
7554 }
7555
Alan Viverettebea0c7da2015-09-01 16:00:20 -04007556 static HandlerActionQueue getRunQueue() {
7557 HandlerActionQueue rq = sRunQueues.get();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007558 if (rq != null) {
7559 return rq;
7560 }
Alan Viverettebea0c7da2015-09-01 16:00:20 -04007561 rq = new HandlerActionQueue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007562 sRunQueues.set(rq);
7563 return rq;
7564 }
Romain Guy8506ab42009-06-11 17:35:47 -07007565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007566 /**
Skuhneb8160872015-09-22 09:51:39 -07007567 * Start a drag resizing which will inform all listeners that a window resize is taking place.
7568 */
Jorim Jaggi9511b0f2016-01-29 19:12:44 -08007569 private void startDragResizing(Rect initialBounds, boolean fullscreen, Rect systemInsets,
Jorim Jaggic39c7b02016-03-24 10:47:07 -07007570 Rect stableInsets, int resizeMode) {
Skuhneb8160872015-09-22 09:51:39 -07007571 if (!mDragResizing) {
7572 mDragResizing = true;
Jorim Jaggi16b63192016-03-25 18:32:19 -07007573 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
7574 mWindowCallbacks.get(i).onWindowDragResizeStart(initialBounds, fullscreen,
7575 systemInsets, stableInsets, resizeMode);
Skuhneb8160872015-09-22 09:51:39 -07007576 }
7577 mFullRedrawNeeded = true;
7578 }
7579 }
7580
7581 /**
7582 * End a drag resize which will inform all listeners that a window resize has ended.
7583 */
7584 private void endDragResizing() {
7585 if (mDragResizing) {
7586 mDragResizing = false;
Jorim Jaggi16b63192016-03-25 18:32:19 -07007587 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
7588 mWindowCallbacks.get(i).onWindowDragResizeEnd();
Skuhneb8160872015-09-22 09:51:39 -07007589 }
7590 mFullRedrawNeeded = true;
7591 }
7592 }
7593
Chong Zhang8dbd9ad2015-10-09 10:06:11 -07007594 private boolean updateContentDrawBounds() {
7595 boolean updated = false;
Jorim Jaggi16b63192016-03-25 18:32:19 -07007596 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
7597 updated |= mWindowCallbacks.get(i).onContentDrawn(
7598 mWindowAttributes.surfaceInsets.left,
7599 mWindowAttributes.surfaceInsets.top,
7600 mWidth, mHeight);
Chong Zhang8dbd9ad2015-10-09 10:06:11 -07007601 }
7602 return updated | (mDragResizing && mReportNextDraw);
7603 }
7604
7605 private void requestDrawWindow() {
7606 if (mReportNextDraw) {
7607 mWindowDrawCountDown = new CountDownLatch(mWindowCallbacks.size());
7608 }
Jorim Jaggi16b63192016-03-25 18:32:19 -07007609 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
7610 mWindowCallbacks.get(i).onRequestDraw(mReportNextDraw);
Chong Zhang8dbd9ad2015-10-09 10:06:11 -07007611 }
7612 }
7613
Skuhneb8160872015-09-22 09:51:39 -07007614 /**
Jorim Jaggi4846ee32016-01-07 17:39:12 +01007615 * Tells this instance that its corresponding activity has just relaunched. In this case, we
7616 * need to force a relayout of the window to make sure we get the correct bounds from window
7617 * manager.
7618 */
7619 public void reportActivityRelaunched() {
7620 mActivityRelaunched = true;
7621 }
7622
7623 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007624 * Class for managing the accessibility interaction connection
7625 * based on the global accessibility state.
7626 */
7627 final class AccessibilityInteractionConnectionManager
7628 implements AccessibilityStateChangeListener {
Igor Murashkina86ab6402013-08-30 12:58:36 -07007629 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007630 public void onAccessibilityStateChanged(boolean enabled) {
7631 if (enabled) {
7632 ensureConnection();
Chris Craikcce47eb2014-07-16 15:12:15 -07007633 if (mAttachInfo.mHasWindowFocus) {
Svetoslav Ganov0d04e242012-02-21 13:46:36 -08007634 mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
7635 View focusedView = mView.findFocus();
7636 if (focusedView != null && focusedView != mView) {
7637 focusedView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
7638 }
7639 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007640 } else {
7641 ensureNoConnection();
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07007642 mHandler.obtainMessage(MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST).sendToTarget();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007643 }
7644 }
7645
7646 public void ensureConnection() {
Phil Weaverf00cd142017-03-03 13:44:00 -08007647 final boolean registered = mAttachInfo.mAccessibilityWindowId
7648 != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
Chris Craikcce47eb2014-07-16 15:12:15 -07007649 if (!registered) {
7650 mAttachInfo.mAccessibilityWindowId =
Svetoslav Ganov0d04e242012-02-21 13:46:36 -08007651 mAccessibilityManager.addAccessibilityInteractionConnection(mWindow,
7652 new AccessibilityInteractionConnection(ViewRootImpl.this));
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007653 }
7654 }
7655
7656 public void ensureNoConnection() {
Phil Weaverf00cd142017-03-03 13:44:00 -08007657 final boolean registered = mAttachInfo.mAccessibilityWindowId
7658 != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007659 if (registered) {
Phil Weaverf00cd142017-03-03 13:44:00 -08007660 mAttachInfo.mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007661 mAccessibilityManager.removeAccessibilityInteractionConnection(mWindow);
7662 }
7663 }
7664 }
7665
Chris Craikcce47eb2014-07-16 15:12:15 -07007666 final class HighContrastTextManager implements HighTextContrastChangeListener {
7667 HighContrastTextManager() {
7668 mAttachInfo.mHighContrastText = mAccessibilityManager.isHighTextContrastEnabled();
7669 }
7670 @Override
7671 public void onHighTextContrastStateChanged(boolean enabled) {
7672 mAttachInfo.mHighContrastText = enabled;
7673
7674 // Destroy Displaylists so they can be recreated with high contrast recordings
7675 destroyHardwareResources();
Chris Craikd36a81f2014-07-17 10:16:51 -07007676
7677 // Schedule redraw, which will rerecord + redraw all text
7678 invalidate();
Chris Craikcce47eb2014-07-16 15:12:15 -07007679 }
7680 }
7681
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007682 /**
7683 * This class is an interface this ViewAncestor provides to the
7684 * AccessibilityManagerService to the latter can interact with
7685 * the view hierarchy in this ViewAncestor.
7686 */
Svetoslav Ganovaf5b4f42011-10-28 12:41:38 -07007687 static final class AccessibilityInteractionConnection
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007688 extends IAccessibilityInteractionConnection.Stub {
Svetoslav Ganov02107852011-10-03 17:06:56 -07007689 private final WeakReference<ViewRootImpl> mViewRootImpl;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007690
Svetoslav Ganovf79f4762011-10-28 15:40:32 -07007691 AccessibilityInteractionConnection(ViewRootImpl viewRootImpl) {
7692 mViewRootImpl = new WeakReference<ViewRootImpl>(viewRootImpl);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007693 }
7694
Svetoslav Ganov42138042012-03-20 11:51:39 -07007695 @Override
Svetoslav Ganov02107852011-10-03 17:06:56 -07007696 public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId,
Svetoslav9ae9ed22014-09-02 16:36:35 -07007697 Region interactiveRegion, int interactionId,
7698 IAccessibilityInteractionConnectionCallback callback, int flags,
Phil Weaverc2e28932016-12-08 12:29:25 -08007699 int interrogatingPid, long interrogatingTid, MagnificationSpec spec, Bundle args) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07007700 ViewRootImpl viewRootImpl = mViewRootImpl.get();
7701 if (viewRootImpl != null && viewRootImpl.mView != null) {
Svetoslav Ganovaf5b4f42011-10-28 12:41:38 -07007702 viewRootImpl.getAccessibilityInteractionController()
Svetoslav Ganov02107852011-10-03 17:06:56 -07007703 .findAccessibilityNodeInfoByAccessibilityIdClientThread(accessibilityNodeId,
Svetoslav9ae9ed22014-09-02 16:36:35 -07007704 interactiveRegion, interactionId, callback, flags, interrogatingPid,
Phil Weaverc2e28932016-12-08 12:29:25 -08007705 interrogatingTid, spec, args);
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007706 } else {
7707 // We cannot make the call and notify the caller so it does not wait.
7708 try {
7709 callback.setFindAccessibilityNodeInfosResult(null, interactionId);
7710 } catch (RemoteException re) {
7711 /* best effort - ignore */
7712 }
Svetoslav Ganov601ad802011-06-09 14:47:38 -07007713 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007714 }
7715
Svetoslav Ganov42138042012-03-20 11:51:39 -07007716 @Override
Svetoslav Ganov02107852011-10-03 17:06:56 -07007717 public void performAccessibilityAction(long accessibilityNodeId, int action,
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07007718 Bundle arguments, int interactionId,
7719 IAccessibilityInteractionConnectionCallback callback, int flags,
Svet Ganov7498efd2014-09-03 21:33:00 -07007720 int interrogatingPid, long interrogatingTid) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07007721 ViewRootImpl viewRootImpl = mViewRootImpl.get();
7722 if (viewRootImpl != null && viewRootImpl.mView != null) {
Svetoslav Ganovaf5b4f42011-10-28 12:41:38 -07007723 viewRootImpl.getAccessibilityInteractionController()
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07007724 .performAccessibilityActionClientThread(accessibilityNodeId, action, arguments,
Svet Ganov7498efd2014-09-03 21:33:00 -07007725 interactionId, callback, flags, interrogatingPid, interrogatingTid);
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007726 } else {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007727 // We cannot make the call and notify the caller so it does not wait.
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007728 try {
7729 callback.setPerformAccessibilityActionResult(false, interactionId);
7730 } catch (RemoteException re) {
7731 /* best effort - ignore */
7732 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007733 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007734 }
7735
Svetoslav Ganov42138042012-03-20 11:51:39 -07007736 @Override
Svetoslav Ganov80943d82013-01-02 10:25:37 -08007737 public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId,
Svetoslav9ae9ed22014-09-02 16:36:35 -07007738 String viewId, Region interactiveRegion, int interactionId,
Svetoslav Ganov80943d82013-01-02 10:25:37 -08007739 IAccessibilityInteractionConnectionCallback callback, int flags,
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -07007740 int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07007741 ViewRootImpl viewRootImpl = mViewRootImpl.get();
7742 if (viewRootImpl != null && viewRootImpl.mView != null) {
Svetoslav Ganovaf5b4f42011-10-28 12:41:38 -07007743 viewRootImpl.getAccessibilityInteractionController()
Svetoslav Ganov80943d82013-01-02 10:25:37 -08007744 .findAccessibilityNodeInfosByViewIdClientThread(accessibilityNodeId,
Svetoslav9ae9ed22014-09-02 16:36:35 -07007745 viewId, interactiveRegion, interactionId, callback, flags,
7746 interrogatingPid, interrogatingTid, spec);
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007747 } else {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007748 // We cannot make the call and notify the caller so it does not wait.
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007749 try {
7750 callback.setFindAccessibilityNodeInfoResult(null, interactionId);
7751 } catch (RemoteException re) {
7752 /* best effort - ignore */
7753 }
7754 }
7755 }
7756
Svetoslav Ganov42138042012-03-20 11:51:39 -07007757 @Override
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007758 public void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text,
Svetoslav9ae9ed22014-09-02 16:36:35 -07007759 Region interactiveRegion, int interactionId,
7760 IAccessibilityInteractionConnectionCallback callback, int flags,
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -07007761 int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007762 ViewRootImpl viewRootImpl = mViewRootImpl.get();
7763 if (viewRootImpl != null && viewRootImpl.mView != null) {
7764 viewRootImpl.getAccessibilityInteractionController()
7765 .findAccessibilityNodeInfosByTextClientThread(accessibilityNodeId, text,
Svetoslav9ae9ed22014-09-02 16:36:35 -07007766 interactiveRegion, interactionId, callback, flags, interrogatingPid,
7767 interrogatingTid, spec);
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007768 } else {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007769 // We cannot make the call and notify the caller so it does not wait.
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007770 try {
7771 callback.setFindAccessibilityNodeInfosResult(null, interactionId);
7772 } catch (RemoteException re) {
7773 /* best effort - ignore */
7774 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007775 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007776 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007777
Svetoslav Ganov42138042012-03-20 11:51:39 -07007778 @Override
Svetoslav9ae9ed22014-09-02 16:36:35 -07007779 public void findFocus(long accessibilityNodeId, int focusType, Region interactiveRegion,
7780 int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -07007781 int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007782 ViewRootImpl viewRootImpl = mViewRootImpl.get();
7783 if (viewRootImpl != null && viewRootImpl.mView != null) {
7784 viewRootImpl.getAccessibilityInteractionController()
Svetoslav9ae9ed22014-09-02 16:36:35 -07007785 .findFocusClientThread(accessibilityNodeId, focusType, interactiveRegion,
7786 interactionId, callback, flags, interrogatingPid, interrogatingTid,
7787 spec);
Svetoslav Ganov8bd69612011-08-23 13:40:30 -07007788 } else {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007789 // We cannot make the call and notify the caller so it does not wait.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007790 try {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007791 callback.setFindAccessibilityNodeInfoResult(null, interactionId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007792 } catch (RemoteException re) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007793 /* best effort - ignore */
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007794 }
7795 }
7796 }
7797
Svetoslav Ganov42138042012-03-20 11:51:39 -07007798 @Override
Svetoslav9ae9ed22014-09-02 16:36:35 -07007799 public void focusSearch(long accessibilityNodeId, int direction, Region interactiveRegion,
7800 int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -07007801 int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007802 ViewRootImpl viewRootImpl = mViewRootImpl.get();
7803 if (viewRootImpl != null && viewRootImpl.mView != null) {
7804 viewRootImpl.getAccessibilityInteractionController()
Svetoslav9ae9ed22014-09-02 16:36:35 -07007805 .focusSearchClientThread(accessibilityNodeId, direction, interactiveRegion,
7806 interactionId, callback, flags, interrogatingPid, interrogatingTid,
7807 spec);
Svetoslav Ganov8bd69612011-08-23 13:40:30 -07007808 } else {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007809 // We cannot make the call and notify the caller so it does not wait.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007810 try {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007811 callback.setFindAccessibilityNodeInfoResult(null, interactionId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007812 } catch (RemoteException re) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007813 /* best effort - ignore */
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007814 }
7815 }
7816 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07007817 }
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07007818
Svetoslav Ganova0156172011-06-26 17:55:44 -07007819 private class SendWindowContentChangedAccessibilityEvent implements Runnable {
Alan Viverette77e9a282013-09-12 17:16:09 -07007820 private int mChangeTypes = 0;
7821
Svetoslav Ganov42138042012-03-20 11:51:39 -07007822 public View mSource;
Svetoslav6254f482013-06-04 17:22:14 -07007823 public long mLastEventTimeMillis;
Svetoslav Ganova0156172011-06-26 17:55:44 -07007824
Igor Murashkina86ab6402013-08-30 12:58:36 -07007825 @Override
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07007826 public void run() {
Svetoslav8d820ecf2013-07-15 17:12:41 -07007827 // The accessibility may be turned off while we were waiting so check again.
7828 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
7829 mLastEventTimeMillis = SystemClock.uptimeMillis();
7830 AccessibilityEvent event = AccessibilityEvent.obtain();
7831 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
Alan Viverette77e9a282013-09-12 17:16:09 -07007832 event.setContentChangeTypes(mChangeTypes);
Svetoslav8d820ecf2013-07-15 17:12:41 -07007833 mSource.sendAccessibilityEventUnchecked(event);
7834 } else {
7835 mLastEventTimeMillis = 0;
7836 }
7837 // In any case reset to initial state.
Svetoslav6254f482013-06-04 17:22:14 -07007838 mSource.resetSubtreeAccessibilityStateChanged();
7839 mSource = null;
Alan Viverette77e9a282013-09-12 17:16:09 -07007840 mChangeTypes = 0;
Svetoslav6254f482013-06-04 17:22:14 -07007841 }
7842
Alan Viverette77e9a282013-09-12 17:16:09 -07007843 public void runOrPost(View source, int changeType) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07007844 if (mSource != null) {
Svetoslav9dafebb2013-06-18 16:29:25 -07007845 // If there is no common predecessor, then mSource points to
7846 // a removed view, hence in this case always prefer the source.
7847 View predecessor = getCommonPredecessor(mSource, source);
7848 mSource = (predecessor != null) ? predecessor : source;
Alan Viverette77e9a282013-09-12 17:16:09 -07007849 mChangeTypes |= changeType;
Svetoslav6254f482013-06-04 17:22:14 -07007850 return;
7851 }
7852 mSource = source;
Alan Viverette77e9a282013-09-12 17:16:09 -07007853 mChangeTypes = changeType;
Svetoslav6254f482013-06-04 17:22:14 -07007854 final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
7855 final long minEventIntevalMillis =
7856 ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
7857 if (timeSinceLastMillis >= minEventIntevalMillis) {
Svetoslav9dafebb2013-06-18 16:29:25 -07007858 mSource.removeCallbacks(this);
Svetoslav6254f482013-06-04 17:22:14 -07007859 run();
7860 } else {
7861 mSource.postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
Svetoslav Ganov79311c42012-01-17 20:24:26 -08007862 }
7863 }
7864 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007865}