View-without-comments.java

 avatar
unknown
java
4 months ago
666 kB
29
No Index
in 8 months
package android.view;
import static android.content.res.Resources.ID_NULL;
import static android.os.Trace.TRACE_TAG_APP;
import static android.os.Trace.TRACE_TAG_VIEW;
import static android.service.autofill.Flags.FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION;
import static android.view.ContentInfo.SOURCE_DRAG_AND_DROP;
import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH;
import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE;
import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
import static android.view.Surface.FRAME_RATE_COMPATIBILITY_GTE;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_UNKNOWN;
import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH;
import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH_ERROR_CODE;
import static android.view.flags.Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API;
import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY;
import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API;
import static android.view.flags.Flags.enableUseMeasureCacheDuringForceLayout;
import static android.view.flags.Flags.sensitiveContentAppProtection;
import static android.view.flags.Flags.toolkitFrameRateBySizeReadOnly;
import static android.view.flags.Flags.toolkitFrameRateDefaultNormalReadOnly;
import static android.view.flags.Flags.toolkitFrameRateSmallUsesPercentReadOnly;
import static android.view.flags.Flags.toolkitFrameRateVelocityMappingReadOnly;
import static android.view.flags.Flags.toolkitFrameRateViewEnablingReadOnly;
import static android.view.flags.Flags.toolkitMetricsForFrameRateDecision;
import static android.view.flags.Flags.toolkitSetFrameRateReadOnly;
import static android.view.flags.Flags.viewVelocityApi;
import static android.view.inputmethod.Flags.FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR;
import static android.view.inputmethod.Flags.initiationWithoutInputConnection;
import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS;
import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS;
import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
import static com.android.window.flags.Flags.FLAG_DELEGATE_UNHANDLED_DRAGS;
import static java.lang.Math.max;
import android.animation.AnimatorInflater;
import android.animation.StateListAnimator;
import android.annotation.AttrRes;
import android.annotation.CallSuper;
import android.annotation.ColorInt;
import android.annotation.DrawableRes;
import android.annotation.FlaggedApi;
import android.annotation.FloatRange;
import android.annotation.IdRes;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.Size;
import android.annotation.StyleRes;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UiContext;
import android.annotation.UiThread;
import android.app.PendingIntent;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.AutofillOptions;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentSender;
import android.content.res.ColorStateList;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.credentials.CredentialManager;
import android.credentials.CredentialOption;
import android.credentials.GetCredentialException;
import android.credentials.GetCredentialRequest;
import android.credentials.GetCredentialResponse;
import android.graphics.Bitmap;
import android.graphics.BlendMode;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.Interpolator;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.RenderEffect;
import android.graphics.RenderNode;
import android.graphics.Shader;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.hardware.display.DisplayManagerGlobal;
import android.hardware.input.InputManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.OutcomeReceiver;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
import android.os.Vibrator;
import android.os.vibrator.Flags;
import android.service.credentials.CredentialProviderService;
import android.sysprop.DisplayProperties;
import android.text.InputType;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.FloatProperty;
import android.util.LayoutDirection;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.LongSparseLongArray;
import android.util.Pair;
import android.util.Pools.SynchronizedPool;
import android.util.Property;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.StateSet;
import android.util.SuperNotCalledException;
import android.util.TimeUtils;
import android.util.TypedValue;
import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
import android.view.AccessibilityIterators.TextSegmentIterator;
import android.view.AccessibilityIterators.WordTextSegmentIterator;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.InputDevice.InputSourceClass;
import android.view.Window.OnContentApplyWindowInsetsListener;
import android.view.WindowInsets.Type;
import android.view.WindowInsetsAnimation.Bounds;
import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityEventSource;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeIdManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.accessibility.AccessibilityNodeProvider;
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureManager;
import android.view.contentcapture.ContentCaptureSession;
import android.view.displayhash.DisplayHash;
import android.view.displayhash.DisplayHashManager;
import android.view.displayhash.DisplayHashResultCallback;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.view.inspector.InspectableProperty;
import android.view.inspector.InspectableProperty.EnumEntry;
import android.view.inspector.InspectableProperty.FlagEntry;
import android.view.translation.TranslationCapability;
import android.view.translation.TranslationSpec.DataFormat;
import android.view.translation.ViewTranslationCallback;
import android.view.translation.ViewTranslationRequest;
import android.view.translation.ViewTranslationResponse;
import android.widget.Checkable;
import android.widget.ScrollBarDrawable;
import android.window.OnBackInvokedDispatcher;
import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.Preconditions;
import com.android.internal.view.ScrollCaptureInternal;
import com.android.internal.view.TooltipPopup;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.widget.ScrollBarUtils;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Predicate;
@UiThread
public class View implements Drawable.Callback, KeyEvent.Callback,
        AccessibilityEventSource {
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private static final boolean DBG = false;
    public static boolean DEBUG_DRAW = false;
    protected static final String VIEW_LOG_TAG = "View";
    private static final String AUTOFILL_LOG_TAG = "View.Autofill";
    private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
    private static final boolean DEBUG_CONTENT_CAPTURE = false;
    public static boolean sDebugViewAttributes = false;
    public static String sDebugViewAttributesApplicationPackage;
    public static final int NO_ID = -1;
    public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
    private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
            new int[]{android.R.attr.autofilledHighlight};
    private static boolean sCompatibilityDone = false;
    public HapticScrollFeedbackProvider mScrollFeedbackProvider = null;
    private static boolean sAlwaysRemeasureExactly = false;
    private static boolean sUseMeasureCacheDuringForceLayoutFlagValue;
    static boolean sTextureViewIgnoresDrawableSetters = false;
    protected static boolean sPreserveMarginParamsInLayoutParamConversion;
    static boolean sCascadedDragDrop;
    static boolean sHasFocusableExcludeAutoFocusable;
    private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
    private static boolean sThrowOnInvalidFloatProperties;
    private static boolean sAcceptZeroSizeDragShadow;
    private static boolean sTraceLayoutSteps;
    private static String sTraceRequestLayoutClass;
    @Nullable
    private ViewCredentialHandler mViewCredentialHandler;
    @Nullable
    private ViewTraversalTracingStrings mTracingStrings;
    static boolean sBrokenInsetsDispatch;
    protected static boolean sBrokenWindowBackground;
    static boolean sForceLayoutWhenInsetsChanged;
    @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Focusable {}
    public static final int NOT_FOCUSABLE = 0x00000000;
    public static final int FOCUSABLE = 0x00000001;
    public static final int FOCUSABLE_AUTO = 0x00000010;
    private static final int FOCUSABLE_MASK = 0x00000011;
    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
    @IntDef({VISIBLE, INVISIBLE, GONE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Visibility {}
    public static final int VISIBLE = 0x00000000;
    public static final int INVISIBLE = 0x00000004;
    public static final int GONE = 0x00000008;
    static final int VISIBILITY_MASK = 0x0000000C;
    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
    public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
    public static final String AUTOFILL_HINT_NAME = "name";
    public static final String AUTOFILL_HINT_USERNAME = "username";
    public static final String AUTOFILL_HINT_PASSWORD = "password";
    public static final String AUTOFILL_HINT_PHONE = "phone";
    public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
    public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
    public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
    public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
            "creditCardExpirationDate";
    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
            "creditCardExpirationMonth";
    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
            "creditCardExpirationYear";
    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
    public static final String AUTOFILL_HINT_PASSWORD_AUTO = "passwordAuto";
    public static final String AUTOFILL_HINT_CREDENTIAL_MANAGER = "credential";
    private @Nullable String[] mAutofillHints;
    private AutofillId mAutofillId;
    @IntDef(prefix = { "AUTOFILL_TYPE_" }, value = {
            AUTOFILL_TYPE_NONE,
            AUTOFILL_TYPE_TEXT,
            AUTOFILL_TYPE_TOGGLE,
            AUTOFILL_TYPE_LIST,
            AUTOFILL_TYPE_DATE,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface AutofillType {}
    public static final int AUTOFILL_TYPE_NONE = 0;
    public static final int AUTOFILL_TYPE_TEXT = 1;
    public static final int AUTOFILL_TYPE_TOGGLE = 2;
    public static final int AUTOFILL_TYPE_LIST = 3;
    public static final int AUTOFILL_TYPE_DATE = 4;
    @IntDef(prefix = { "IMPORTANT_FOR_AUTOFILL_" }, value = {
            IMPORTANT_FOR_AUTOFILL_AUTO,
            IMPORTANT_FOR_AUTOFILL_YES,
            IMPORTANT_FOR_AUTOFILL_NO,
            IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
            IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface AutofillImportance {}
    public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
    public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
    public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
    public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
    public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
    @IntDef(flag = true, prefix = { "AUTOFILL_FLAG_" }, value = {
            AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface AutofillFlags {}
    public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
    @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
            IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
            IMPORTANT_FOR_CONTENT_CAPTURE_YES,
            IMPORTANT_FOR_CONTENT_CAPTURE_NO,
            IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
            IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ContentCaptureImportance {}
    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
    @IntDef(flag = true, prefix = {"SCROLL_CAPTURE_HINT_"},
            value = {
                    SCROLL_CAPTURE_HINT_AUTO,
                    SCROLL_CAPTURE_HINT_EXCLUDE,
                    SCROLL_CAPTURE_HINT_INCLUDE,
                    SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ScrollCaptureHint {}
    public static final int SCROLL_CAPTURE_HINT_AUTO = 0;
    public static final int SCROLL_CAPTURE_HINT_EXCLUDE = 0x1;
    public static final int SCROLL_CAPTURE_HINT_INCLUDE = 0x2;
    public static final int SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS = 0x4;
    static final int ENABLED = 0x00000000;
    static final int DISABLED = 0x00000020;
    static final int ENABLED_MASK = 0x00000020;
    static final int WILL_NOT_DRAW = 0x00000080;
    static final int DRAW_MASK = 0x00000080;
    static final int SCROLLBARS_NONE = 0x00000000;
    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
    static final int SCROLLBARS_VERTICAL = 0x00000200;
    static final int SCROLLBARS_MASK = 0x00000300;
    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
    static final int FADING_EDGE_NONE = 0x00000000;
    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
    static final int FADING_EDGE_VERTICAL = 0x00002000;
    static final int FADING_EDGE_MASK = 0x00003000;
    static final int CLICKABLE = 0x00004000;
    static final int DRAWING_CACHE_ENABLED = 0x00008000;
    static final int SAVE_DISABLED = 0x000010000;
    static final int SAVE_DISABLED_MASK = 0x000010000;
    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "DRAWING_CACHE_QUALITY_" }, value = {
            DRAWING_CACHE_QUALITY_LOW,
            DRAWING_CACHE_QUALITY_HIGH,
            DRAWING_CACHE_QUALITY_AUTO
    })
    public @interface DrawingCacheQuality {}
    @Deprecated
    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
    @Deprecated
    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
    @Deprecated
    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
    };
    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
    static final int LONG_CLICKABLE = 0x00200000;
    static final int DUPLICATE_PARENT_STATE = 0x00400000;
    static final int CONTEXT_CLICKABLE = 0x00800000;
    @IntDef(prefix = { "SCROLLBARS_" }, value = {
            SCROLLBARS_INSIDE_OVERLAY,
            SCROLLBARS_INSIDE_INSET,
            SCROLLBARS_OUTSIDE_OVERLAY,
            SCROLLBARS_OUTSIDE_INSET
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ScrollBarStyle {}
    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
    static final int SCROLLBARS_INSET_MASK = 0x01000000;
    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
    public static final int KEEP_SCREEN_ON = 0x04000000;
    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
    static final int PARENT_SAVE_DISABLED = 0x20000000;
    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
    private static Paint sDebugPaint;
    static final int TOOLTIP = 0x40000000;
    @IntDef(prefix = { "CONTENT_SENSITIVITY_" }, value = {
            CONTENT_SENSITIVITY_AUTO,
            CONTENT_SENSITIVITY_SENSITIVE,
            CONTENT_SENSITIVITY_NOT_SENSITIVE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ContentSensitivity {}
    @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
    public static final int CONTENT_SENSITIVITY_AUTO = 0x0;
    @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
    public static final int CONTENT_SENSITIVITY_SENSITIVE = 0x1;
    @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
    public static final int CONTENT_SENSITIVITY_NOT_SENSITIVE = 0x2;
    @IntDef(flag = true, prefix = { "FOCUSABLES_" }, value = {
            FOCUSABLES_ALL,
            FOCUSABLES_TOUCH_MODE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface FocusableMode {}
    public static final int FOCUSABLES_ALL = 0x00000000;
    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
    @IntDef(prefix = { "FOCUS_" }, value = {
            FOCUS_BACKWARD,
            FOCUS_FORWARD,
            FOCUS_LEFT,
            FOCUS_UP,
            FOCUS_RIGHT,
            FOCUS_DOWN
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface FocusDirection {}
    @IntDef(prefix = { "FOCUS_" }, value = {
            FOCUS_LEFT,
            FOCUS_UP,
            FOCUS_RIGHT,
            FOCUS_DOWN
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface FocusRealDirection {}
    public static final int FOCUS_BACKWARD = 0x00000001;
    public static final int FOCUS_FORWARD = 0x00000002;
    public static final int FOCUS_LEFT = 0x00000011;
    public static final int FOCUS_UP = 0x00000021;
    public static final int FOCUS_RIGHT = 0x00000042;
    public static final int FOCUS_DOWN = 0x00000082;
    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
    public static final int MEASURED_STATE_MASK = 0xff000000;
    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
    protected static final int[] EMPTY_STATE_SET;
    protected static final int[] ENABLED_STATE_SET;
    protected static final int[] FOCUSED_STATE_SET;
    protected static final int[] SELECTED_STATE_SET;
    protected static final int[] PRESSED_STATE_SET;
    protected static final int[] WINDOW_FOCUSED_STATE_SET;
    protected static final int[] ENABLED_FOCUSED_STATE_SET;
    protected static final int[] ENABLED_SELECTED_STATE_SET;
    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
    protected static final int[] FOCUSED_SELECTED_STATE_SET;
    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
    protected static final int[] PRESSED_SELECTED_STATE_SET;
    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
    protected static final int[] PRESSED_FOCUSED_STATE_SET;
    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
    protected static final int[] PRESSED_ENABLED_STATE_SET;
    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
    public static final int FRAME_RATE_CATEGORY_REASON_UNKNOWN = 0x0000_0000;
    public static final int FRAME_RATE_CATEGORY_REASON_SMALL = 0x0100_0000;
    public static final int FRAME_RATE_CATEGORY_REASON_INTERMITTENT = 0x0200_0000;
    public static final int FRAME_RATE_CATEGORY_REASON_LARGE = 0x03000000;
    public static final int FRAME_RATE_CATEGORY_REASON_REQUESTED = 0x0400_0000;
    public static final int FRAME_RATE_CATEGORY_REASON_INVALID = 0x0500_0000;
    public static final int FRAME_RATE_CATEGORY_REASON_VELOCITY = 0x0600_0000;
    public static final int FRAME_RATE_CATEGORY_REASON_BOOST = 0x0800_0000;
    public static final int FRAME_RATE_CATEGORY_REASON_TOUCH = 0x0900_0000;
    public static final int FRAME_RATE_CATEGORY_REASON_CONFLICTED = 0x0A00_0000;
    private static final int FRAME_RATE_CATEGORY_REASON_MASK = 0xFFFF_0000;
    protected static boolean sToolkitSetFrameRateReadOnlyFlagValue;
    private static boolean sToolkitMetricsForFrameRateDecisionFlagValue;
    private static final boolean sToolkitFrameRateDefaultNormalReadOnlyFlagValue =
            toolkitFrameRateDefaultNormalReadOnly();
    private static final boolean sToolkitFrameRateBySizeReadOnlyFlagValue =
            toolkitFrameRateBySizeReadOnly();
    private static final boolean sToolkitFrameRateSmallUsesPercentReadOnlyFlagValue =
            toolkitFrameRateSmallUsesPercentReadOnly();
    private static final boolean sToolkitFrameRateViewEnablingReadOnlyFlagValue =
            toolkitFrameRateViewEnablingReadOnly();
    private static boolean sToolkitFrameRateVelocityMappingReadOnlyFlagValue =
            toolkitFrameRateVelocityMappingReadOnly();
    @Surface.FrameRateCompatibility int mFrameRateCompatibility =
            FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
    static {
        EMPTY_STATE_SET = StateSet.get(0);
        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
        FOCUSED_SELECTED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
                        | StateSet.VIEW_STATE_FOCUSED);
        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
        ENABLED_SELECTED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
                        | StateSet.VIEW_STATE_ENABLED);
        ENABLED_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
                        | StateSet.VIEW_STATE_ENABLED);
        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
                        | StateSet.VIEW_STATE_ENABLED);
        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
        PRESSED_SELECTED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
                        | StateSet.VIEW_STATE_PRESSED);
        PRESSED_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
                        | StateSet.VIEW_STATE_PRESSED);
        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
                        | StateSet.VIEW_STATE_PRESSED);
        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
        PRESSED_ENABLED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
                        | StateSet.VIEW_STATE_PRESSED);
        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
                        | StateSet.VIEW_STATE_PRESSED);
        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
                        | StateSet.VIEW_STATE_PRESSED);
        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
                        | StateSet.VIEW_STATE_PRESSED);
        sToolkitSetFrameRateReadOnlyFlagValue = toolkitSetFrameRateReadOnly();
        sToolkitMetricsForFrameRateDecisionFlagValue = toolkitMetricsForFrameRateDecision();
        sUseMeasureCacheDuringForceLayoutFlagValue = enableUseMeasureCacheDuringForceLayout();
    }
    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
            AccessibilityEvent.TYPE_VIEW_CLICKED
            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
            | AccessibilityEvent.TYPE_VIEW_SELECTED
            | AccessibilityEvent.TYPE_VIEW_FOCUSED
            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
    static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
    static final int DEBUG_CORNERS_SIZE_DIP = 8;
    static final ThreadLocal<Rect> sThreadLocal = ThreadLocal.withInitial(Rect::new);
    @UnsupportedAppUsage
    private SparseArray<Object> mKeyedTags;
    private static int sNextAccessibilityViewId;
    protected Animation mCurrentAnimation = null;
    @ViewDebug.ExportedProperty(category = "measurement")
    @UnsupportedAppUsage
    int mMeasuredWidth;
    @ViewDebug.ExportedProperty(category = "measurement")
    @UnsupportedAppUsage
    int mMeasuredHeight;
    @UnsupportedAppUsage
    boolean mRecreateDisplayList = false;
    @IdRes
    @ViewDebug.ExportedProperty(resolveId = true)
    int mID = NO_ID;
    private int mAutofillViewId = NO_ID;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private int mAccessibilityViewId = NO_ID;
    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    protected Object mTag = null;
    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
    static final int PFLAG_FOCUSED                     = 0x00000002;
    static final int PFLAG_SELECTED                    = 0x00000004;
    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
    static final int PFLAG_DRAWN                       = 0x00000020;
    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
    private static final int PFLAG_PRESSED             = 0x00004000;
    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
    static final int PFLAG_ALPHA_SET                   = 0x00040000;
    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
    static final int PFLAG_DIRTY                       = 0x00200000;
    static final int PFLAG_DIRTY_MASK                  = 0x00200000;
    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
    private static final int PFLAG_PREPRESSED          = 0x02000000;
    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
    private static final int PFLAG_HOVERED             = 0x10000000;
    private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000;
    static final int PFLAG_ACTIVATED                   = 0x40000000;
    static final int PFLAG_INVALIDATED                 = 0x80000000;
    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
    @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
            LAYOUT_DIRECTION_LTR,
            LAYOUT_DIRECTION_RTL,
            LAYOUT_DIRECTION_INHERIT,
            LAYOUT_DIRECTION_LOCALE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface LayoutDir {}
    @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
            LAYOUT_DIRECTION_LTR,
            LAYOUT_DIRECTION_RTL
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ResolvedLayoutDir {}
    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
    private static final int[] LAYOUT_DIRECTION_FLAGS = {
            LAYOUT_DIRECTION_LTR,
            LAYOUT_DIRECTION_RTL,
            LAYOUT_DIRECTION_INHERIT,
            LAYOUT_DIRECTION_LOCALE
    };
    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
    public static final int TEXT_DIRECTION_INHERIT = 0;
    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
    public static final int TEXT_DIRECTION_ANY_RTL = 2;
    public static final int TEXT_DIRECTION_LTR = 3;
    public static final int TEXT_DIRECTION_RTL = 4;
    public static final int TEXT_DIRECTION_LOCALE = 5;
    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
    };
    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
    @IntDef(prefix = { "TEXT_ALIGNMENT_" }, value = {
            TEXT_ALIGNMENT_INHERIT,
            TEXT_ALIGNMENT_GRAVITY,
            TEXT_ALIGNMENT_CENTER,
            TEXT_ALIGNMENT_TEXT_START,
            TEXT_ALIGNMENT_TEXT_END,
            TEXT_ALIGNMENT_VIEW_START,
            TEXT_ALIGNMENT_VIEW_END
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface TextAlignment {}
    public static final int TEXT_ALIGNMENT_INHERIT = 0;
    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
    public static final int TEXT_ALIGNMENT_CENTER = 4;
    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
    };
    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
    public static final int ACCESSIBILITY_DATA_SENSITIVE_AUTO = 0x00000000;
    public static final int ACCESSIBILITY_DATA_SENSITIVE_YES = 0x00000001;
    public static final int ACCESSIBILITY_DATA_SENSITIVE_NO = 0x00000002;
    @IntDef(prefix = { "ACCESSIBILITY_DATA_SENSITIVE_" }, value = {
            ACCESSIBILITY_DATA_SENSITIVE_AUTO,
            ACCESSIBILITY_DATA_SENSITIVE_YES,
            ACCESSIBILITY_DATA_SENSITIVE_NO,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface AccessibilityDataSensitive {}
    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
            PFLAG2_TEXT_DIRECTION_RESOLVED |
            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
            PFLAG2_PADDING_RESOLVED |
            PFLAG2_DRAWABLE_RESOLVED;
    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
    static final int PFLAG3_IS_LAID_OUT = 0x4;
    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
    static final int PFLAG3_CALLED_SUPER = 0x10;
    static final int PFLAG3_APPLYING_INSETS = 0x20;
    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
    static final int SCROLL_INDICATORS_NONE = 0x0000;
    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
            | PFLAG3_SCROLL_INDICATOR_END;
    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true, prefix = { "SCROLL_INDICATOR_" }, value = {
            SCROLL_INDICATOR_TOP,
            SCROLL_INDICATOR_BOTTOM,
            SCROLL_INDICATOR_LEFT,
            SCROLL_INDICATOR_RIGHT,
            SCROLL_INDICATOR_START,
            SCROLL_INDICATOR_END,
    })
    public @interface ScrollIndicators {}
    public static final int SCROLL_INDICATOR_TOP =
            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
    public static final int SCROLL_INDICATOR_BOTTOM =
            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
    public static final int SCROLL_INDICATOR_LEFT =
            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
    public static final int SCROLL_INDICATOR_RIGHT =
            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
    public static final int SCROLL_INDICATOR_START =
            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
    public static final int SCROLL_INDICATOR_END =
            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
    private static final int PFLAG3_CLUSTER = 0x8000;
    private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
    private static final int PFLAG3_FINGER_DOWN = 0x20000;
    private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
            | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
            | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
            | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
            << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
    static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
    private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000;
    private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000;
    private static final int PFLAG3_AUTOFILLID_EXPLICITLY_SET = 0x40000000;
    private static final int PFLAG3_ACCESSIBILITY_HEADING = 0x80000000;
    private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
            IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
            | IMPORTANT_FOR_CONTENT_CAPTURE_NO
            | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
            | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
    private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10;
    private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20;
    private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED = 0x40;
    private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE = 0x80;
    private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK =
            PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
            | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
    static final int PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS = 0x000000100;
    private static final int PFLAG4_AUTOFILL_HIDE_HIGHLIGHT = 0x200;
    static final int PFLAG4_SCROLL_CAPTURE_HINT_SHIFT = 10;
    static final int PFLAG4_SCROLL_CAPTURE_HINT_MASK = (SCROLL_CAPTURE_HINT_INCLUDE
            | SCROLL_CAPTURE_HINT_EXCLUDE | SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS)
            << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
    private static final int PFLAG4_ALLOW_CLICK_WHEN_DISABLED = 0x000001000;
    private static final int PFLAG4_DETACHED = 0x000002000;
    private static final int PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE = 0x000004000;
    private static final int PFLAG4_DRAG_A11Y_STARTED = 0x000008000;
    private static final int PFLAG4_AUTO_HANDWRITING_ENABLED = 0x000010000;
    private static final int PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER = 0x000020000;
    private static final int PFLAG4_TRAVERSAL_TRACING_ENABLED = 0x000040000;
    private static final int PFLAG4_RELAYOUT_TRACING_ENABLED = 0x000080000;
    private static final int PFLAG4_ROTARY_HAPTICS_DETERMINED = 0x100000;
    private static final int PFLAG4_ROTARY_HAPTICS_ENABLED = 0x200000;
    private static final int PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT = 0x400000;
    private static final int PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT = 0x800000;
    private static final int PFLAG4_CONTENT_SENSITIVITY_SHIFT = 24;
    private static final int PFLAG4_CONTENT_SENSITIVITY_MASK =
            (CONTENT_SENSITIVITY_AUTO | CONTENT_SENSITIVITY_SENSITIVE
                    | CONTENT_SENSITIVITY_NOT_SENSITIVE) << PFLAG4_CONTENT_SENSITIVITY_SHIFT;
    private static final int PFLAG4_IS_COUNTED_AS_SENSITIVE = 0x4000000;
    private static final int PFLAG4_HAS_DRAWN = 0x8000000;
    private static final int PFLAG4_HAS_MOVED = 0x10000000;
    private static final int PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION = 0x20000000;
    protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
    protected  static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
    protected  static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
    @IntDef(flag = true, prefix = { "VIEW_STRUCTURE_FOR" }, value = {
            VIEW_STRUCTURE_FOR_ASSIST,
            VIEW_STRUCTURE_FOR_AUTOFILL,
            VIEW_STRUCTURE_FOR_CONTENT_CAPTURE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ViewStructureType {}
    public static final int OVER_SCROLL_ALWAYS = 0;
    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
    public static final int OVER_SCROLL_NEVER = 2;
    @Deprecated
    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
    @Deprecated
    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
    @Deprecated
    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
    @Deprecated
    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
    @Deprecated
    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
    @Deprecated
    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
    @Deprecated
    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
    @Deprecated
    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
    @Deprecated
    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
    @Deprecated
    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
    @Deprecated
    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
    @Deprecated
    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
    @UnsupportedAppUsage
    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
    @UnsupportedAppUsage
    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
    @UnsupportedAppUsage
    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
    public static final int STATUS_BAR_DISABLE_ONGOING_CALL_CHIP = 0x04000000;
    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
            | SYSTEM_UI_FLAG_FULLSCREEN;
    @Deprecated
    public static final int SYSTEM_UI_LAYOUT_FLAGS =
            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
    @IntDef(flag = true, prefix = { "FIND_VIEWS_" }, value = {
            FIND_VIEWS_WITH_TEXT,
            FIND_VIEWS_WITH_CONTENT_DESCRIPTION
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface FindViewFlags {}
    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
    public static final int SCREEN_STATE_OFF = 0x0;
    public static final int SCREEN_STATE_ON = 0x1;
    public static final int SCROLL_AXIS_NONE = 0;
    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
    private int mOverScrollMode;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    protected ViewParent mParent;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    AttachInfo mAttachInfo;
    @ViewDebug.ExportedProperty(flagMapping = {
        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
                name = "FORCE_LAYOUT"),
        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
                name = "LAYOUT_REQUIRED"),
        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
            name = "DRAWING_CACHE_INVALID", outputIf = false),
        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
    }, formatToHexString = true)
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769414)
    public int mPrivateFlags;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768943)
    int mPrivateFlags2;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
    int mPrivateFlags3;
    private int mPrivateFlags4;
    @ViewDebug.ExportedProperty(flagMapping = {
            @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
                    equals = SYSTEM_UI_FLAG_LOW_PROFILE,
                    name = "LOW_PROFILE"),
            @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
                    equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
                    name = "HIDE_NAVIGATION"),
            @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
                    equals = SYSTEM_UI_FLAG_FULLSCREEN,
                    name = "FULLSCREEN"),
            @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
                    equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
                    name = "LAYOUT_STABLE"),
            @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
                    equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
                    name = "LAYOUT_HIDE_NAVIGATION"),
            @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
                    equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
                    name = "LAYOUT_FULLSCREEN"),
            @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
                    equals = SYSTEM_UI_FLAG_IMMERSIVE,
                    name = "IMMERSIVE"),
            @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
                    equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
                    name = "IMMERSIVE_STICKY"),
            @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
                    equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
                    name = "LIGHT_STATUS_BAR"),
            @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
                    equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
                    name = "LIGHT_NAVIGATION_BAR"),
            @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
                    equals = STATUS_BAR_DISABLE_EXPAND,
                    name = "STATUS_BAR_DISABLE_EXPAND"),
            @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
                    equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
                    name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
            @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
                    equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
                    name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
            @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
                    equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
                    name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
            @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
                    equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
                    name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
            @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
                    equals = STATUS_BAR_DISABLE_HOME,
                    name = "STATUS_BAR_DISABLE_HOME"),
            @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
                    equals = STATUS_BAR_DISABLE_BACK,
                    name = "STATUS_BAR_DISABLE_BACK"),
            @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
                    equals = STATUS_BAR_DISABLE_CLOCK,
                    name = "STATUS_BAR_DISABLE_CLOCK"),
            @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
                    equals = STATUS_BAR_DISABLE_RECENT,
                    name = "STATUS_BAR_DISABLE_RECENT"),
            @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
                    equals = STATUS_BAR_DISABLE_SEARCH,
                    name = "STATUS_BAR_DISABLE_SEARCH"),
            @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
                    equals = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
                    name = "STATUS_BAR_DISABLE_ONGOING_CALL_CHIP")
    }, formatToHexString = true)
    @SystemUiVisibility
    int mSystemUiVisibility;
    @IntDef(flag = true, prefix = "", value = {
            SYSTEM_UI_FLAG_LOW_PROFILE,
            SYSTEM_UI_FLAG_HIDE_NAVIGATION,
            SYSTEM_UI_FLAG_FULLSCREEN,
            SYSTEM_UI_FLAG_LAYOUT_STABLE,
            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
            SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
            SYSTEM_UI_FLAG_IMMERSIVE,
            SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
            SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
            SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
            STATUS_BAR_DISABLE_EXPAND,
            STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
            STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
            STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
            STATUS_BAR_DISABLE_SYSTEM_INFO,
            STATUS_BAR_DISABLE_HOME,
            STATUS_BAR_DISABLE_BACK,
            STATUS_BAR_DISABLE_CLOCK,
            STATUS_BAR_DISABLE_RECENT,
            STATUS_BAR_DISABLE_SEARCH,
            STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface SystemUiVisibility {}
    int mTransientStateCount = 0;
    int mWindowAttachCount;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    protected ViewGroup.LayoutParams mLayoutParams;
    @ViewDebug.ExportedProperty(formatToHexString = true)
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    int mViewFlags;
    static class TransformationInfo {
        private final Matrix mMatrix = new Matrix();
        private Matrix mInverseMatrix;
        @ViewDebug.ExportedProperty
        private float mAlpha = 1f;
        float mTransitionAlpha = 1f;
    }
    @UnsupportedAppUsage
    public TransformationInfo mTransformationInfo;
    @ViewDebug.ExportedProperty(category = "drawing")
    Rect mClipBounds = null;
    private boolean mLastIsOpaque;
    @ViewDebug.ExportedProperty(category = "layout")
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    protected int mLeft;
    private int mLastFrameLeft;
    @ViewDebug.ExportedProperty(category = "layout")
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    protected int mRight;
    @ViewDebug.ExportedProperty(category = "layout")
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    protected int mTop;
    private int mLastFrameTop;
    @ViewDebug.ExportedProperty(category = "layout")
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    protected int mBottom;
    @ViewDebug.ExportedProperty(category = "scrolling")
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    protected int mScrollX;
    @ViewDebug.ExportedProperty(category = "scrolling")
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    protected int mScrollY;
    @ViewDebug.ExportedProperty(category = "padding")
    @UnsupportedAppUsage
    protected int mPaddingLeft = 0;
    @ViewDebug.ExportedProperty(category = "padding")
    @UnsupportedAppUsage
    protected int mPaddingRight = 0;
    @ViewDebug.ExportedProperty(category = "padding")
    @UnsupportedAppUsage
    protected int mPaddingTop;
    @ViewDebug.ExportedProperty(category = "padding")
    @UnsupportedAppUsage
    protected int mPaddingBottom;
    private float mHandwritingBoundsOffsetLeft;
    private float mHandwritingBoundsOffsetTop;
    private float mHandwritingBoundsOffsetRight;
    private float mHandwritingBoundsOffsetBottom;
    private Insets mLayoutInsets;
    private CharSequence mStateDescription;
    private CharSequence mContentDescription;
    private CharSequence mAccessibilityPaneTitle;
    private int mExplicitAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_AUTO;
    private int mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_AUTO;
    private int mLabelForId = View.NO_ID;
    private MatchLabelForPredicate mMatchLabelForPredicate;
    private int mAccessibilityTraversalBeforeId = NO_ID;
    private int mAccessibilityTraversalAfterId = NO_ID;
    private MatchIdPredicate mMatchIdPredicate;
    @ViewDebug.ExportedProperty(category = "padding")
    protected int mUserPaddingRight;
    @ViewDebug.ExportedProperty(category = "padding")
    protected int mUserPaddingBottom;
    @ViewDebug.ExportedProperty(category = "padding")
    protected int mUserPaddingLeft;
    @ViewDebug.ExportedProperty(category = "padding")
    int mUserPaddingStart;
    @ViewDebug.ExportedProperty(category = "padding")
    int mUserPaddingEnd;
    int mUserPaddingLeftInitial;
    int mUserPaddingRightInitial;
    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
    private boolean mLeftPaddingDefined = false;
    private boolean mRightPaddingDefined = false;
    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
    private LongSparseLongArray mMeasureCache;
    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private Drawable mBackground;
    private TintInfo mBackgroundTint;
    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
    private ForegroundInfo mForegroundInfo;
    private Drawable mScrollIndicatorDrawable;
    RenderNode mBackgroundRenderNode;
    @UnsupportedAppUsage
    private int mBackgroundResource;
    private boolean mBackgroundSizeChanged;
    private Drawable mDefaultFocusHighlight;
    private Drawable mDefaultFocusHighlightCache;
    private boolean mDefaultFocusHighlightSizeChanged;
    private static boolean sUseDefaultFocusHighlight;
    private static boolean sCanFocusZeroSized;
    private static boolean sAlwaysAssignFocus;
    private String mTransitionName;
    static class TintInfo {
        ColorStateList mTintList;
        BlendMode mBlendMode;
        boolean mHasTintMode;
        boolean mHasTintList;
    }
    private static class ForegroundInfo {
        private Drawable mDrawable;
        private TintInfo mTintInfo;
        private int mGravity = Gravity.FILL;
        private boolean mInsidePadding = true;
        private boolean mBoundsChanged = true;
        private final Rect mSelfBounds = new Rect();
        private final Rect mOverlayBounds = new Rect();
    }
    static class ListenerInfo {
        @UnsupportedAppUsage
        ListenerInfo() {
        }
        @UnsupportedAppUsage
        protected OnFocusChangeListener mOnFocusChangeListener;
        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
        protected OnScrollChangeListener mOnScrollChangeListener;
        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
        @UnsupportedAppUsage
        public OnClickListener mOnClickListener;
        @UnsupportedAppUsage
        protected OnLongClickListener mOnLongClickListener;
        protected OnContextClickListener mOnContextClickListener;
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
        @UnsupportedAppUsage
        private OnKeyListener mOnKeyListener;
        @UnsupportedAppUsage
        private OnTouchListener mOnTouchListener;
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        private OnHoverListener mOnHoverListener;
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        private OnGenericMotionListener mOnGenericMotionListener;
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        private OnDragListener mOnDragListener;
        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
        OnCapturedPointerListener mOnCapturedPointerListener;
        private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
        WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback;
        private List<Rect> mSystemGestureExclusionRects = null;
        private List<Rect> mKeepClearRects = null;
        private List<Rect> mUnrestrictedKeepClearRects = null;
        private boolean mPreferKeepClear = false;
        private Rect mHandwritingArea = null;
        public RenderNode.PositionUpdateListener mPositionUpdateListener;
        private Runnable mPositionChangedUpdate;
        ScrollCaptureCallback mScrollCaptureCallback;
        @Nullable
        private OnReceiveContentListener mOnReceiveContentListener;
    }
    @UnsupportedAppUsage
    ListenerInfo mListenerInfo;
    private static class TooltipInfo {
        @Nullable
        CharSequence mTooltipText;
        int mAnchorX;
        int mAnchorY;
        @Nullable
        TooltipPopup mTooltipPopup;
        boolean mTooltipFromLongClick;
        Runnable mShowTooltipRunnable;
        Runnable mHideTooltipRunnable;
        int mHoverSlop;
        private boolean updateAnchorPos(MotionEvent event) {
            final int newAnchorX = (int) event.getX();
            final int newAnchorY = (int) event.getY();
            if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop
                    && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) {
                return false;
            }
            mAnchorX = newAnchorX;
            mAnchorY = newAnchorY;
            return true;
        }
        private void clearAnchorPos() {
            mAnchorX = Integer.MAX_VALUE;
            mAnchorY = Integer.MAX_VALUE;
        }
    }
    TooltipInfo mTooltipInfo;
    private float mLongClickX = Float.NaN;
    private float mLongClickY = Float.NaN;
    @ViewDebug.ExportedProperty(deepExport = true)
    @UnsupportedAppUsage
    @UiContext
    protected Context mContext;
    @UnsupportedAppUsage
    private final Resources mResources;
    @UnsupportedAppUsage
    private ScrollabilityCache mScrollCache;
    private int[] mDrawableState = null;
    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
    private StateListAnimator mStateListAnimator;
    private int mNextFocusLeftId = View.NO_ID;
    private int mNextFocusRightId = View.NO_ID;
    private int mNextFocusUpId = View.NO_ID;
    private int mNextFocusDownId = View.NO_ID;
    int mNextFocusForwardId = View.NO_ID;
    int mNextClusterForwardId = View.NO_ID;
    boolean mDefaultFocusHighlightEnabled = true;
    private CheckForLongPress mPendingCheckForLongPress;
    @UnsupportedAppUsage
    private CheckForTap mPendingCheckForTap = null;
    private PerformClick mPerformClick;
    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
    private SendAccessibilityEventThrottle mSendStateChangedAccessibilityEvent;
    private UnsetPressedState mUnsetPressedState;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    private boolean mHasPerformedLongPress;
    private boolean mInContextButtonPress;
    private boolean mIgnoreNextUpEvent;
    @ViewDebug.ExportedProperty(category = "measurement")
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    private int mMinHeight;
    @ViewDebug.ExportedProperty(category = "measurement")
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    private int mMinWidth;
    private TouchDelegate mTouchDelegate = null;
    private boolean mHoveringTouchDelegate = false;
    private Runnable mHandwritingDelegatorCallback;
    private String mAllowedHandwritingDelegatePackageName;
    private boolean mIsHandwritingDelegate;
    private String mAllowedHandwritingDelegatorPackageName;
    private @InputMethodManager.HandwritingDelegateFlags int mHandwritingDelegateFlags;
    private int mDrawingCacheBackgroundColor = 0;
    private ViewTreeObserver mFloatingTreeObserver;
    private int mTouchSlop;
    private float mAmbiguousGestureMultiplier;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    private ViewPropertyAnimator mAnimator = null;
    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
    public static final int DRAG_FLAG_GLOBAL = 1 << 8;
    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
    public static final int DRAG_FLAG_ACCESSIBILITY_ACTION = 1 << 10;
    public static final int DRAG_FLAG_REQUEST_SURFACE_FOR_RETURN_ANIMATION = 1 << 11;
    @FlaggedApi(FLAG_DELEGATE_UNHANDLED_DRAGS)
    public static final int DRAG_FLAG_GLOBAL_SAME_APPLICATION = 1 << 12;
    @FlaggedApi(FLAG_DELEGATE_UNHANDLED_DRAGS)
    public static final int DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG = 1 << 13;
    private float mVerticalScrollFactor;
    @UnsupportedAppUsage
    private int mVerticalScrollbarPosition;
    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
    public static final int SCROLLBAR_POSITION_LEFT = 1;
    public static final int SCROLLBAR_POSITION_RIGHT = 2;
    public static final int LAYER_TYPE_NONE = 0;
    public static final int LAYER_TYPE_SOFTWARE = 1;
    public static final int LAYER_TYPE_HARDWARE = 2;
    @IntDef(prefix = { "LAYER_TYPE_" }, value = {
            LAYER_TYPE_NONE,
            LAYER_TYPE_SOFTWARE,
            LAYER_TYPE_HARDWARE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface LayerType {}
    int mLayerType = LAYER_TYPE_NONE;
    Paint mLayerPaint;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public boolean mCachingFailed;
    @UnsupportedAppUsage
    private Bitmap mDrawingCache;
    @UnsupportedAppUsage
    private Bitmap mUnscaledDrawingCache;
    @UnsupportedAppUsage
    final RenderNode mRenderNode;
    private boolean mSendingHoverAccessibilityEvents;
    @UnsupportedAppUsage
    AccessibilityDelegate mAccessibilityDelegate;
    ViewOverlay mOverlay;
    private ViewParent mNestedScrollingParent;
    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
                    new InputEventConsistencyVerifier(this, 0) : null;
    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
    private int[] mTempNestedScrollConsumed;
    GhostView mGhostView;
    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
    public String[] mAttributes;
    private static SparseArray<String> mAttributeMap;
    private HandlerActionQueue mRunQueue;
    private PointerIcon mMousePointerIcon;
    private Vibrator mVibrator;
    @UnsupportedAppUsage
    String mStartActivityRequestWho;
    @Nullable
    private RoundScrollbarRenderer mRoundScrollbarRenderer;
    private Handler mVisibilityChangeForAutofillHandler;
    @Nullable
    private ContentCaptureSession mContentCaptureSession;
    private boolean mContentCaptureSessionCached;
    @LayoutRes
    private int mSourceLayoutId = ID_NULL;
    @Nullable
    private SparseIntArray mAttributeSourceResId;
    @Nullable
    private SparseArray<int[]> mAttributeResolutionStacks;
    @StyleRes
    private int mExplicitStyle;
    @InputSourceClass
    int mUnbufferedInputSource = InputDevice.SOURCE_CLASS_NONE;
    @Nullable
    private String[] mReceiveContentMimeTypes;
    @Nullable
    private ViewTranslationCallback mViewTranslationCallback;
    private float mFrameContentVelocity = -1;
    @Nullable
    private ViewTranslationResponse mViewTranslationResponse;
    private static final float FRAME_RATE_SQUARE_SMALL_SIZE_DP = 40f;
    private static final float FRAME_RATE_NARROW_SIZE_DP = 10f;
    private static final float FRAME_RATE_SIZE_PERCENTAGE_THRESHOLD = 0.07f;
    static final float MAX_FRAME_RATE = 120;
    private float mPreferredFrameRate = REQUESTED_FRAME_RATE_CATEGORY_DEFAULT;
    private int mLastFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
    @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
    public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = Float.NaN;
    @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
    public static final float REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE = -1;
    @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
    public static final float REQUESTED_FRAME_RATE_CATEGORY_LOW = -2;
    @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
    public static final float REQUESTED_FRAME_RATE_CATEGORY_NORMAL = -3;
    @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
    public static final float REQUESTED_FRAME_RATE_CATEGORY_HIGH = -4;
    private int mSizeBasedFrameRateCategoryAndReason;
    public View(Context context) {
        mContext = context;
        mResources = context != null ? context.getResources() : null;
        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
        mPrivateFlags2 =
                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
        final ViewConfiguration configuration = ViewConfiguration.get(context);
        mTouchSlop = configuration.getScaledTouchSlop();
        mAmbiguousGestureMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
        mUserPaddingStart = UNDEFINED_PADDING;
        mUserPaddingEnd = UNDEFINED_PADDING;
        mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
        if (!sCompatibilityDone && context != null) {
            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
            sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
            sPreserveMarginParamsInLayoutParamConversion =
                    targetSdkVersion >= Build.VERSION_CODES.N;
            sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
            sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
            sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
            sUseDefaultFocusHighlight = context.getResources().getBoolean(
                    com.android.internal.R.bool.config_useDefaultFocusHighlight);
            sThrowOnInvalidFloatProperties = targetSdkVersion >= Build.VERSION_CODES.P;
            sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
            sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
            sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
            sBrokenInsetsDispatch = targetSdkVersion < Build.VERSION_CODES.R;
            sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
            GradientDrawable.sWrapNegativeAngleMeasurements =
                    targetSdkVersion >= Build.VERSION_CODES.Q;
            sForceLayoutWhenInsetsChanged = targetSdkVersion < Build.VERSION_CODES.R;
            sCompatibilityDone = true;
        }
    }
    public View(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }
    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        this(context);
        mSourceLayoutId = Resources.getAttributeSetSourceResId(attrs);
        final TypedArray a = context.obtainStyledAttributes(
                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
        retrieveExplicitStyle(context.getTheme(), attrs);
        saveAttributeDataForStyleable(context, com.android.internal.R.styleable.View, attrs, a,
                defStyleAttr, defStyleRes);
        if (sDebugViewAttributes) {
            saveAttributeData(attrs, a);
        }
        Drawable background = null;
        int leftPadding = -1;
        int topPadding = -1;
        int rightPadding = -1;
        int bottomPadding = -1;
        int startPadding = UNDEFINED_PADDING;
        int endPadding = UNDEFINED_PADDING;
        int padding = -1;
        int paddingHorizontal = -1;
        int paddingVertical = -1;
        int viewFlagValues = 0;
        int viewFlagMasks = 0;
        boolean setScrollContainer = false;
        int x = 0;
        int y = 0;
        float tx = 0;
        float ty = 0;
        float tz = 0;
        float elevation = 0;
        float rotation = 0;
        float rotationX = 0;
        float rotationY = 0;
        float sx = 1f;
        float sy = 1f;
        boolean transformSet = false;
        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
        int overScrollMode = mOverScrollMode;
        boolean initializeScrollbars = false;
        boolean initializeScrollIndicators = false;
        boolean startPaddingDefined = false;
        boolean endPaddingDefined = false;
        boolean leftPaddingDefined = false;
        boolean rightPaddingDefined = false;
        viewFlagValues |= FOCUSABLE_AUTO;
        viewFlagMasks |= FOCUSABLE_AUTO;
        final int N = a.getIndexCount();
        for (int i = 0; i < N; i++) {
            int attr = a.getIndex(i);
            switch (attr) {
                case com.android.internal.R.styleable.View_background:
                    background = a.getDrawable(attr);
                    break;
                case com.android.internal.R.styleable.View_padding:
                    padding = a.getDimensionPixelSize(attr, -1);
                    mUserPaddingLeftInitial = padding;
                    mUserPaddingRightInitial = padding;
                    leftPaddingDefined = true;
                    rightPaddingDefined = true;
                    break;
                case com.android.internal.R.styleable.View_paddingHorizontal:
                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
                    mUserPaddingLeftInitial = paddingHorizontal;
                    mUserPaddingRightInitial = paddingHorizontal;
                    leftPaddingDefined = true;
                    rightPaddingDefined = true;
                    break;
                case com.android.internal.R.styleable.View_paddingVertical:
                    paddingVertical = a.getDimensionPixelSize(attr, -1);
                    break;
                case com.android.internal.R.styleable.View_paddingLeft:
                    leftPadding = a.getDimensionPixelSize(attr, -1);
                    mUserPaddingLeftInitial = leftPadding;
                    leftPaddingDefined = true;
                    break;
                case com.android.internal.R.styleable.View_paddingTop:
                    topPadding = a.getDimensionPixelSize(attr, -1);
                    break;
                case com.android.internal.R.styleable.View_paddingRight:
                    rightPadding = a.getDimensionPixelSize(attr, -1);
                    mUserPaddingRightInitial = rightPadding;
                    rightPaddingDefined = true;
                    break;
                case com.android.internal.R.styleable.View_paddingBottom:
                    bottomPadding = a.getDimensionPixelSize(attr, -1);
                    break;
                case com.android.internal.R.styleable.View_paddingStart:
                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
                    break;
                case com.android.internal.R.styleable.View_paddingEnd:
                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
                    break;
                case com.android.internal.R.styleable.View_scrollX:
                    x = a.getDimensionPixelOffset(attr, 0);
                    break;
                case com.android.internal.R.styleable.View_scrollY:
                    y = a.getDimensionPixelOffset(attr, 0);
                    break;
                case com.android.internal.R.styleable.View_alpha:
                    setAlpha(a.getFloat(attr, 1f));
                    break;
                case com.android.internal.R.styleable.View_transformPivotX:
                    setPivotX(a.getDimension(attr, 0));
                    break;
                case com.android.internal.R.styleable.View_transformPivotY:
                    setPivotY(a.getDimension(attr, 0));
                    break;
                case com.android.internal.R.styleable.View_translationX:
                    tx = a.getDimension(attr, 0);
                    transformSet = true;
                    break;
                case com.android.internal.R.styleable.View_translationY:
                    ty = a.getDimension(attr, 0);
                    transformSet = true;
                    break;
                case com.android.internal.R.styleable.View_translationZ:
                    tz = a.getDimension(attr, 0);
                    transformSet = true;
                    break;
                case com.android.internal.R.styleable.View_elevation:
                    elevation = a.getDimension(attr, 0);
                    transformSet = true;
                    break;
                case com.android.internal.R.styleable.View_rotation:
                    rotation = a.getFloat(attr, 0);
                    transformSet = true;
                    break;
                case com.android.internal.R.styleable.View_rotationX:
                    rotationX = a.getFloat(attr, 0);
                    transformSet = true;
                    break;
                case com.android.internal.R.styleable.View_rotationY:
                    rotationY = a.getFloat(attr, 0);
                    transformSet = true;
                    break;
                case com.android.internal.R.styleable.View_scaleX:
                    sx = a.getFloat(attr, 1f);
                    transformSet = true;
                    break;
                case com.android.internal.R.styleable.View_scaleY:
                    sy = a.getFloat(attr, 1f);
                    transformSet = true;
                    break;
                case com.android.internal.R.styleable.View_id:
                    mID = a.getResourceId(attr, NO_ID);
                    break;
                case com.android.internal.R.styleable.View_tag:
                    mTag = a.getText(attr);
                    break;
                case com.android.internal.R.styleable.View_fitsSystemWindows:
                    if (a.getBoolean(attr, false)) {
                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
                    }
                    break;
                case com.android.internal.R.styleable.View_focusable:
                    viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
                    if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
                        viewFlagMasks |= FOCUSABLE_MASK;
                    }
                    break;
                case com.android.internal.R.styleable.View_focusableInTouchMode:
                    if (a.getBoolean(attr, false)) {
                        viewFlagValues &= ~FOCUSABLE_AUTO;
                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
                    }
                    break;
                case com.android.internal.R.styleable.View_clickable:
                    if (a.getBoolean(attr, false)) {
                        viewFlagValues |= CLICKABLE;
                        viewFlagMasks |= CLICKABLE;
                    }
                    break;
                case com.android.internal.R.styleable.View_allowClickWhenDisabled:
                    setAllowClickWhenDisabled(a.getBoolean(attr, false));
                    break;
                case com.android.internal.R.styleable.View_longClickable:
                    if (a.getBoolean(attr, false)) {
                        viewFlagValues |= LONG_CLICKABLE;
                        viewFlagMasks |= LONG_CLICKABLE;
                    }
                    break;
                case com.android.internal.R.styleable.View_contextClickable:
                    if (a.getBoolean(attr, false)) {
                        viewFlagValues |= CONTEXT_CLICKABLE;
                        viewFlagMasks |= CONTEXT_CLICKABLE;
                    }
                    break;
                case com.android.internal.R.styleable.View_saveEnabled:
                    if (!a.getBoolean(attr, true)) {
                        viewFlagValues |= SAVE_DISABLED;
                        viewFlagMasks |= SAVE_DISABLED_MASK;
                    }
                    break;
                case com.android.internal.R.styleable.View_duplicateParentState:
                    if (a.getBoolean(attr, false)) {
                        viewFlagValues |= DUPLICATE_PARENT_STATE;
                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
                    }
                    break;
                case com.android.internal.R.styleable.View_visibility:
                    final int visibility = a.getInt(attr, 0);
                    if (visibility != 0) {
                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
                        viewFlagMasks |= VISIBILITY_MASK;
                    }
                    break;
                case com.android.internal.R.styleable.View_layoutDirection:
                    mPrivateFlags2 &=
                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
                    final int layoutDirection = a.getInt(attr, -1);
                    final int value = (layoutDirection != -1) ?
                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
                    break;
                case com.android.internal.R.styleable.View_drawingCacheQuality:
                    final int cacheQuality = a.getInt(attr, 0);
                    if (cacheQuality != 0) {
                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
                    }
                    break;
                case com.android.internal.R.styleable.View_contentDescription:
                    setContentDescription(a.getString(attr));
                    break;
                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
                    break;
                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
                    break;
                case com.android.internal.R.styleable.View_labelFor:
                    setLabelFor(a.getResourceId(attr, NO_ID));
                    break;
                case com.android.internal.R.styleable.View_soundEffectsEnabled:
                    if (!a.getBoolean(attr, true)) {
                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
                    }
                    break;
                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
                    if (!a.getBoolean(attr, true)) {
                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
                    }
                    break;
                case R.styleable.View_scrollbars:
                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
                    if (scrollbars != SCROLLBARS_NONE) {
                        viewFlagValues |= scrollbars;
                        viewFlagMasks |= SCROLLBARS_MASK;
                        initializeScrollbars = true;
                    }
                    break;
                case R.styleable.View_fadingEdge:
                    break;
                case R.styleable.View_requiresFadingEdge:
                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
                    if (fadingEdge != FADING_EDGE_NONE) {
                        viewFlagValues |= fadingEdge;
                        viewFlagMasks |= FADING_EDGE_MASK;
                        initializeFadingEdgeInternal(a);
                    }
                    break;
                case R.styleable.View_scrollbarStyle:
                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
                    }
                    break;
                case R.styleable.View_isScrollContainer:
                    setScrollContainer = true;
                    if (a.getBoolean(attr, false)) {
                        setScrollContainer(true);
                    }
                    break;
                case com.android.internal.R.styleable.View_keepScreenOn:
                    if (a.getBoolean(attr, false)) {
                        viewFlagValues |= KEEP_SCREEN_ON;
                        viewFlagMasks |= KEEP_SCREEN_ON;
                    }
                    break;
                case R.styleable.View_filterTouchesWhenObscured:
                    if (a.getBoolean(attr, false)) {
                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
                    }
                    break;
                case R.styleable.View_nextFocusLeft:
                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
                    break;
                case R.styleable.View_nextFocusRight:
                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
                    break;
                case R.styleable.View_nextFocusUp:
                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
                    break;
                case R.styleable.View_nextFocusDown:
                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
                    break;
                case R.styleable.View_nextFocusForward:
                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
                    break;
                case R.styleable.View_nextClusterForward:
                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
                    break;
                case R.styleable.View_minWidth:
                    mMinWidth = a.getDimensionPixelSize(attr, 0);
                    break;
                case R.styleable.View_minHeight:
                    mMinHeight = a.getDimensionPixelSize(attr, 0);
                    break;
                case R.styleable.View_onClick:
                    if (context.isRestricted()) {
                        throw new IllegalStateException("The android:onClick attribute cannot "
                                + "be used within a restricted context");
                    }
                    final String handlerName = a.getString(attr);
                    if (handlerName != null) {
                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
                    }
                    break;
                case R.styleable.View_overScrollMode:
                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
                    break;
                case R.styleable.View_verticalScrollbarPosition:
                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
                    break;
                case R.styleable.View_layerType:
                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
                    break;
                case R.styleable.View_textDirection:
                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
                    final int textDirection = a.getInt(attr, -1);
                    if (textDirection != -1) {
                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
                    }
                    break;
                case R.styleable.View_textAlignment:
                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
                    break;
                case R.styleable.View_importantForAccessibility:
                    setImportantForAccessibility(a.getInt(attr,
                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
                    break;
                case R.styleable.View_accessibilityDataSensitive:
                    setAccessibilityDataSensitive(a.getInt(attr,
                            ACCESSIBILITY_DATA_SENSITIVE_AUTO));
                    break;
                case R.styleable.View_accessibilityLiveRegion:
                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
                    break;
                case R.styleable.View_transitionName:
                    setTransitionName(a.getString(attr));
                    break;
                case R.styleable.View_nestedScrollingEnabled:
                    setNestedScrollingEnabled(a.getBoolean(attr, false));
                    break;
                case R.styleable.View_stateListAnimator:
                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
                            a.getResourceId(attr, 0)));
                    break;
                case R.styleable.View_backgroundTint:
                    if (mBackgroundTint == null) {
                        mBackgroundTint = new TintInfo();
                    }
                    mBackgroundTint.mTintList = a.getColorStateList(
                            R.styleable.View_backgroundTint);
                    mBackgroundTint.mHasTintList = true;
                    break;
                case R.styleable.View_backgroundTintMode:
                    if (mBackgroundTint == null) {
                        mBackgroundTint = new TintInfo();
                    }
                    mBackgroundTint.mBlendMode = Drawable.parseBlendMode(a.getInt(
                            R.styleable.View_backgroundTintMode, -1), null);
                    mBackgroundTint.mHasTintMode = true;
                    break;
                case R.styleable.View_outlineProvider:
                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
                            PROVIDER_BACKGROUND));
                    break;
                case R.styleable.View_foreground:
                    setForeground(a.getDrawable(attr));
                    break;
                case R.styleable.View_foregroundGravity:
                    setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
                    break;
                case R.styleable.View_foregroundTintMode:
                    setForegroundTintBlendMode(
                            Drawable.parseBlendMode(a.getInt(attr, -1),
                                    null));
                    break;
                case R.styleable.View_foregroundTint:
                    setForegroundTintList(a.getColorStateList(attr));
                    break;
                case R.styleable.View_foregroundInsidePadding:
                    if (mForegroundInfo == null) {
                        mForegroundInfo = new ForegroundInfo();
                    }
                    mForegroundInfo.mInsidePadding = a.getBoolean(attr,
                            mForegroundInfo.mInsidePadding);
                    break;
                case R.styleable.View_scrollIndicators:
                    final int scrollIndicators =
                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
                                    & SCROLL_INDICATORS_PFLAG3_MASK;
                    if (scrollIndicators != 0) {
                        mPrivateFlags3 |= scrollIndicators;
                        initializeScrollIndicators = true;
                    }
                    break;
                case R.styleable.View_pointerIcon:
                    final int resourceId = a.getResourceId(attr, 0);
                    if (resourceId != 0) {
                        setPointerIcon(PointerIcon.load(
                                context.getResources(), resourceId));
                    } else {
                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
                        }
                    }
                    break;
                case R.styleable.View_forceHasOverlappingRendering:
                    if (a.peekValue(attr) != null) {
                        forceHasOverlappingRendering(a.getBoolean(attr, true));
                    }
                    break;
                case R.styleable.View_tooltipText:
                    setTooltipText(a.getText(attr));
                    break;
                case R.styleable.View_keyboardNavigationCluster:
                    if (a.peekValue(attr) != null) {
                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
                    }
                    break;
                case R.styleable.View_focusedByDefault:
                    if (a.peekValue(attr) != null) {
                        setFocusedByDefault(a.getBoolean(attr, true));
                    }
                    break;
                case R.styleable.View_autofillHints:
                    if (a.peekValue(attr) != null) {
                        CharSequence[] rawHints = null;
                        String rawString = null;
                        if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
                            int resId = a.getResourceId(attr, 0);
                            try {
                                rawHints = a.getTextArray(attr);
                            } catch (Resources.NotFoundException e) {
                                rawString = getResources().getString(resId);
                            }
                        } else {
                            rawString = a.getString(attr);
                        }
                        if (rawHints == null) {
                            if (rawString == null) {
                                throw new IllegalArgumentException(
                                        "Could not resolve autofillHints");
                            } else {
                                rawHints = rawString.split(",");
                            }
                        }
                        String[] hints = new String[rawHints.length];
                        int numHints = rawHints.length;
                        for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
                            hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
                        }
                        setAutofillHints(hints);
                    }
                    break;
                case R.styleable.View_importantForAutofill:
                    if (a.peekValue(attr) != null) {
                        setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
                    }
                    break;
                case R.styleable.View_importantForContentCapture:
                    if (a.peekValue(attr) != null) {
                        setImportantForContentCapture(a.getInt(attr,
                                IMPORTANT_FOR_CONTENT_CAPTURE_AUTO));
                    }
                    break;
                case R.styleable.View_isCredential:
                    if (a.peekValue(attr) != null) {
                        setIsCredential(a.getBoolean(attr, false));
                    }
                    break;
                case R.styleable.View_defaultFocusHighlightEnabled:
                    if (a.peekValue(attr) != null) {
                        setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
                    }
                    break;
                case R.styleable.View_screenReaderFocusable:
                    if (a.peekValue(attr) != null) {
                        setScreenReaderFocusable(a.getBoolean(attr, false));
                    }
                    break;
                case R.styleable.View_accessibilityPaneTitle:
                    if (a.peekValue(attr) != null) {
                        setAccessibilityPaneTitle(a.getString(attr));
                    }
                    break;
                case R.styleable.View_outlineSpotShadowColor:
                    setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
                    break;
                case R.styleable.View_outlineAmbientShadowColor:
                    setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
                    break;
                case com.android.internal.R.styleable.View_accessibilityHeading:
                    setAccessibilityHeading(a.getBoolean(attr, false));
                    break;
                case R.styleable.View_forceDarkAllowed:
                    mRenderNode.setForceDarkAllowed(a.getBoolean(attr, true));
                    break;
                case R.styleable.View_scrollCaptureHint:
                    setScrollCaptureHint((a.getInt(attr, SCROLL_CAPTURE_HINT_AUTO)));
                    break;
                case R.styleable.View_clipToOutline:
                    setClipToOutline(a.getBoolean(attr, false));
                    break;
                case R.styleable.View_preferKeepClear:
                    setPreferKeepClear(a.getBoolean(attr, false));
                    break;
                case R.styleable.View_autoHandwritingEnabled:
                    setAutoHandwritingEnabled(a.getBoolean(attr, false));
                    break;
                case R.styleable.View_handwritingBoundsOffsetLeft:
                    mHandwritingBoundsOffsetLeft = a.getDimension(attr, 0);
                    break;
                case R.styleable.View_handwritingBoundsOffsetTop:
                    mHandwritingBoundsOffsetTop = a.getDimension(attr, 0);
                    break;
                case R.styleable.View_handwritingBoundsOffsetRight:
                    mHandwritingBoundsOffsetRight = a.getDimension(attr, 0);
                    break;
                case R.styleable.View_handwritingBoundsOffsetBottom:
                    mHandwritingBoundsOffsetBottom = a.getDimension(attr, 0);
                    break;
                case R.styleable.View_contentSensitivity:
                    setContentSensitivity(a.getInt(attr, CONTENT_SENSITIVITY_AUTO));
                    break;
            }
        }
        setOverScrollMode(overScrollMode);
        mUserPaddingStart = startPadding;
        mUserPaddingEnd = endPadding;
        if (background != null) {
            setBackground(background);
        }
        mLeftPaddingDefined = leftPaddingDefined;
        mRightPaddingDefined = rightPaddingDefined;
        if (padding >= 0) {
            leftPadding = padding;
            topPadding = padding;
            rightPadding = padding;
            bottomPadding = padding;
            mUserPaddingLeftInitial = padding;
            mUserPaddingRightInitial = padding;
        } else {
            if (paddingHorizontal >= 0) {
                leftPadding = paddingHorizontal;
                rightPadding = paddingHorizontal;
                mUserPaddingLeftInitial = paddingHorizontal;
                mUserPaddingRightInitial = paddingHorizontal;
            }
            if (paddingVertical >= 0) {
                topPadding = paddingVertical;
                bottomPadding = paddingVertical;
            }
        }
        if (isRtlCompatibilityMode()) {
            if (!mLeftPaddingDefined && startPaddingDefined) {
                leftPadding = startPadding;
            }
            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
            if (!mRightPaddingDefined && endPaddingDefined) {
                rightPadding = endPadding;
            }
            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
        } else {
            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
            if (mLeftPaddingDefined && !hasRelativePadding) {
                mUserPaddingLeftInitial = leftPadding;
            }
            if (mRightPaddingDefined && !hasRelativePadding) {
                mUserPaddingRightInitial = rightPadding;
            }
        }
        internalSetPadding(
                mUserPaddingLeftInitial,
                topPadding >= 0 ? topPadding : mPaddingTop,
                mUserPaddingRightInitial,
                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
        if (viewFlagMasks != 0) {
            setFlags(viewFlagValues, viewFlagMasks);
        }
        if (initializeScrollbars) {
            initializeScrollbarsInternal(a);
        }
        if (initializeScrollIndicators) {
            initializeScrollIndicatorsInternal();
        }
        a.recycle();
        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
            recomputePadding();
        }
        if (x != 0 || y != 0) {
            scrollTo(x, y);
        }
        if (transformSet) {
            setTranslationX(tx);
            setTranslationY(ty);
            setTranslationZ(tz);
            setElevation(elevation);
            setRotation(rotation);
            setRotationX(rotationX);
            setRotationY(rotationY);
            setScaleX(sx);
            setScaleY(sy);
        }
        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
            setScrollContainer(true);
        }
        computeOpaqueFlags();
    }
    @NonNull
    public int[] getAttributeResolutionStack(@AttrRes int attribute) {
        if (!sDebugViewAttributes
                || mAttributeResolutionStacks == null
                || mAttributeResolutionStacks.get(attribute) == null) {
            return new int[0];
        }
        int[] attributeResolutionStack = mAttributeResolutionStacks.get(attribute);
        int stackSize = attributeResolutionStack.length;
        if (mSourceLayoutId != ID_NULL) {
            stackSize++;
        }
        int currentIndex = 0;
        int[] stack = new int[stackSize];
        if (mSourceLayoutId != ID_NULL) {
            stack[currentIndex] = mSourceLayoutId;
            currentIndex++;
        }
        for (int i = 0; i < attributeResolutionStack.length; i++) {
            stack[currentIndex] = attributeResolutionStack[i];
            currentIndex++;
        }
        return stack;
    }
    @NonNull
    @SuppressWarnings("AndroidFrameworkEfficientCollections")
    public Map<Integer, Integer> getAttributeSourceResourceMap() {
        HashMap<Integer, Integer> map = new HashMap<>();
        if (!sDebugViewAttributes || mAttributeSourceResId == null) {
            return map;
        }
        for (int i = 0; i < mAttributeSourceResId.size(); i++) {
            map.put(mAttributeSourceResId.keyAt(i), mAttributeSourceResId.valueAt(i));
        }
        return map;
    }
    @StyleRes
    public int getExplicitStyle() {
        if (!sDebugViewAttributes) {
            return ID_NULL;
        }
        return mExplicitStyle;
    }
    private static class DeclaredOnClickListener implements OnClickListener {
        private final View mHostView;
        private final String mMethodName;
        private Method mResolvedMethod;
        private Context mResolvedContext;
        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
            mHostView = hostView;
            mMethodName = methodName;
        }
        @Override
        public void onClick(@NonNull View v) {
            if (mResolvedMethod == null) {
                resolveMethod(mHostView.getContext(), mMethodName);
            }
            try {
                mResolvedMethod.invoke(mResolvedContext, v);
            } catch (IllegalAccessException e) {
                throw new IllegalStateException(
                        "Could not execute non-public method for android:onClick", e);
            } catch (InvocationTargetException e) {
                throw new IllegalStateException(
                        "Could not execute method for android:onClick", e);
            }
        }
        @NonNull
        private void resolveMethod(@Nullable Context context, @NonNull String name) {
            while (context != null) {
                try {
                    if (!context.isRestricted()) {
                        final Method method = context.getClass().getMethod(mMethodName, View.class);
                        if (method != null) {
                            mResolvedMethod = method;
                            mResolvedContext = context;
                            return;
                        }
                    }
                } catch (NoSuchMethodException e) {
                }
                if (context instanceof ContextWrapper) {
                    context = ((ContextWrapper) context).getBaseContext();
                } else {
                    context = null;
                }
            }
            final int id = mHostView.getId();
            final String idText = id == NO_ID ? "" : " with id '"
                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
            throw new IllegalStateException("Could not find method " + mMethodName
                    + "(View) in a parent or ancestor Context for android:onClick "
                    + "attribute defined on view " + mHostView.getClass() + idText);
        }
    }
    @UnsupportedAppUsage
    View() {
        mResources = null;
        mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
    }
    public final boolean isShowingLayoutBounds() {
        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
    }
    @TestApi
    public final void setShowingLayoutBounds(boolean debugLayout) {
        if (mAttachInfo != null) {
            mAttachInfo.mDebugLayout = debugLayout;
        }
    }
    private static SparseArray<String> getAttributeMap() {
        if (mAttributeMap == null) {
            mAttributeMap = new SparseArray<>();
        }
        return mAttributeMap;
    }
    private void retrieveExplicitStyle(@NonNull Resources.Theme theme,
            @Nullable AttributeSet attrs) {
        if (!sDebugViewAttributes) {
            return;
        }
        mExplicitStyle = theme.getExplicitStyle(attrs);
    }
    public final void saveAttributeDataForStyleable(@NonNull Context context,
            @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t,
            int defStyleAttr, int defStyleRes) {
        if (!sDebugViewAttributes) {
            return;
        }
        int[] attributeResolutionStack = context.getTheme().getAttributeResolutionStack(
                defStyleAttr, defStyleRes, mExplicitStyle);
        if (mAttributeResolutionStacks == null) {
            mAttributeResolutionStacks = new SparseArray<>();
        }
        if (mAttributeSourceResId == null) {
            mAttributeSourceResId = new SparseIntArray();
        }
        final int indexCount = t.getIndexCount();
        for (int j = 0; j < indexCount; ++j) {
            final int index = t.getIndex(j);
            mAttributeSourceResId.append(styleable[index], t.getSourceResourceId(index, 0));
            mAttributeResolutionStacks.append(styleable[index], attributeResolutionStack);
        }
    }
    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
        final int indexCount = t.getIndexCount();
        int i = 0;
        for (int j = 0; j < attrsCount; ++j) {
            attributes[i] = attrs.getAttributeName(j);
            attributes[i + 1] = attrs.getAttributeValue(j);
            i += 2;
        }
        final Resources res = t.getResources();
        final SparseArray<String> attributeMap = getAttributeMap();
        for (int j = 0; j < indexCount; ++j) {
            final int index = t.getIndex(j);
            if (!t.hasValueOrEmpty(index)) {
                continue;
            }
            final int resourceId = t.getResourceId(index, 0);
            if (resourceId == 0) {
                continue;
            }
            String resourceName = attributeMap.get(resourceId);
            if (resourceName == null) {
                try {
                    resourceName = res.getResourceName(resourceId);
                } catch (Resources.NotFoundException e) {
                    resourceName = "0x" + Integer.toHexString(resourceId);
                }
                attributeMap.put(resourceId, resourceName);
            }
            attributes[i] = resourceName;
            attributes[i + 1] = t.getString(index);
            i += 2;
        }
        final String[] trimmed = new String[i];
        System.arraycopy(attributes, 0, trimmed, 0, i);
        mAttributes = trimmed;
    }
    @Override
    public String toString() {
        StringBuilder out = new StringBuilder(256);
        out.append(getClass().getName());
        out.append('{');
        out.append(Integer.toHexString(System.identityHashCode(this)));
        out.append(' ');
        switch (mViewFlags&VISIBILITY_MASK) {
            case VISIBLE: out.append('V'); break;
            case INVISIBLE: out.append('I'); break;
            case GONE: out.append('G'); break;
            default: out.append('.'); break;
        }
        out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
        out.append(' ');
        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
            out.append('p');
        } else {
            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
        }
        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
        out.append(' ');
        out.append(mLeft);
        out.append(',');
        out.append(mTop);
        out.append('-');
        out.append(mRight);
        out.append(',');
        out.append(mBottom);
        appendId(out);
        if (mAutofillId != null) {
            out.append(" aid="); out.append(mAutofillId);
        }
        out.append("}");
        return out.toString();
    }
    void appendId(StringBuilder out) {
        final int id = getId();
        if (id != NO_ID) {
            out.append(" #");
            out.append(Integer.toHexString(id));
            final Resources r = mResources;
            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
                try {
                    String pkgname;
                    switch (id&0xff000000) {
                        case 0x7f000000:
                            pkgname="app";
                            break;
                        case 0x01000000:
                            pkgname="android";
                            break;
                        default:
                            pkgname = r.getResourcePackageName(id);
                            break;
                    }
                    String typename = r.getResourceTypeName(id);
                    String entryname = r.getResourceEntryName(id);
                    out.append(" ");
                    out.append(pkgname);
                    out.append(":");
                    out.append(typename);
                    out.append("/");
                    out.append(entryname);
                } catch (Resources.NotFoundException e) {
                }
            }
        }
    }
    protected void initializeFadingEdge(TypedArray a) {
        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
        initializeFadingEdgeInternal(arr);
        arr.recycle();
    }
    protected void initializeFadingEdgeInternal(TypedArray a) {
        initScrollCache();
        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
                R.styleable.View_fadingEdgeLength,
                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
    }
    public int getVerticalFadingEdgeLength() {
        if (isVerticalFadingEdgeEnabled()) {
            ScrollabilityCache cache = mScrollCache;
            if (cache != null) {
                return cache.fadingEdgeLength;
            }
        }
        return 0;
    }
    public void setFadingEdgeLength(int length) {
        initScrollCache();
        mScrollCache.fadingEdgeLength = length;
    }
    @FlaggedApi(FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION)
    public void clearPendingCredentialRequest() {
        if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
            Log.v(AUTOFILL_LOG_TAG, "clearPendingCredentialRequest called");
        }
        mViewCredentialHandler = null;
    }
    @FlaggedApi(FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION)
    public void setPendingCredentialRequest(@NonNull GetCredentialRequest request,
            @NonNull OutcomeReceiver<GetCredentialResponse, GetCredentialException> callback) {
        Preconditions.checkNotNull(request, "request must not be null");
        Preconditions.checkNotNull(callback, "callback must not be null");
        for (CredentialOption option : request.getCredentialOptions()) {
            ArrayList<AutofillId> ids = option.getCandidateQueryData()
                    .getParcelableArrayList(
                            CredentialProviderService.EXTRA_AUTOFILL_ID, AutofillId.class);
            ids = ids != null ? ids : new ArrayList<>();
            if (!ids.contains(getAutofillId())) {
                ids.add(getAutofillId());
            }
            option.getCandidateQueryData()
                    .putParcelableArrayList(CredentialProviderService.EXTRA_AUTOFILL_ID, ids);
        }
        mViewCredentialHandler = new ViewCredentialHandler(request, callback);
    }
    @Nullable
    public ViewCredentialHandler getViewCredentialHandler() {
        return mViewCredentialHandler;
    }
    public int getHorizontalFadingEdgeLength() {
        if (isHorizontalFadingEdgeEnabled()) {
            ScrollabilityCache cache = mScrollCache;
            if (cache != null) {
                return cache.fadingEdgeLength;
            }
        }
        return 0;
    }
    public int getVerticalScrollbarWidth() {
        ScrollabilityCache cache = mScrollCache;
        if (cache != null) {
            ScrollBarDrawable scrollBar = cache.scrollBar;
            if (scrollBar != null) {
                int size = scrollBar.getSize(true);
                if (size <= 0) {
                    size = cache.scrollBarSize;
                }
                return size;
            }
            return 0;
        }
        return 0;
    }
    protected int getHorizontalScrollbarHeight() {
        ScrollabilityCache cache = mScrollCache;
        if (cache != null) {
            ScrollBarDrawable scrollBar = cache.scrollBar;
            if (scrollBar != null) {
                int size = scrollBar.getSize(false);
                if (size <= 0) {
                    size = cache.scrollBarSize;
                }
                return size;
            }
            return 0;
        }
        return 0;
    }
    protected void initializeScrollbars(TypedArray a) {
        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
        initializeScrollbarsInternal(arr);
        arr.recycle();
    }
    private void initializeScrollBarDrawable() {
        initScrollCache();
        if (mScrollCache.scrollBar == null) {
            mScrollCache.scrollBar = new ScrollBarDrawable();
            mScrollCache.scrollBar.setState(getDrawableState());
            mScrollCache.scrollBar.setCallback(this);
        }
    }
    @UnsupportedAppUsage
    protected void initializeScrollbarsInternal(TypedArray a) {
        initScrollCache();
        final ScrollabilityCache scrollabilityCache = mScrollCache;
        if (scrollabilityCache.scrollBar == null) {
            scrollabilityCache.scrollBar = new ScrollBarDrawable();
            scrollabilityCache.scrollBar.setState(getDrawableState());
            scrollabilityCache.scrollBar.setCallback(this);
        }
        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
        if (!fadeScrollbars) {
            scrollabilityCache.state = ScrollabilityCache.ON;
        }
        scrollabilityCache.fadeScrollBars = fadeScrollbars;
        scrollabilityCache.scrollBarFadeDuration = a.getInt(
                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
                        .getScrollBarFadeDuration());
        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
                R.styleable.View_scrollbarDefaultDelayBeforeFade,
                ViewConfiguration.getScrollDefaultDelay());
        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
                com.android.internal.R.styleable.View_scrollbarSize,
                ViewConfiguration.get(mContext).getScaledScrollBarSize());
        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
        if (thumb != null) {
            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
        }
        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
                false);
        if (alwaysDraw) {
            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
        }
        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
        if (thumb != null) {
            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
        }
        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
                false);
        if (alwaysDraw) {
            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
        }
        final int layoutDirection = getLayoutDirection();
        if (track != null) {
            track.setLayoutDirection(layoutDirection);
        }
        if (thumb != null) {
            thumb.setLayoutDirection(layoutDirection);
        }
        resolvePadding();
    }
    public void setVerticalScrollbarThumbDrawable(@Nullable Drawable drawable) {
        initializeScrollBarDrawable();
        mScrollCache.scrollBar.setVerticalThumbDrawable(drawable);
    }
    public void setVerticalScrollbarTrackDrawable(@Nullable Drawable drawable) {
        initializeScrollBarDrawable();
        mScrollCache.scrollBar.setVerticalTrackDrawable(drawable);
    }
    public void setHorizontalScrollbarThumbDrawable(@Nullable Drawable drawable) {
        initializeScrollBarDrawable();
        mScrollCache.scrollBar.setHorizontalThumbDrawable(drawable);
    }
    public void setHorizontalScrollbarTrackDrawable(@Nullable Drawable drawable) {
        initializeScrollBarDrawable();
        mScrollCache.scrollBar.setHorizontalTrackDrawable(drawable);
    }
    public @Nullable Drawable getVerticalScrollbarThumbDrawable() {
        return mScrollCache != null ? mScrollCache.scrollBar.getVerticalThumbDrawable() : null;
    }
    public @Nullable Drawable getVerticalScrollbarTrackDrawable() {
        return mScrollCache != null ? mScrollCache.scrollBar.getVerticalTrackDrawable() : null;
    }
    public @Nullable Drawable getHorizontalScrollbarThumbDrawable() {
        return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalThumbDrawable() : null;
    }
    public @Nullable Drawable getHorizontalScrollbarTrackDrawable() {
        return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalTrackDrawable() : null;
    }
    private void initializeScrollIndicatorsInternal() {
        if (mScrollIndicatorDrawable == null) {
            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
        }
    }
    private void initScrollCache() {
        if (mScrollCache == null) {
            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
        }
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private ScrollabilityCache getScrollCache() {
        initScrollCache();
        return mScrollCache;
    }
    public void setVerticalScrollbarPosition(int position) {
        if (mVerticalScrollbarPosition != position) {
            mVerticalScrollbarPosition = position;
            computeOpaqueFlags();
            resolvePadding();
        }
    }
    public int getVerticalScrollbarPosition() {
        return mVerticalScrollbarPosition;
    }
    boolean isOnScrollbar(float x, float y) {
        if (mScrollCache == null) {
            return false;
        }
        x += getScrollX();
        y += getScrollY();
        final boolean canScrollVertically =
                computeVerticalScrollRange() > computeVerticalScrollExtent();
        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden() && canScrollVertically) {
            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
            getVerticalScrollBarBounds(null, touchBounds);
            if (touchBounds.contains((int) x, (int) y)) {
                return true;
            }
        }
        final boolean canScrollHorizontally =
                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
        if (isHorizontalScrollBarEnabled() && canScrollHorizontally) {
            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
            getHorizontalScrollBarBounds(null, touchBounds);
            if (touchBounds.contains((int) x, (int) y)) {
                return true;
            }
        }
        return false;
    }
    @UnsupportedAppUsage
    boolean isOnScrollbarThumb(float x, float y) {
        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
    }
    private boolean isOnVerticalScrollbarThumb(float x, float y) {
        if (mScrollCache == null || !isVerticalScrollBarEnabled() || isVerticalScrollBarHidden()) {
            return false;
        }
        final int range = computeVerticalScrollRange();
        final int extent = computeVerticalScrollExtent();
        if (range > extent) {
            x += getScrollX();
            y += getScrollY();
            final Rect bounds = mScrollCache.mScrollBarBounds;
            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
            getVerticalScrollBarBounds(bounds, touchBounds);
            final int offset = computeVerticalScrollOffset();
            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
                    extent, range);
            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
                    extent, range, offset);
            final int thumbTop = bounds.top + thumbOffset;
            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
            if (x >= touchBounds.left && x <= touchBounds.right
                    && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
                return true;
            }
        }
        return false;
    }
    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
        if (mScrollCache == null || !isHorizontalScrollBarEnabled()) {
            return false;
        }
        final int range = computeHorizontalScrollRange();
        final int extent = computeHorizontalScrollExtent();
        if (range > extent) {
            x += getScrollX();
            y += getScrollY();
            final Rect bounds = mScrollCache.mScrollBarBounds;
            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
            getHorizontalScrollBarBounds(bounds, touchBounds);
            final int offset = computeHorizontalScrollOffset();
            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
                    extent, range);
            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
                    extent, range, offset);
            final int thumbLeft = bounds.left + thumbOffset;
            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
            if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
                    && y >= touchBounds.top && y <= touchBounds.bottom) {
                return true;
            }
        }
        return false;
    }
    @UnsupportedAppUsage
    boolean isDraggingScrollBar() {
        return mScrollCache != null
                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
    }
    @RemotableViewMethod
    public void setScrollIndicators(@ScrollIndicators int indicators) {
        setScrollIndicators(indicators,
                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
    }
    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
        indicators &= mask;
        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
        if (mPrivateFlags3 != updatedFlags) {
            mPrivateFlags3 = updatedFlags;
            if (indicators != 0) {
                initializeScrollIndicatorsInternal();
            }
            invalidate();
        }
    }
    @InspectableProperty(flagMapping = {
            @FlagEntry(target = SCROLL_INDICATORS_NONE, mask = 0xffff_ffff, name = "none"),
            @FlagEntry(target = SCROLL_INDICATOR_TOP, name = "top"),
            @FlagEntry(target = SCROLL_INDICATOR_BOTTOM, name = "bottom"),
            @FlagEntry(target = SCROLL_INDICATOR_LEFT, name = "left"),
            @FlagEntry(target = SCROLL_INDICATOR_RIGHT, name = "right"),
            @FlagEntry(target = SCROLL_INDICATOR_START, name = "start"),
            @FlagEntry(target = SCROLL_INDICATOR_END, name = "end")
    })
    @ScrollIndicators
    public int getScrollIndicators() {
        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
    }
    @UnsupportedAppUsage
    ListenerInfo getListenerInfo() {
        if (mListenerInfo != null) {
            return mListenerInfo;
        }
        mListenerInfo = new ListenerInfo();
        return mListenerInfo;
    }
    public void setOnScrollChangeListener(OnScrollChangeListener l) {
        getListenerInfo().mOnScrollChangeListener = l;
    }
    public void setOnFocusChangeListener(OnFocusChangeListener l) {
        getListenerInfo().mOnFocusChangeListener = l;
    }
    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
        ListenerInfo li = getListenerInfo();
        if (li.mOnLayoutChangeListeners == null) {
            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
        }
        if (!li.mOnLayoutChangeListeners.contains(listener)) {
            li.mOnLayoutChangeListeners.add(listener);
        }
    }
    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
        ListenerInfo li = mListenerInfo;
        if (li == null || li.mOnLayoutChangeListeners == null) {
            return;
        }
        li.mOnLayoutChangeListeners.remove(listener);
    }
    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
        ListenerInfo li = getListenerInfo();
        if (li.mOnAttachStateChangeListeners == null) {
            li.mOnAttachStateChangeListeners
                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
        }
        li.mOnAttachStateChangeListeners.add(listener);
    }
    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
        ListenerInfo li = mListenerInfo;
        if (li == null || li.mOnAttachStateChangeListeners == null) {
            return;
        }
        li.mOnAttachStateChangeListeners.remove(listener);
    }
    public OnFocusChangeListener getOnFocusChangeListener() {
        ListenerInfo li = mListenerInfo;
        return li != null ? li.mOnFocusChangeListener : null;
    }
    public void setOnClickListener(@Nullable OnClickListener l) {
        if (!isClickable()) {
            setClickable(true);
        }
        getListenerInfo().mOnClickListener = l;
    }
    public boolean hasOnClickListeners() {
        ListenerInfo li = mListenerInfo;
        return (li != null && li.mOnClickListener != null);
    }
    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
        if (!isLongClickable()) {
            setLongClickable(true);
        }
        getListenerInfo().mOnLongClickListener = l;
    }
    public boolean hasOnLongClickListeners() {
        ListenerInfo li = mListenerInfo;
        return (li != null && li.mOnLongClickListener != null);
    }
    @Nullable
    public OnLongClickListener getOnLongClickListener() {
        ListenerInfo li = mListenerInfo;
        return (li != null) ? li.mOnLongClickListener : null;
    }
    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
        if (!isContextClickable()) {
            setContextClickable(true);
        }
        getListenerInfo().mOnContextClickListener = l;
    }
    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
        if (!isLongClickable()) {
            setLongClickable(true);
        }
        getListenerInfo().mOnCreateContextMenuListener = l;
    }
    public void addFrameMetricsListener(Window window,
            Window.OnFrameMetricsAvailableListener listener,
            Handler handler) {
        if (mAttachInfo != null) {
            if (mAttachInfo.mThreadedRenderer != null) {
                if (mFrameMetricsObservers == null) {
                    mFrameMetricsObservers = new ArrayList<>();
                }
                FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
                mFrameMetricsObservers.add(fmo);
                mAttachInfo.mThreadedRenderer.addObserver(fmo.getRendererObserver());
            } else {
                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
            }
        } else {
            if (mFrameMetricsObservers == null) {
                mFrameMetricsObservers = new ArrayList<>();
            }
            FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
            mFrameMetricsObservers.add(fmo);
        }
    }
    public void removeFrameMetricsListener(
            Window.OnFrameMetricsAvailableListener listener) {
        ThreadedRenderer renderer = getThreadedRenderer();
        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
        if (fmo == null) {
            throw new IllegalArgumentException(
                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
        }
        if (mFrameMetricsObservers != null) {
            mFrameMetricsObservers.remove(fmo);
            if (renderer != null) {
                renderer.removeObserver(fmo.getRendererObserver());
            }
        }
    }
    private void registerPendingFrameMetricsObservers() {
        if (mFrameMetricsObservers != null) {
            ThreadedRenderer renderer = getThreadedRenderer();
            if (renderer != null) {
                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
                    renderer.addObserver(fmo.getRendererObserver());
                }
            } else {
                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
            }
        }
    }
    private FrameMetricsObserver findFrameMetricsObserver(
            Window.OnFrameMetricsAvailableListener listener) {
        if (mFrameMetricsObservers != null) {
            for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
                FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
                if (observer.mListener == listener) {
                    return observer;
                }
            }
        }
        return null;
    }
    public void setNotifyAutofillManagerOnClick(boolean notify) {
        if (notify) {
            mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
        } else {
            mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
        }
    }
    private void notifyAutofillManagerOnClick() {
        if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) {
            try {
                getAutofillManager().notifyViewClicked(this);
            } finally {
                mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
            }
        }
    }
    private boolean performClickInternal() {
        notifyAutofillManagerOnClick();
        return performClick();
    }
    public boolean performClick() {
        notifyAutofillManagerOnClick();
        final boolean result;
        final ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnClickListener != null) {
            playSoundEffect(SoundEffectConstants.CLICK);
            li.mOnClickListener.onClick(this);
            result = true;
        } else {
            result = false;
        }
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
        notifyEnterOrExitForAutoFillIfNeeded(true);
        return result;
    }
    public boolean callOnClick() {
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnClickListener != null) {
            li.mOnClickListener.onClick(this);
            return true;
        }
        return false;
    }
    public boolean performLongClick() {
        return performLongClickInternal(mLongClickX, mLongClickY);
    }
    public boolean performLongClick(float x, float y) {
        mLongClickX = x;
        mLongClickY = y;
        final boolean handled = performLongClick();
        mLongClickX = Float.NaN;
        mLongClickY = Float.NaN;
        return handled;
    }
    private boolean performLongClickInternal(float x, float y) {
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
        boolean handled = false;
        final OnLongClickListener listener =
                mListenerInfo == null ? null : mListenerInfo.mOnLongClickListener;
        boolean shouldPerformHapticFeedback = true;
        if (listener != null) {
            handled = listener.onLongClick(View.this);
            if (handled) {
                shouldPerformHapticFeedback = listener.onLongClickUseDefaultHapticFeedback(
                        View.this);
            }
        }
        if (!handled) {
            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
        }
        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
            if (!handled) {
                handled = showLongClickTooltip((int) x, (int) y);
            }
        }
        if (handled && shouldPerformHapticFeedback) {
            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
        }
        return handled;
    }
    public boolean performContextClick(float x, float y) {
        return performContextClick();
    }
    public boolean performContextClick() {
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
        boolean handled = false;
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnContextClickListener != null) {
            handled = li.mOnContextClickListener.onContextClick(View.this);
        }
        if (handled) {
            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
        }
        return handled;
    }
    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
            showContextMenu(event.getX(), event.getY());
            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
            return true;
        }
        return false;
    }
    public boolean showContextMenu() {
        return getParent().showContextMenuForChild(this);
    }
    public boolean showContextMenu(float x, float y) {
        return getParent().showContextMenuForChild(this, x, y);
    }
    public ActionMode startActionMode(ActionMode.Callback callback) {
        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
    }
    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
        ViewParent parent = getParent();
        if (parent == null) return null;
        try {
            return parent.startActionModeForChild(this, callback, type);
        } catch (AbstractMethodError ame) {
            return parent.startActionModeForChild(this, callback);
        }
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    public void startActivityForResult(Intent intent, int requestCode) {
        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
    }
    public boolean dispatchActivityResult(
            String who, int requestCode, int resultCode, Intent data) {
        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
            onActivityResult(requestCode, resultCode, data);
            mStartActivityRequestWho = null;
            return true;
        }
        return false;
    }
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    }
    public void setOnKeyListener(OnKeyListener l) {
        getListenerInfo().mOnKeyListener = l;
    }
    public void setOnTouchListener(OnTouchListener l) {
        getListenerInfo().mOnTouchListener = l;
    }
    public void setOnGenericMotionListener(OnGenericMotionListener l) {
        getListenerInfo().mOnGenericMotionListener = l;
    }
    public void setOnHoverListener(OnHoverListener l) {
        getListenerInfo().mOnHoverListener = l;
    }
    public void setOnDragListener(OnDragListener l) {
        getListenerInfo().mOnDragListener = l;
    }
    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
        if (DBG) {
            System.out.println(this + " requestFocus()");
        }
        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
            mPrivateFlags |= PFLAG_FOCUSED;
            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
            if (mParent != null) {
                mParent.requestChildFocus(this, this);
                updateFocusedInCluster(oldFocus, direction);
            }
            if (mAttachInfo != null) {
                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
            }
            onFocusChanged(true, direction, previouslyFocusedRect);
            refreshDrawableState();
        }
    }
    public final void setRevealOnFocusHint(boolean revealOnFocus) {
        if (revealOnFocus) {
            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
        } else {
            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
        }
    }
    public final boolean getRevealOnFocusHint() {
        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
    }
    public void getHotspotBounds(Rect outRect) {
        final Drawable background = getBackground();
        if (background != null) {
            background.getHotspotBounds(outRect);
        } else {
            getBoundsOnScreen(outRect);
        }
    }
    public boolean requestRectangleOnScreen(Rect rectangle) {
        return requestRectangleOnScreen(rectangle, false);
    }
    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
        if (mParent == null) {
            return false;
        }
        View child = this;
        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
        position.set(rectangle);
        ViewParent parent = mParent;
        boolean scrolled = false;
        while (parent != null) {
            rectangle.set((int) position.left, (int) position.top,
                    (int) position.right, (int) position.bottom);
            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
            if (!(parent instanceof View)) {
                break;
            }
            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
            child = (View) parent;
            parent = child.getParent();
        }
        return scrolled;
    }
    public void clearFocus() {
        if (DBG) {
            System.out.println(this + " clearFocus()");
        }
        final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
        clearFocusInternal(null, true, refocus);
    }
    public void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
            mPrivateFlags &= ~PFLAG_FOCUSED;
            clearParentsWantFocus();
            if (propagate && mParent != null) {
                mParent.clearChildFocus(this);
            }
            onFocusChanged(false, 0, null);
            refreshDrawableState();
            if (propagate && (!refocus || !rootViewRequestFocus())) {
                notifyGlobalFocusCleared(this);
            }
        }
    }
    void notifyGlobalFocusCleared(View oldFocus) {
        if (oldFocus != null && mAttachInfo != null) {
            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
        }
    }
    boolean rootViewRequestFocus() {
        final View root = getRootView();
        return root != null && root.requestFocus();
    }
    void unFocus(View focused) {
        if (DBG) {
            System.out.println(this + " unFocus()");
        }
        clearFocusInternal(focused, false, false);
    }
    @ViewDebug.ExportedProperty(category = "focus")
    public boolean hasFocus() {
        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
    }
    public boolean hasFocusable() {
        return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
    }
    public boolean hasExplicitFocusable() {
        return hasFocusable(false, true);
    }
    boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
        if (!isFocusableInTouchMode()) {
            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
                final ViewGroup g = (ViewGroup) p;
                if (g.shouldBlockFocusForTouchscreen()) {
                    return false;
                }
            }
        }
        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE
                || (mViewFlags & ENABLED_MASK) != ENABLED) {
            return false;
        }
        if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
            return true;
        }
        return false;
    }
    @CallSuper
    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
            @Nullable Rect previouslyFocusedRect) {
        if (DBG) {
            Log.d(VIEW_LOG_TAG, "onFocusChanged() entered. gainFocus: "
                    + gainFocus);
        }
        if (gainFocus) {
            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
        } else {
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
        }
        switchDefaultFocusHighlight();
        if (!gainFocus) {
            if (isPressed()) {
                setPressed(false);
            }
            if (hasWindowFocus()) {
            }
            onFocusLost();
        } else if (hasWindowFocus()) {
            ViewRootImpl viewRoot = getViewRootImpl();
            if (viewRoot != null) {
                if (mIsHandwritingDelegate) {
                    viewRoot.getHandwritingInitiator().onDelegateViewFocused(this);
                } else if (initiationWithoutInputConnection() && onCheckIsTextEditor()) {
                    viewRoot.getHandwritingInitiator().onEditorFocused(this);
                }
            }
        }
        invalidate(true);
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnFocusChangeListener != null) {
            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
        }
        if (mAttachInfo != null) {
            mAttachInfo.mKeyDispatchState.reset(this);
        }
        if (mParent != null) {
            mParent.onDescendantUnbufferedRequested();
        }
        notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
        updatePreferKeepClearForFocus();
    }
    private void notifyFocusChangeToImeFocusController(boolean hasFocus) {
        if (mAttachInfo == null) {
            return;
        }
        mAttachInfo.mViewRootImpl.getImeFocusController().onViewFocusChanged(this, hasFocus);
    }
    public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
        if (canNotifyAutofillEnterExitEvent()) {
            AutofillManager afm = getAutofillManager();
            if (afm != null) {
                if (DBG) {
                    Log.d(VIEW_LOG_TAG, this + " afm is not null");
                }
                if (enter) {
                    if (DBG) {
                        Log.d(VIEW_LOG_TAG,
                                "notifyEnterOrExitForAutoFillIfNeeded:"
                                + " isLaidOut(): " + isLaidOut()
                                + " isVisibleToUser(): " + isVisibleToUser()
                                + " isFocused(): " + isFocused());
                    }
                    if (!isLaidOut() || !isVisibleToUser()) {
                        mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
                    } else if (isVisibleToUser()) {
                        if (isFocused()) {
                            afm.notifyViewEntered(this);
                        } else {
                            afm.notifyViewEnteredForFillDialog(this);
                        }
                    }
                } else if (!isFocused()) {
                    afm.notifyViewExited(this);
                }
            }
        }
    }
    public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
        if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
            boolean currentPaneTitleEmpty = mAccessibilityPaneTitle == null;
            boolean newPaneTitleEmpty =  accessibilityPaneTitle == null;
            mAccessibilityPaneTitle = accessibilityPaneTitle;
            if (mAccessibilityPaneTitle != null
                    && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
                setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
            }
            if (currentPaneTitleEmpty) {
                notifyViewAccessibilityStateChangedIfNeeded(
                        AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED);
            } else if (newPaneTitleEmpty) {
                notifyViewAccessibilityStateChangedIfNeeded(
                        AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
            } else {
                notifyViewAccessibilityStateChangedIfNeeded(
                        AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
            }
        }
    }
    @InspectableProperty
    @Nullable
    public CharSequence getAccessibilityPaneTitle() {
        return mAccessibilityPaneTitle;
    }
    private boolean isAccessibilityPane() {
        return mAccessibilityPaneTitle != null;
    }
    public void sendAccessibilityEvent(int eventType) {
        if (mAccessibilityDelegate != null) {
            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
        } else {
            sendAccessibilityEventInternal(eventType);
        }
    }
    public void announceForAccessibility(CharSequence text) {
        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
            AccessibilityEvent event = AccessibilityEvent.obtain(
                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
            onInitializeAccessibilityEvent(event);
            event.getText().add(text);
            event.setContentDescription(null);
            mParent.requestSendAccessibilityEvent(this, event);
        }
    }
    public void sendAccessibilityEventInternal(int eventType) {
        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
        }
    }
    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
        if (mAccessibilityDelegate != null) {
            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
        } else {
            sendAccessibilityEventUncheckedInternal(event);
        }
    }
    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
        boolean isWindowStateChanged =
                (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
        boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes()
                & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0);
        boolean detached = detached();
        if (!isShown() && !isWindowDisappearedEvent && !detached) {
            return;
        }
        onInitializeAccessibilityEvent(event);
        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
            dispatchPopulateAccessibilityEvent(event);
        }
        SendAccessibilityEventThrottle throttle = getThrottleForAccessibilityEvent(event);
        if (throttle != null) {
            throttle.post(event);
        } else if (!isWindowDisappearedEvent && detached) {
            postDelayed(() -> {
                if (AccessibilityManager.getInstance(mContext).isEnabled() && isShown()) {
                    requestParentSendAccessibilityEvent(event);
                }
            }, ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
        } else {
            requestParentSendAccessibilityEvent(event);
        }
    }
    private void requestParentSendAccessibilityEvent(AccessibilityEvent event) {
        ViewParent parent = getParent();
        if (parent != null) {
            getParent().requestSendAccessibilityEvent(this, event);
        }
    }
    private SendAccessibilityEventThrottle getThrottleForAccessibilityEvent(
            AccessibilityEvent event) {
        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
            if (mSendViewScrolledAccessibilityEvent == null) {
                mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
            }
            return mSendViewScrolledAccessibilityEvent;
        }
        boolean isStateContentChanged = (event.getContentChangeTypes()
                & AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION) != 0;
        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
                && isStateContentChanged) {
            if (mSendStateChangedAccessibilityEvent == null) {
                mSendStateChangedAccessibilityEvent = new SendAccessibilityEventThrottle();
            }
            return mSendStateChangedAccessibilityEvent;
        }
        return null;
    }
    private void clearAccessibilityThrottles() {
        cancel(mSendViewScrolledAccessibilityEvent);
        cancel(mSendStateChangedAccessibilityEvent);
    }
    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
        if (mAccessibilityDelegate != null) {
            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
        } else {
            return dispatchPopulateAccessibilityEventInternal(event);
        }
    }
    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
        onPopulateAccessibilityEvent(event);
        return false;
    }
    @CallSuper
    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
        if (mAccessibilityDelegate != null) {
            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
        } else {
            onPopulateAccessibilityEventInternal(event);
        }
    }
    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
        if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
                && isAccessibilityPane()) {
            event.getText().add(getAccessibilityPaneTitle());
        }
    }
    @CallSuper
    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
        if (mAccessibilityDelegate != null) {
            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
        } else {
            onInitializeAccessibilityEventInternal(event);
        }
    }
    @UnsupportedAppUsage
    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
        event.setSource(this);
        event.setClassName(getAccessibilityClassName());
        event.setPackageName(getContext().getPackageName());
        event.setEnabled(isEnabled());
        event.setContentDescription(mContentDescription);
        event.setScrollX(getScrollX());
        event.setScrollY(getScrollY());
        switch (event.getEventType()) {
            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
                ArrayList<View> focusablesTempList = (mAttachInfo != null)
                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
                event.setItemCount(focusablesTempList.size());
                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
                if (mAttachInfo != null) {
                    focusablesTempList.clear();
                }
            } break;
            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
                CharSequence text = getIterableTextForAccessibility();
                if (text != null && text.length() > 0) {
                    event.setFromIndex(getAccessibilitySelectionStart());
                    event.setToIndex(getAccessibilitySelectionEnd());
                    event.setItemCount(text.length());
                }
            } break;
        }
    }
    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
        if (mAccessibilityDelegate != null) {
            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
        } else {
            return createAccessibilityNodeInfoInternal();
        }
    }
    public @Nullable AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
        if (provider != null) {
            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
        } else {
            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
            onInitializeAccessibilityNodeInfo(info);
            return info;
        }
    }
    @CallSuper
    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
        if (mAccessibilityDelegate != null) {
            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
        } else {
            onInitializeAccessibilityNodeInfoInternal(info);
        }
    }
    @UnsupportedAppUsage
    public void getBoundsOnScreen(Rect outRect) {
        getBoundsOnScreen(outRect, false);
    }
    @UnsupportedAppUsage
    @TestApi
    public void getBoundsOnScreen(@NonNull Rect outRect, boolean clipToParent) {
        if (mAttachInfo == null) {
            return;
        }
        RectF position = mAttachInfo.mTmpTransformRect;
        getBoundsToScreenInternal(position, clipToParent);
        outRect.set(Math.round(position.left), Math.round(position.top),
                Math.round(position.right), Math.round(position.bottom));
        mAttachInfo.mViewRootImpl.applyViewBoundsSandboxingIfNeeded(outRect);
    }
    public void getBoundsOnScreen(RectF outRect, boolean clipToParent) {
        if (mAttachInfo == null) {
            return;
        }
        RectF position = mAttachInfo.mTmpTransformRect;
        getBoundsToScreenInternal(position, clipToParent);
        outRect.set(position.left, position.top, position.right, position.bottom);
    }
    public void getBoundsInWindow(Rect outRect, boolean clipToParent) {
        if (mAttachInfo == null) {
            return;
        }
        RectF position = mAttachInfo.mTmpTransformRect;
        getBoundsToWindowInternal(position, clipToParent);
        outRect.set(Math.round(position.left), Math.round(position.top),
                Math.round(position.right), Math.round(position.bottom));
    }
    private void getBoundsToScreenInternal(RectF position, boolean clipToParent) {
        position.set(0, 0, mRight - mLeft, mBottom - mTop);
        mapRectFromViewToScreenCoords(position, clipToParent);
    }
    private void getBoundsToWindowInternal(RectF position, boolean clipToParent) {
        position.set(0, 0, mRight - mLeft, mBottom - mTop);
        mapRectFromViewToWindowCoords(position, clipToParent);
    }
    public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
        mapRectFromViewToWindowCoords(rect, clipToParent);
        rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
    }
    public void mapRectFromViewToWindowCoords(RectF rect, boolean clipToParent) {
        if (!hasIdentityMatrix()) {
            getMatrix().mapRect(rect);
        }
        rect.offset(mLeft, mTop);
        ViewParent parent = mParent;
        while (parent instanceof View) {
            View parentView = (View) parent;
            rect.offset(-parentView.mScrollX, -parentView.mScrollY);
            if (clipToParent) {
                rect.left = Math.max(rect.left, 0);
                rect.top = Math.max(rect.top, 0);
                rect.right = Math.min(rect.right, parentView.getWidth());
                rect.bottom = Math.min(rect.bottom, parentView.getHeight());
            }
            if (!parentView.hasIdentityMatrix()) {
                parentView.getMatrix().mapRect(rect);
            }
            rect.offset(parentView.mLeft, parentView.mTop);
            parent = parentView.mParent;
        }
        if (parent instanceof ViewRootImpl) {
            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
            rect.offset(0, -viewRootImpl.mCurScrollY);
        }
    }
    public CharSequence getAccessibilityClassName() {
        return View.class.getName();
    }
    public void onProvideStructure(ViewStructure structure) {
    }
    public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
        onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
    }
    public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
        onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
    }
    protected void onProvideStructure(@NonNull ViewStructure structure,
            @ViewStructureType int viewFor, int flags) {
        final int id = mID;
        if (id != NO_ID && !isViewIdGenerated(id)) {
            String pkg, type, entry;
            try {
                final Resources res = getResources();
                entry = res.getResourceEntryName(id);
                type = res.getResourceTypeName(id);
                pkg = res.getResourcePackageName(id);
            } catch (Resources.NotFoundException e) {
                entry = type = pkg = null;
            }
            structure.setId(id, pkg, type, entry);
        } else {
            structure.setId(id, null, null, null);
        }
        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
                || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
            final @AutofillType int autofillType = getAutofillType();
            if (autofillType != AUTOFILL_TYPE_NONE) {
                structure.setAutofillType(autofillType);
                structure.setAutofillHints(getAutofillHints());
                structure.setAutofillValue(getAutofillValue());
                structure.setIsCredential(isCredential());
            }
            if (getViewCredentialHandler() != null) {
                structure.setPendingCredentialRequest(
                        getViewCredentialHandler().getRequest(),
                        getViewCredentialHandler().getCallback());
            }
            structure.setImportantForAutofill(getImportantForAutofill());
            structure.setReceiveContentMimeTypes(getReceiveContentMimeTypes());
        }
        int ignoredParentLeft = 0;
        int ignoredParentTop = 0;
        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
                && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
            View parentGroup = null;
            ViewParent viewParent = getParent();
            if (viewParent instanceof View) {
                parentGroup = (View) viewParent;
            }
            while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
                ignoredParentLeft += parentGroup.mLeft - parentGroup.mScrollX;
                ignoredParentTop += parentGroup.mTop - parentGroup.mScrollY;
                viewParent = parentGroup.getParent();
                if (viewParent instanceof View) {
                    parentGroup = (View) viewParent;
                } else {
                    break;
                }
            }
        }
        structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
                mRight - mLeft, mBottom - mTop);
        if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
            if (!hasIdentityMatrix()) {
                structure.setTransformation(getMatrix());
            }
            structure.setElevation(getZ());
        }
        structure.setVisibility(getVisibility());
        structure.setEnabled(isEnabled());
        if (isClickable()) {
            structure.setClickable(true);
        }
        if (isFocusable()) {
            structure.setFocusable(true);
        }
        if (isFocused()) {
            structure.setFocused(true);
        }
        if (isAccessibilityFocused()) {
            structure.setAccessibilityFocused(true);
        }
        if (isSelected()) {
            structure.setSelected(true);
        }
        if (isActivated()) {
            structure.setActivated(true);
        }
        if (isLongClickable()) {
            structure.setLongClickable(true);
        }
        if (this instanceof Checkable) {
            structure.setCheckable(true);
            if (((Checkable)this).isChecked()) {
                structure.setChecked(true);
            }
        }
        if (isOpaque()) {
            structure.setOpaque(true);
        }
        if (isContextClickable()) {
            structure.setContextClickable(true);
        }
        structure.setClassName(getAccessibilityClassName().toString());
        structure.setContentDescription(getContentDescription());
    }
    public void onProvideVirtualStructure(ViewStructure structure) {
        onProvideVirtualStructureCompat(structure, false);
    }
    private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) {
        final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
        if (provider != null) {
            if (forAutofill && Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
                Log.v(AUTOFILL_LOG_TAG, "onProvideVirtualStructureCompat() for " + this);
            }
            final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
            structure.setChildCount(1);
            final ViewStructure root = structure.newChild(0);
            if (info != null) {
                populateVirtualStructure(root, provider, info, forAutofill);
                info.recycle();
            } else {
                Log.w(AUTOFILL_LOG_TAG, "AccessibilityNodeInfo is null.");
            }
        }
    }
    public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
        if (mContext.isAutofillCompatibilityEnabled()) {
            onProvideVirtualStructureCompat(structure, true);
        }
    }
    public void setOnReceiveContentListener(
            @SuppressLint("NullableCollection") @Nullable String[] mimeTypes,
            @Nullable OnReceiveContentListener listener) {
        if (listener != null) {
            Preconditions.checkArgument(mimeTypes != null && mimeTypes.length > 0,
                    "When the listener is set, MIME types must also be set");
        }
        if (mimeTypes != null) {
        }
        mReceiveContentMimeTypes = ArrayUtils.isEmpty(mimeTypes) ? null : mimeTypes;
        getListenerInfo().mOnReceiveContentListener = listener;
    }
    @Nullable
    public ContentInfo performReceiveContent(@NonNull ContentInfo payload) {
        final OnReceiveContentListener listener = (mListenerInfo == null) ? null
                : getListenerInfo().mOnReceiveContentListener;
        if (listener != null) {
            final ContentInfo remaining = listener.onReceiveContent(this, payload);
            return (remaining == null) ? null : onReceiveContent(remaining);
        }
        return onReceiveContent(payload);
    }
    @Nullable
    public ContentInfo onReceiveContent(@NonNull ContentInfo payload) {
        return payload;
    }
    @SuppressLint("NullableCollection")
    @Nullable
    public String[] getReceiveContentMimeTypes() {
        return mReceiveContentMimeTypes;
    }
    public void autofill(@SuppressWarnings("unused") AutofillValue value) {
    }
    public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
        if (!mContext.isAutofillCompatibilityEnabled()) {
            return;
        }
        final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
        if (provider == null) {
            return;
        }
        final int valueCount = values.size();
        for (int i = 0; i < valueCount; i++) {
            final AutofillValue value = values.valueAt(i);
            if (value.isText()) {
                final int virtualId = values.keyAt(i);
                final CharSequence text = value.getTextValue();
                final Bundle arguments = new Bundle();
                arguments.putCharSequence(
                        AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
                provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
            }
        }
    }
    public void onGetCredentialResponse(GetCredentialResponse response) {
        if (getPendingCredentialCallback() == null) {
            Log.w(AUTOFILL_LOG_TAG, "onGetCredentialResponse called but no callback found");
            return;
        }
        getPendingCredentialCallback().onResult(response);
    }
    public void onGetCredentialException(String errorType, String errorMsg) {
        if (getPendingCredentialCallback() == null) {
            Log.w(AUTOFILL_LOG_TAG, "onGetCredentialException called but no callback found");
            return;
        }
        getPendingCredentialCallback().onError(new GetCredentialException(errorType, errorMsg));
    }
    public final AutofillId getAutofillId() {
        if (mAutofillId == null) {
            mAutofillId = new AutofillId(getAutofillViewId());
        }
        return mAutofillId;
    }
    @FlaggedApi(FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION)
    @Nullable
    public final GetCredentialRequest getPendingCredentialRequest() {
        if (mViewCredentialHandler == null) {
            return null;
        }
        return mViewCredentialHandler.getRequest();
    }
    @FlaggedApi(FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION)
    @Nullable
    public final OutcomeReceiver<GetCredentialResponse,
            GetCredentialException> getPendingCredentialCallback() {
        if (mViewCredentialHandler == null) {
            return null;
        }
        return mViewCredentialHandler.getCallback();
    }
    public void setAutofillId(@Nullable AutofillId id) {
        if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
            Log.v(AUTOFILL_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id);
        }
        if (isAttachedToWindow()) {
            throw new IllegalStateException("Cannot set autofill id when view is attached");
        }
        if (id != null && !id.isNonVirtual()) {
            throw new IllegalStateException("Cannot set autofill id assigned to virtual views");
        }
        if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) {
            return;
        }
        mAutofillId = id;
        if (id != null) {
            mAutofillViewId = id.getViewId();
            mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
        } else {
            mAutofillViewId = NO_ID;
            mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
        }
    }
    public void resetSubtreeAutofillIds() {
        if (mAutofillViewId == NO_ID) {
            return;
        }
        if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
            Log.v(CONTENT_CAPTURE_LOG_TAG, "resetAutofillId() for " + mAutofillViewId);
        } else if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
            Log.v(AUTOFILL_LOG_TAG, "resetAutofillId() for " + mAutofillViewId);
        }
        mAutofillId = null;
        mAutofillViewId = NO_ID;
        mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
    }
    public @AutofillType int getAutofillType() {
        return AUTOFILL_TYPE_NONE;
    }
    @ViewDebug.ExportedProperty()
    @InspectableProperty
    @Nullable public String[] getAutofillHints() {
        return mAutofillHints;
    }
    @TestApi
    public boolean isAutofilled() {
        return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
    }
    public boolean hideAutofillHighlight() {
        return (mPrivateFlags4 & PFLAG4_AUTOFILL_HIDE_HIGHLIGHT) != 0;
    }
    @Nullable
    public AutofillValue getAutofillValue() {
        return null;
    }
    @ViewDebug.ExportedProperty(mapping = {
            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
                to = "yesExcludeDescendants"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
                to = "noExcludeDescendants")})
    @InspectableProperty(enumMapping = {
            @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_AUTO, name = "auto"),
            @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES, name = "yes"),
            @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO, name = "no"),
            @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
                    name = "yesExcludeDescendants"),
            @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
                    name = "noExcludeDescendants"),
    })
    public @AutofillImportance int getImportantForAutofill() {
        return (mPrivateFlags3
                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
    }
    public void setImportantForAutofill(@AutofillImportance int mode) {
        mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
        mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
    }
    public final boolean isImportantForAutofill() {
        ViewParent parent = mParent;
        while (parent instanceof View) {
            final int parentImportance = ((View) parent).getImportantForAutofill();
            if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
                    || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
                if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
                    Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
                            + "because parent " + parent + "'s importance is " + parentImportance);
                }
                return false;
            }
            parent = parent.getParent();
        }
        final int importance = getImportantForAutofill();
        if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
                || importance == IMPORTANT_FOR_AUTOFILL_YES) {
            return true;
        }
        if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
                || importance == IMPORTANT_FOR_AUTOFILL_NO) {
            if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
                Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
                        + "because its importance is " + importance);
            }
            return false;
        }
        if (importance != IMPORTANT_FOR_AUTOFILL_AUTO) {
            Log.w(AUTOFILL_LOG_TAG, "invalid autofill importance (" + importance + " on view "
                    + this);
            return false;
        }
        final int id = mID;
        if (id != NO_ID && !isViewIdGenerated(id)) {
            final Resources res = getResources();
            String entry = null;
            String pkg = null;
            try {
                entry = res.getResourceEntryName(id);
                pkg = res.getResourcePackageName(id);
            } catch (Resources.NotFoundException e) {
            }
            if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
                return true;
            }
        }
        if (getAutofillHints() != null) {
            return true;
        }
        return false;
    }
    @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
    public final void setContentSensitivity(@ContentSensitivity int mode)  {
        mPrivateFlags4 &= ~PFLAG4_CONTENT_SENSITIVITY_MASK;
        mPrivateFlags4 |= ((mode << PFLAG4_CONTENT_SENSITIVITY_SHIFT)
                & PFLAG4_CONTENT_SENSITIVITY_MASK);
        if (sensitiveContentAppProtection()) {
            updateSensitiveViewsCountIfNeeded(isAggregatedVisible());
        }
    }
    @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
    public @ContentSensitivity final int getContentSensitivity() {
        return (mPrivateFlags4 & PFLAG4_CONTENT_SENSITIVITY_MASK)
                >> PFLAG4_CONTENT_SENSITIVITY_SHIFT;
    }
    @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
    public final boolean isContentSensitive() {
        final int contentSensitivity = getContentSensitivity();
        if (contentSensitivity == CONTENT_SENSITIVITY_SENSITIVE) {
            return true;
        } else if (contentSensitivity == CONTENT_SENSITIVITY_NOT_SENSITIVE) {
            return false;
        } else if (sensitiveContentAppProtection()) {
            return SensitiveAutofillHintsHelper
                    .containsSensitiveAutofillHint(getAutofillHints());
        }
        return false;
    }
    private void updateSensitiveViewsCountIfNeeded(boolean appeared) {
        if (!sensitiveContentAppProtection() || mAttachInfo == null) {
            return;
        }
        if (appeared && isContentSensitive()) {
            if ((mPrivateFlags4 & PFLAG4_IS_COUNTED_AS_SENSITIVE) == 0) {
                mPrivateFlags4 |= PFLAG4_IS_COUNTED_AS_SENSITIVE;
                mAttachInfo.increaseSensitiveViewsCount();
            }
        } else {
            if ((mPrivateFlags4 & PFLAG4_IS_COUNTED_AS_SENSITIVE) != 0) {
                mPrivateFlags4 &= ~PFLAG4_IS_COUNTED_AS_SENSITIVE;
                mAttachInfo.decreaseSensitiveViewsCount();
            }
        }
    }
    @ViewDebug.ExportedProperty(mapping = {
            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
                to = "yesExcludeDescendants"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
                to = "noExcludeDescendants")})
    @InspectableProperty(enumMapping = {
            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
                    name = "yesExcludeDescendants"),
            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
                    name = "noExcludeDescendants"),
    })
    public @ContentCaptureImportance int getImportantForContentCapture() {
        return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
    }
    public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
        mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
        mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
    }
    public final boolean isImportantForContentCapture() {
        boolean isImportant;
        if ((mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED) != 0) {
            isImportant = (mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE) != 0;
            return isImportant;
        }
        isImportant = calculateIsImportantForContentCapture();
        mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
        if (isImportant) {
            mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
        }
        mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED;
        return isImportant;
    }
    private boolean calculateIsImportantForContentCapture() {
        ViewParent parent = mParent;
        while (parent instanceof View) {
            final int parentImportance = ((View) parent).getImportantForContentCapture();
            if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
                    || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
                if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
                    Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for "
                            + "content capture because parent " + parent + "'s importance is "
                            + parentImportance);
                }
                return false;
            }
            parent = parent.getParent();
        }
        final int importance = getImportantForContentCapture();
        if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
                || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
            return true;
        }
        if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
                || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
            if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
                Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for content "
                        + "capture because its importance is " + importance);
            }
            return false;
        }
        if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
            Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
                    + " on view " + this);
            return false;
        }
        if (this instanceof ViewGroup) {
            final ViewGroup group = (ViewGroup) this;
            for (int i = 0; i < group.getChildCount(); i++) {
                final View child = group.getChildAt(i);
                if (child.isImportantForContentCapture()) {
                    return true;
                }
            }
        }
        if (getAutofillHints() != null) {
            return true;
        }
        return false;
    }
    private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
        AttachInfo ai = mAttachInfo;
        if (ai != null && !ai.mReadyForContentCaptureUpdates) return;
        if (mContext.getContentCaptureOptions() == null) return;
        if (appeared) {
            final boolean isRecycledWithoutRelayout = getNotifiedContentCaptureDisappeared()
                    && getVisibility() == VISIBLE
                    && !isLayoutRequested();
            if (getVisibility() != VISIBLE || getNotifiedContentCaptureAppeared()
                    || !(isLaidOut() || isRecycledWithoutRelayout)) {
                if (DEBUG_CONTENT_CAPTURE) {
                    Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid="
                            + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
                            + ", visible=" + (getVisibility() == VISIBLE)
                            + ": alreadyNotifiedAppeared=" + getNotifiedContentCaptureAppeared()
                            + ", alreadyNotifiedDisappeared="
                            + getNotifiedContentCaptureDisappeared());
                }
                return;
            }
        } else {
            if (!getNotifiedContentCaptureAppeared() || getNotifiedContentCaptureDisappeared()) {
                if (DEBUG_CONTENT_CAPTURE) {
                    Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + ": laid="
                            + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
                            + ", visible=" + (getVisibility() == VISIBLE)
                            + ": alreadyNotifiedAppeared=" + getNotifiedContentCaptureAppeared()
                            + ", alreadyNotifiedDisappeared="
                            + getNotifiedContentCaptureDisappeared());
                }
                return;
            }
        }
        ContentCaptureSession session = getContentCaptureSession();
        if (session == null) return;
        if (!isImportantForContentCapture()) return;
        if (appeared) {
            setNotifiedContentCaptureAppeared();
            if (ai != null) {
                makeParentImportantAndNotifyAppearedEventIfNeed();
                ai.delayNotifyContentCaptureEvent(session, this, appeared);
            } else {
                if (DEBUG_CONTENT_CAPTURE) {
                    Log.w(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on appeared for " + this);
                }
            }
        } else {
            mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
            mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
            if (ai != null) {
                ai.delayNotifyContentCaptureEvent(session, this, appeared);
            } else {
                if (DEBUG_CONTENT_CAPTURE) {
                    Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
                }
            }
            if (!isTemporarilyDetached()) {
                clearTranslationState();
            }
        }
    }
    private void makeParentImportantAndNotifyAppearedEventIfNeed() {
        final ViewParent parent = getParent();
        if (parent instanceof View) {
            View p = ((View) parent);
            if (p.getNotifiedContentCaptureAppeared()) {
                return;
            }
            p.mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
        }
    }
    private void setNotifiedContentCaptureAppeared() {
        mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
        mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
    }
    protected boolean getNotifiedContentCaptureAppeared() {
        return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0;
    }
    private boolean getNotifiedContentCaptureDisappeared() {
        return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0;
    }
    public void setContentCaptureSession(@Nullable ContentCaptureSession contentCaptureSession) {
        mContentCaptureSession = contentCaptureSession;
    }
    @Nullable
    public final ContentCaptureSession getContentCaptureSession() {
        if (mContentCaptureSessionCached) {
            return mContentCaptureSession;
        }
        mContentCaptureSession = getAndCacheContentCaptureSession();
        mContentCaptureSessionCached = true;
        return mContentCaptureSession;
    }
    @Nullable
    private ContentCaptureSession getAndCacheContentCaptureSession() {
        if (mContentCaptureSession != null) {
            return mContentCaptureSession;
        }
        ContentCaptureSession session = null;
        if (mParent instanceof View) {
            session = ((View) mParent).getContentCaptureSession();
        }
        if (session == null) {
            final ContentCaptureManager ccm = mContext
                    .getSystemService(ContentCaptureManager.class);
            return ccm == null ? null : ccm.getMainContentCaptureSession();
        }
        return session;
    }
    @Nullable
    private AutofillManager getAutofillManager() {
        return mContext.getSystemService(AutofillManager.class);
    }
    final boolean isActivityDeniedForAutofillForUnimportantView() {
        final AutofillManager afm = getAutofillManager();
        if (afm == null) return false;
        return afm.isActivityDeniedForAutofill();
    }
    final boolean isMatchingAutofillableHeuristics() {
        final AutofillManager afm = getAutofillManager();
        if (afm == null) return false;
        return afm.isTriggerFillRequestOnUnimportantViewEnabled()
            ? afm.isAutofillable(this) : false;
    }
    private boolean isAutofillable() {
        if (DBG) {
            Log.d(VIEW_LOG_TAG, "isAutofillable() entered.");
        }
        if (getAutofillType() == AUTOFILL_TYPE_NONE) {
            if (DBG) {
                Log.d(VIEW_LOG_TAG, "getAutofillType() returns AUTOFILL_TYPE_NONE");
            }
            return false;
        }
        final AutofillManager afm = getAutofillManager();
        if (afm == null) {
            if (DBG) {
                Log.d(VIEW_LOG_TAG, "AutofillManager is null");
            }
            return false;
        }
        if (getAutofillViewId() <= LAST_APP_AUTOFILL_ID) {
            if (DBG) {
                Log.d(VIEW_LOG_TAG, "getAutofillViewId()<=LAST_APP_AUTOFILL_ID");
            }
            return false;
        }
        if ((isImportantForAutofill() && afm.isTriggerFillRequestOnFilteredImportantViewsEnabled())
                || (!isImportantForAutofill()
                    && afm.isTriggerFillRequestOnUnimportantViewEnabled())) {
            if (DBG) {
                Log.d(VIEW_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill()
                        + "afm.isAutofillable(): " + afm.isAutofillable(this));
            }
            return afm.isAutofillable(this) ? true : notifyAugmentedAutofillIfNeeded(afm);
        }
        if (DBG) {
            Log.d(VIEW_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill());
        }
        return isImportantForAutofill() ? true : notifyAugmentedAutofillIfNeeded(afm);
    }
    private boolean notifyAugmentedAutofillIfNeeded(AutofillManager afm) {
        final AutofillOptions options = mContext.getAutofillOptions();
        if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
            return false;
        }
        afm.notifyViewEnteredForAugmentedAutofill(this);
        return true;
    }
    public boolean canNotifyAutofillEnterExitEvent() {
        if (DBG) {
            Log.d(VIEW_LOG_TAG, "canNotifyAutofillEnterExitEvent() entered. "
                    + " isAutofillable(): " + isAutofillable()
                    + " isAttachedToWindow(): " + isAttachedToWindow());
        }
        return isAutofillable() && isAttachedToWindow();
    }
    private void populateVirtualStructure(ViewStructure structure,
            AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
            boolean forAutofill) {
        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
                null, null, info.getViewIdResourceName());
        Rect rect = structure.getTempRect();
        info.getBoundsInParent(rect);
        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
        structure.setVisibility(VISIBLE);
        structure.setEnabled(info.isEnabled());
        if (info.isClickable()) {
            structure.setClickable(true);
        }
        if (info.isFocusable()) {
            structure.setFocusable(true);
        }
        if (info.isFocused()) {
            structure.setFocused(true);
        }
        if (info.isAccessibilityFocused()) {
            structure.setAccessibilityFocused(true);
        }
        if (info.isSelected()) {
            structure.setSelected(true);
        }
        if (info.isLongClickable()) {
            structure.setLongClickable(true);
        }
        if (info.isCheckable()) {
            structure.setCheckable(true);
            if (info.isChecked()) {
                structure.setChecked(true);
            }
        }
        if (info.isContextClickable()) {
            structure.setContextClickable(true);
        }
        if (forAutofill) {
            structure.setAutofillId(new AutofillId(getAutofillId(),
                    AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
        }
        if (getViewCredentialHandler() != null) {
            structure.setPendingCredentialRequest(
                    getViewCredentialHandler().getRequest(),
                    getViewCredentialHandler().getCallback());
        }
        CharSequence cname = info.getClassName();
        structure.setClassName(cname != null ? cname.toString() : null);
        structure.setContentDescription(info.getContentDescription());
        if (forAutofill) {
            final int maxTextLength = info.getMaxTextLength();
            if (maxTextLength != -1) {
                structure.setMaxTextLength(maxTextLength);
            }
            structure.setHint(info.getHintText());
        }
        CharSequence text = info.getText();
        boolean hasText = text != null || info.getError() != null;
        if (hasText) {
            structure.setText(text, info.getTextSelectionStart(), info.getTextSelectionEnd());
        }
        if (forAutofill) {
            if (info.isEditable()) {
                structure.setDataIsSensitive(true);
                if (hasText) {
                    structure.setAutofillType(AUTOFILL_TYPE_TEXT);
                    structure.setAutofillValue(AutofillValue.forText(text));
                }
                int inputType = info.getInputType();
                if (inputType == 0 && info.isPassword()) {
                    inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
                }
                structure.setInputType(inputType);
            } else {
                structure.setDataIsSensitive(false);
            }
        }
        final int NCHILDREN = info.getChildCount();
        if (NCHILDREN > 0) {
            structure.setChildCount(NCHILDREN);
            for (int i=0; i<NCHILDREN; i++) {
                if (AccessibilityNodeInfo.getVirtualDescendantId(info.getChildNodeIds().get(i))
                        == AccessibilityNodeProvider.HOST_VIEW_ID) {
                    Log.e(VIEW_LOG_TAG, "Virtual view pointing to its host. Ignoring");
                    continue;
                }
                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
                if (cinfo != null) {
                    ViewStructure child = structure.newChild(i);
                    populateVirtualStructure(child, provider, cinfo, forAutofill);
                    cinfo.recycle();
                }
            }
        }
    }
    public void dispatchProvideStructure(ViewStructure structure) {
    }
    public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
            @AutofillFlags int flags) {
        dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
    }
    private void dispatchProvideStructure(@NonNull ViewStructure structure,
            @ViewStructureType int viewFor, @AutofillFlags int flags) {
        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
            structure.setAutofillId(getAutofillId());
            onProvideAutofillStructure(structure, flags);
            onProvideAutofillVirtualStructure(structure, flags);
        } else if (!isAssistBlocked()) {
            onProvideStructure(structure);
            onProvideVirtualStructure(structure);
        } else {
            structure.setClassName(getAccessibilityClassName().toString());
            structure.setAssistBlocked(true);
        }
    }
    public void dispatchInitialProvideContentCaptureStructure() {
        AttachInfo ai = mAttachInfo;
        if (ai == null) {
            Log.w(CONTENT_CAPTURE_LOG_TAG,
                    "dispatchProvideContentCaptureStructure(): no AttachInfo for " + this);
            return;
        }
        ContentCaptureManager ccm = ai.mContentCaptureManager;
        if (ccm == null) {
            Log.w(CONTENT_CAPTURE_LOG_TAG, "dispatchProvideContentCaptureStructure(): "
                    + "no ContentCaptureManager for " + this);
            return;
        }
        ai.mReadyForContentCaptureUpdates = true;
        if (!isImportantForContentCapture()) {
            if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
                Log.d(CONTENT_CAPTURE_LOG_TAG,
                        "dispatchProvideContentCaptureStructure(): decorView is not important");
            }
            return;
        }
        ai.mContentCaptureManager = ccm;
        ContentCaptureSession session = getContentCaptureSession();
        if (session == null) {
            if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
                Log.d(CONTENT_CAPTURE_LOG_TAG,
                        "dispatchProvideContentCaptureStructure(): no session for " + this);
            }
            return;
        }
        try {
            dispatchProvideContentCaptureStructure();
        } finally {
        }
    }
    void dispatchProvideContentCaptureStructure() {
        ContentCaptureSession session = getContentCaptureSession();
        if (session != null) {
            ViewStructure structure = session.newViewStructure(this);
            setNotifiedContentCaptureAppeared();
            session.notifyViewAppeared(structure);
        }
    }
    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
        if (mAttachInfo == null) {
            return;
        }
        Rect bounds = mAttachInfo.mTmpInvalRect;
        getDrawingRect(bounds);
        info.setBoundsInParent(bounds);
        getBoundsOnScreen(bounds, true);
        info.setBoundsInScreen(bounds);
        getBoundsInWindow(bounds, true);
        info.setBoundsInWindow(bounds);
        ViewParent parent = getParentForAccessibility();
        if (parent instanceof View) {
            info.setParent((View) parent);
        }
        if (mID != View.NO_ID) {
            View rootView = getRootView();
            if (rootView == null) {
                rootView = this;
            }
            View label = rootView.findLabelForView(this, mID);
            if (label != null) {
                info.setLabeledBy(label);
            }
            if ((mAttachInfo.mAccessibilityFetchFlags
                    & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS) != 0
                    && Resources.resourceHasPackage(mID)) {
                try {
                    String viewId = getResources().getResourceName(mID);
                    info.setViewIdResourceName(viewId);
                } catch (Resources.NotFoundException nfe) {
                }
            }
        }
        if (mLabelForId != View.NO_ID) {
            View rootView = getRootView();
            if (rootView == null) {
                rootView = this;
            }
            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
            if (labeled != null) {
                info.setLabelFor(labeled);
            }
        }
        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
            View rootView = getRootView();
            if (rootView == null) {
                rootView = this;
            }
            View next = rootView.findViewInsideOutShouldExist(this,
                    mAccessibilityTraversalBeforeId);
            if (next != null && next.includeForAccessibility()) {
                info.setTraversalBefore(next);
            }
        }
        if (mAccessibilityTraversalAfterId != View.NO_ID) {
            View rootView = getRootView();
            if (rootView == null) {
                rootView = this;
            }
            View next = rootView.findViewInsideOutShouldExist(this,
                    mAccessibilityTraversalAfterId);
            if (next != null && next.includeForAccessibility()) {
                info.setTraversalAfter(next);
            }
        }
        info.setVisibleToUser(isVisibleToUser());
        info.setImportantForAccessibility(isImportantForAccessibility());
        info.setAccessibilityDataSensitive(isAccessibilityDataSensitive());
        info.setPackageName(mContext.getPackageName());
        info.setClassName(getAccessibilityClassName());
        info.setStateDescription(getStateDescription());
        info.setContentDescription(getContentDescription());
        info.setEnabled(isEnabled());
        info.setClickable(isClickable());
        info.setFocusable(isFocusable());
        info.setScreenReaderFocusable(isScreenReaderFocusable());
        info.setFocused(isFocused());
        info.setAccessibilityFocused(isAccessibilityFocused());
        info.setSelected(isSelected());
        info.setLongClickable(isLongClickable());
        info.setContextClickable(isContextClickable());
        info.setLiveRegion(getAccessibilityLiveRegion());
        if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) {
            info.setTooltipText(mTooltipInfo.mTooltipText);
            info.addAction((mTooltipInfo.mTooltipPopup == null)
                    ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP
                    : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP);
        }
        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
        if (isFocusable()) {
            if (isFocused()) {
                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
            } else {
                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
            }
        }
        if (!isAccessibilityFocused()) {
            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
        } else {
            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
        }
        if (isClickable() && isEnabled()) {
            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
        }
        if (isLongClickable() && isEnabled()) {
            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
        }
        if (isContextClickable() && isEnabled()) {
            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
        }
        CharSequence text = getIterableTextForAccessibility();
        if (text != null && text.length() > 0) {
            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
        }
        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
        populateAccessibilityNodeInfoDrawingOrderInParent(info);
        info.setPaneTitle(mAccessibilityPaneTitle);
        info.setHeading(isAccessibilityHeading());
        if (mTouchDelegate != null) {
            info.setTouchDelegateInfo(mTouchDelegate.getTouchDelegateInfo());
        }
        if (startedSystemDragForAccessibility()) {
            info.addAction(AccessibilityAction.ACTION_DRAG_CANCEL);
        }
        if (canAcceptAccessibilityDrop()) {
            info.addAction(AccessibilityAction.ACTION_DRAG_DROP);
        }
    }
    public void addExtraDataToAccessibilityNodeInfo(
            @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
            @Nullable Bundle arguments) {
    }
    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
            info.setDrawingOrder(0);
            return;
        }
        int drawingOrderInParent = 1;
        View viewAtDrawingLevel = this;
        final ViewParent parent = getParentForAccessibility();
        while (viewAtDrawingLevel != parent) {
            final ViewParent currentParent = viewAtDrawingLevel.getParent();
            if (!(currentParent instanceof ViewGroup)) {
                drawingOrderInParent = 0;
                break;
            } else {
                final ViewGroup parentGroup = (ViewGroup) currentParent;
                final int childCount = parentGroup.getChildCount();
                if (childCount > 1) {
                    List<View> preorderedList = parentGroup.buildOrderedChildList();
                    if (preorderedList != null) {
                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
                        for (int i = 0; i < childDrawIndex; i++) {
                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
                        }
                        preorderedList.clear();
                    } else {
                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
                        if (childDrawIndex != 0) {
                            for (int i = 0; i < numChildrenToIterate; i++) {
                                final int otherDrawIndex = (customOrder ?
                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
                                if (otherDrawIndex < childDrawIndex) {
                                    drawingOrderInParent +=
                                            numViewsForAccessibility(parentGroup.getChildAt(i));
                                }
                            }
                        }
                    }
                }
            }
            viewAtDrawingLevel = (View) currentParent;
        }
        info.setDrawingOrder(drawingOrderInParent);
    }
    private static int numViewsForAccessibility(View view) {
        if (view != null) {
            if (view.includeForAccessibility()) {
                return 1;
            } else if (view instanceof ViewGroup) {
                return ((ViewGroup) view).getNumChildrenForAccessibility();
            }
        }
        return 0;
    }
    private View findLabelForView(View view, int labeledId) {
        if (mMatchLabelForPredicate == null) {
            mMatchLabelForPredicate = new MatchLabelForPredicate();
        }
        mMatchLabelForPredicate.mLabeledId = labeledId;
        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
    }
    public boolean isVisibleToUserForAutofill(int virtualId) {
        if (mContext.isAutofillCompatibilityEnabled()) {
            final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
            if (provider != null) {
                final AccessibilityNodeInfo node = provider.createAccessibilityNodeInfo(virtualId);
                if (node != null) {
                    return node.isVisibleToUser();
                }
            } else {
                Log.w(VIEW_LOG_TAG, "isVisibleToUserForAutofill(" + virtualId + "): no provider");
            }
            return false;
        }
        return true;
    }
    @UnsupportedAppUsage
    public boolean isVisibleToUser() {
        return isVisibleToUser(null);
    }
    @UnsupportedAppUsage(trackingBug = 171933273)
    protected boolean isVisibleToUser(Rect boundInView) {
        if (mAttachInfo != null) {
            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
                return false;
            }
            Object current = this;
            while (current instanceof View) {
                View view = (View) current;
                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
                        view.getVisibility() != VISIBLE) {
                    return false;
                }
                current = view.mParent;
            }
            Rect visibleRect = mAttachInfo.mTmpInvalRect;
            Point offset = mAttachInfo.mPoint;
            if (!getGlobalVisibleRect(visibleRect, offset)) {
                return false;
            }
            if (boundInView != null) {
                visibleRect.offset(-offset.x, -offset.y);
                return boundInView.intersect(visibleRect);
            }
            return true;
        }
        return false;
    }
    public AccessibilityDelegate getAccessibilityDelegate() {
        return mAccessibilityDelegate;
    }
    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
        mAccessibilityDelegate = delegate;
    }
    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
        if (mAccessibilityDelegate != null) {
            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
        } else {
            return null;
        }
    }
    @UnsupportedAppUsage
    public int getAccessibilityViewId() {
        if (mAccessibilityViewId == NO_ID) {
            mAccessibilityViewId = sNextAccessibilityViewId++;
        }
        return mAccessibilityViewId;
    }
    public int getAutofillViewId() {
        if (mAutofillViewId == NO_ID) {
            mAutofillViewId = mContext.getNextAutofillId();
        }
        return mAutofillViewId;
    }
    public int getAccessibilityWindowId() {
        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
                : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
    }
    @ViewDebug.ExportedProperty(category = "accessibility")
    public final @Nullable CharSequence getStateDescription() {
        return mStateDescription;
    }
    @ViewDebug.ExportedProperty(category = "accessibility")
    @InspectableProperty
    public CharSequence getContentDescription() {
        return mContentDescription;
    }
    @RemotableViewMethod
    public void setStateDescription(@Nullable CharSequence stateDescription) {
        if (mStateDescription == null) {
            if (stateDescription == null) {
                return;
            }
        } else if (mStateDescription.equals(stateDescription)) {
            return;
        }
        mStateDescription = stateDescription;
        if (!TextUtils.isEmpty(stateDescription)
                && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
        }
        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
            AccessibilityEvent event = AccessibilityEvent.obtain();
            event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
            event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION);
            sendAccessibilityEventUnchecked(event);
        }
    }
    @RemotableViewMethod
    public void setContentDescription(CharSequence contentDescription) {
        if (mContentDescription == null) {
            if (contentDescription == null) {
                return;
            }
        } else if (mContentDescription.equals(contentDescription)) {
            return;
        }
        mContentDescription = contentDescription;
        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
            notifySubtreeAccessibilityStateChangedIfNeeded();
        } else {
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
        }
    }
    @RemotableViewMethod
    public void setAccessibilityTraversalBefore(@IdRes int beforeId) {
        if (mAccessibilityTraversalBeforeId == beforeId) {
            return;
        }
        mAccessibilityTraversalBeforeId = beforeId;
        notifyViewAccessibilityStateChangedIfNeeded(
                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
    }
    @IdRes
    @InspectableProperty
    public int getAccessibilityTraversalBefore() {
        return mAccessibilityTraversalBeforeId;
    }
    @RemotableViewMethod
    public void setAccessibilityTraversalAfter(@IdRes int afterId) {
        if (mAccessibilityTraversalAfterId == afterId) {
            return;
        }
        mAccessibilityTraversalAfterId = afterId;
        notifyViewAccessibilityStateChangedIfNeeded(
                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
    }
    @IdRes
    @InspectableProperty
    public int getAccessibilityTraversalAfter() {
        return mAccessibilityTraversalAfterId;
    }
    @IdRes
    @ViewDebug.ExportedProperty(category = "accessibility")
    @InspectableProperty
    public int getLabelFor() {
        return mLabelForId;
    }
    @RemotableViewMethod
    public void setLabelFor(@IdRes int id) {
        if (mLabelForId == id) {
            return;
        }
        mLabelForId = id;
        if (mLabelForId != View.NO_ID
                && mID == View.NO_ID) {
            mID = generateViewId();
        }
        notifyViewAccessibilityStateChangedIfNeeded(
                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
    }
    @CallSuper
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    protected void onFocusLost() {
        resetPressedState();
    }
    private void resetPressedState() {
        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
            return;
        }
        if (isPressed()) {
            setPressed(false);
            if (!mHasPerformedLongPress) {
                removeLongPressCallback();
            }
        }
    }
    @ViewDebug.ExportedProperty(category = "focus")
    @InspectableProperty(hasAttributeId = false)
    public boolean isFocused() {
        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
    }
    public View findFocus() {
        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
    }
    @InspectableProperty(name = "isScrollContainer")
    public boolean isScrollContainer() {
        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
    }
    public void setScrollContainer(boolean isScrollContainer) {
        if (isScrollContainer) {
            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
                mAttachInfo.mScrollContainers.add(this);
                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
            }
            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
        } else {
            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
                mAttachInfo.mScrollContainers.remove(this);
            }
            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
        }
    }
    @Deprecated
    @DrawingCacheQuality
    @InspectableProperty(enumMapping = {
            @EnumEntry(value = DRAWING_CACHE_QUALITY_LOW, name = "low"),
            @EnumEntry(value = DRAWING_CACHE_QUALITY_HIGH, name = "high"),
            @EnumEntry(value = DRAWING_CACHE_QUALITY_AUTO, name = "auto")
    })
    public int getDrawingCacheQuality() {
        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
    }
    @Deprecated
    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
    }
    @InspectableProperty
    public boolean getKeepScreenOn() {
        return (mViewFlags & KEEP_SCREEN_ON) != 0;
    }
    public void setKeepScreenOn(boolean keepScreenOn) {
        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
    }
    @IdRes
    @InspectableProperty(name = "nextFocusLeft")
    public int getNextFocusLeftId() {
        return mNextFocusLeftId;
    }
    public void setNextFocusLeftId(@IdRes int nextFocusLeftId) {
        mNextFocusLeftId = nextFocusLeftId;
    }
    @IdRes
    @InspectableProperty(name = "nextFocusRight")
    public int getNextFocusRightId() {
        return mNextFocusRightId;
    }
    public void setNextFocusRightId(@IdRes int nextFocusRightId) {
        mNextFocusRightId = nextFocusRightId;
    }
    @IdRes
    @InspectableProperty(name = "nextFocusUp")
    public int getNextFocusUpId() {
        return mNextFocusUpId;
    }
    public void setNextFocusUpId(@IdRes int nextFocusUpId) {
        mNextFocusUpId = nextFocusUpId;
    }
    @IdRes
    @InspectableProperty(name = "nextFocusDown")
    public int getNextFocusDownId() {
        return mNextFocusDownId;
    }
    public void setNextFocusDownId(@IdRes int nextFocusDownId) {
        mNextFocusDownId = nextFocusDownId;
    }
    @IdRes
    @InspectableProperty(name = "nextFocusForward")
    public int getNextFocusForwardId() {
        return mNextFocusForwardId;
    }
    public void setNextFocusForwardId(@IdRes int nextFocusForwardId) {
        mNextFocusForwardId = nextFocusForwardId;
    }
    @IdRes
    @InspectableProperty(name = "nextClusterForward")
    public int getNextClusterForwardId() {
        return mNextClusterForwardId;
    }
    public void setNextClusterForwardId(@IdRes int nextClusterForwardId) {
        mNextClusterForwardId = nextClusterForwardId;
    }
    public boolean isShown() {
        View current = this;
        do {
            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
                return false;
            }
            ViewParent parent = current.mParent;
            if (parent == null) {
                return false;            }
            if (!(parent instanceof View)) {
                return true;
            }
            current = (View) parent;
        } while (current != null);
        return false;
    }
    private boolean detached() {
        View current = this;
        do {
            if ((current.mPrivateFlags4 & PFLAG4_DETACHED) != 0) {
                return true;
            }
            ViewParent parent = current.mParent;
            if (parent == null) {
                return false;
            }
            if (!(parent instanceof View)) {
                return false;
            }
            current = (View) parent;
        } while (current != null);
        return false;
    }
    @Deprecated
    protected boolean fitSystemWindows(Rect insets) {
        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
            if (insets == null) {
                return false;
            }
            try {
                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
            } finally {
                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
            }
        } else {
            return fitSystemWindowsInt(insets);
        }
    }
    private boolean fitSystemWindowsInt(Rect insets) {
        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
            Rect localInsets = sThreadLocal.get();
            boolean res = computeFitSystemWindows(insets, localInsets);
            applyInsets(localInsets);
            return res;
        }
        return false;
    }
    private void applyInsets(Rect insets) {
        mUserPaddingStart = UNDEFINED_PADDING;
        mUserPaddingEnd = UNDEFINED_PADDING;
        mUserPaddingLeftInitial = insets.left;
        mUserPaddingRightInitial = insets.right;
        internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
    }
    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
        if ((mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
                && (mViewFlags & FITS_SYSTEM_WINDOWS) != 0) {
            return onApplyFrameworkOptionalFitSystemWindows(insets);
        }
        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
            if (fitSystemWindows(insets.getSystemWindowInsetsAsRect())) {
                return insets.consumeSystemWindowInsets();
            }
        } else {
            if (fitSystemWindowsInt(insets.getSystemWindowInsetsAsRect())) {
                return insets.consumeSystemWindowInsets();
            }
        }
        return insets;
    }
    private WindowInsets onApplyFrameworkOptionalFitSystemWindows(WindowInsets insets) {
        Rect localInsets = sThreadLocal.get();
        WindowInsets result = computeSystemWindowInsets(insets, localInsets);
        applyInsets(localInsets);
        return result;
    }
    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
        getListenerInfo().mOnApplyWindowInsetsListener = listener;
    }
    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
        try {
            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
            } else {
                return onApplyWindowInsets(insets);
            }
        } finally {
            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
        }
    }
    public void setWindowInsetsAnimationCallback(
            @Nullable WindowInsetsAnimation.Callback callback) {
        getListenerInfo().mWindowInsetsAnimationCallback = callback;
    }
    public boolean hasWindowInsetsAnimationCallback() {
        return getListenerInfo().mWindowInsetsAnimationCallback != null;
    }
    public void dispatchWindowInsetsAnimationPrepare(
            @NonNull WindowInsetsAnimation animation) {
        if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
            mListenerInfo.mWindowInsetsAnimationCallback.onPrepare(animation);
        }
    }
    @NonNull
    public Bounds dispatchWindowInsetsAnimationStart(
            @NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
        if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
            return mListenerInfo.mWindowInsetsAnimationCallback.onStart(animation, bounds);
        }
        return bounds;
    }
    @NonNull
    public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
            @NonNull List<WindowInsetsAnimation> runningAnimations) {
        if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
            return mListenerInfo.mWindowInsetsAnimationCallback.onProgress(insets,
                    runningAnimations);
        } else {
            return insets;
        }
    }
    public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
        if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
            mListenerInfo.mWindowInsetsAnimationCallback.onEnd(animation);
        }
    }
    public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
        if (rects.isEmpty() && mListenerInfo == null) return;
        final ListenerInfo info = getListenerInfo();
        if (info.mSystemGestureExclusionRects != null) {
            info.mSystemGestureExclusionRects.clear();
            info.mSystemGestureExclusionRects.addAll(rects);
        } else {
            info.mSystemGestureExclusionRects = new ArrayList<>(rects);
        }
        updatePositionUpdateListener();
        postUpdate(this::updateSystemGestureExclusionRects);
    }
    private void updatePositionUpdateListener() {
        final ListenerInfo info = getListenerInfo();
        if (getSystemGestureExclusionRects().isEmpty()
                && collectPreferKeepClearRects().isEmpty()
                && collectUnrestrictedPreferKeepClearRects().isEmpty()
                && (info.mHandwritingArea == null || !shouldTrackHandwritingArea())) {
            if (info.mPositionUpdateListener != null) {
                mRenderNode.removePositionUpdateListener(info.mPositionUpdateListener);
                info.mPositionUpdateListener = null;
                info.mPositionChangedUpdate = null;
            }
        } else {
            if (info.mPositionUpdateListener == null) {
                info.mPositionChangedUpdate = () -> {
                    updateSystemGestureExclusionRects();
                    updateKeepClearRects();
                    updateHandwritingArea();
                };
                info.mPositionUpdateListener = new RenderNode.PositionUpdateListener() {
                    @Override
                    public void positionChanged(long n, int l, int t, int r, int b) {
                        postUpdate(info.mPositionChangedUpdate);
                    }
                    @Override
                    public void positionLost(long frameNumber) {
                        postUpdate(info.mPositionChangedUpdate);
                    }
                };
                mRenderNode.addPositionUpdateListener(info.mPositionUpdateListener);
            }
        }
    }
    private void postUpdate(Runnable r) {
        final Handler h = getHandler();
        if (h != null) {
            h.postAtFrontOfQueue(r);
        }
    }
    void updateSystemGestureExclusionRects() {
        final AttachInfo ai = mAttachInfo;
        if (ai != null) {
            ai.mViewRootImpl.updateSystemGestureExclusionRectsForView(this);
        }
    }
    @NonNull
    public List<Rect> getSystemGestureExclusionRects() {
        final ListenerInfo info = mListenerInfo;
        if (info != null) {
            final List<Rect> list = info.mSystemGestureExclusionRects;
            if (list != null) {
                return list;
            }
        }
        return Collections.emptyList();
    }
    public final void setPreferKeepClear(boolean preferKeepClear) {
        getListenerInfo().mPreferKeepClear = preferKeepClear;
        updatePositionUpdateListener();
        postUpdate(this::updateKeepClearRects);
    }
    public final boolean isPreferKeepClear() {
        return mListenerInfo != null && mListenerInfo.mPreferKeepClear;
    }
    public final void setPreferKeepClearRects(@NonNull List<Rect> rects) {
        final ListenerInfo info = getListenerInfo();
        if (info.mKeepClearRects != null) {
            info.mKeepClearRects.clear();
            info.mKeepClearRects.addAll(rects);
        } else {
            info.mKeepClearRects = new ArrayList<>(rects);
        }
        updatePositionUpdateListener();
        postUpdate(this::updateKeepClearRects);
    }
    @NonNull
    public final List<Rect> getPreferKeepClearRects() {
        final ListenerInfo info = mListenerInfo;
        if (info != null && info.mKeepClearRects != null) {
            return new ArrayList(info.mKeepClearRects);
        }
        return Collections.emptyList();
    }
    @SystemApi
    @RequiresPermission(android.Manifest.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS)
    public final void setUnrestrictedPreferKeepClearRects(@NonNull List<Rect> rects) {
        final ListenerInfo info = getListenerInfo();
        if (info.mUnrestrictedKeepClearRects != null) {
            info.mUnrestrictedKeepClearRects.clear();
            info.mUnrestrictedKeepClearRects.addAll(rects);
        } else {
            info.mUnrestrictedKeepClearRects = new ArrayList<>(rects);
        }
        updatePositionUpdateListener();
        postUpdate(this::updateKeepClearRects);
    }
    @SystemApi
    @NonNull
    public final List<Rect> getUnrestrictedPreferKeepClearRects() {
        final ListenerInfo info = mListenerInfo;
        if (info != null && info.mUnrestrictedKeepClearRects != null) {
            return new ArrayList(info.mUnrestrictedKeepClearRects);
        }
        return Collections.emptyList();
    }
    void updateKeepClearRects() {
        final AttachInfo ai = mAttachInfo;
        if (ai != null) {
            ai.mViewRootImpl.updateKeepClearRectsForView(this);
        }
    }
    @NonNull
    List<Rect> collectPreferKeepClearRects() {
        ListenerInfo info = mListenerInfo;
        boolean keepClearForFocus = isFocused()
                && ViewConfiguration.get(mContext).isPreferKeepClearForFocusEnabled();
        boolean keepBoundsClear = (info != null && info.mPreferKeepClear) || keepClearForFocus;
        boolean hasCustomKeepClearRects = info != null && info.mKeepClearRects != null;
        if (!keepBoundsClear && !hasCustomKeepClearRects) {
            return Collections.emptyList();
        } else if (keepBoundsClear && !hasCustomKeepClearRects) {
            return Collections.singletonList(new Rect(0, 0, getWidth(), getHeight()));
        }
        final List<Rect> list = new ArrayList<>();
        if (keepBoundsClear) {
            list.add(new Rect(0, 0, getWidth(), getHeight()));
        }
        if (hasCustomKeepClearRects) {
            list.addAll(info.mKeepClearRects);
        }
        return list;
    }
    private void updatePreferKeepClearForFocus() {
        if (ViewConfiguration.get(mContext).isPreferKeepClearForFocusEnabled()) {
            updatePositionUpdateListener();
            post(this::updateKeepClearRects);
        }
    }
    @NonNull
    List<Rect> collectUnrestrictedPreferKeepClearRects() {
        final ListenerInfo info = mListenerInfo;
        if (info != null && info.mUnrestrictedKeepClearRects != null) {
            return info.mUnrestrictedKeepClearRects;
        }
        return Collections.emptyList();
    }
    public void setHandwritingBoundsOffsets(float offsetLeft, float offsetTop,
            float offsetRight, float offsetBottom) {
        mHandwritingBoundsOffsetLeft = offsetLeft;
        mHandwritingBoundsOffsetTop = offsetTop;
        mHandwritingBoundsOffsetRight = offsetRight;
        mHandwritingBoundsOffsetBottom = offsetBottom;
    }
    public float getHandwritingBoundsOffsetLeft() {
        return mHandwritingBoundsOffsetLeft;
    }
    public float getHandwritingBoundsOffsetTop() {
        return mHandwritingBoundsOffsetTop;
    }
    public float getHandwritingBoundsOffsetRight() {
        return mHandwritingBoundsOffsetRight;
    }
    public float getHandwritingBoundsOffsetBottom() {
        return mHandwritingBoundsOffsetBottom;
    }
    public void setHandwritingArea(@Nullable Rect rect) {
        final ListenerInfo info = getListenerInfo();
        info.mHandwritingArea = rect;
        updatePositionUpdateListener();
        postUpdate(this::updateHandwritingArea);
    }
    @Nullable
    public Rect getHandwritingArea() {
        final ListenerInfo info = mListenerInfo;
        if (info != null && info.mHandwritingArea != null) {
            return new Rect(info.mHandwritingArea);
        }
        return null;
    }
    void updateHandwritingArea() {
        if (!shouldTrackHandwritingArea()) return;
        final AttachInfo ai = mAttachInfo;
        if (ai != null) {
            ai.mViewRootImpl.getHandwritingInitiator().updateHandwritingAreasForView(this);
        }
    }
    boolean shouldInitiateHandwriting() {
        return isAutoHandwritingEnabled() || getHandwritingDelegatorCallback() != null;
    }
    public boolean shouldTrackHandwritingArea() {
        return shouldInitiateHandwriting();
    }
    public void setHandwritingDelegatorCallback(@Nullable Runnable callback) {
        mHandwritingDelegatorCallback = callback;
        if (callback != null) {
            setHandwritingArea(new Rect(0, 0, getWidth(), getHeight()));
        }
    }
    @Nullable
    public Runnable getHandwritingDelegatorCallback() {
        return mHandwritingDelegatorCallback;
    }
    public void setAllowedHandwritingDelegatePackage(@Nullable String allowedPackageName) {
        mAllowedHandwritingDelegatePackageName = allowedPackageName;
    }
    @Nullable
    public String getAllowedHandwritingDelegatePackageName() {
        return mAllowedHandwritingDelegatePackageName;
    }
    public void setIsHandwritingDelegate(boolean isHandwritingDelegate) {
        mIsHandwritingDelegate = isHandwritingDelegate;
    }
    public boolean isHandwritingDelegate() {
        return mIsHandwritingDelegate;
    }
    public void setAllowedHandwritingDelegatorPackage(@Nullable String allowedPackageName) {
        mAllowedHandwritingDelegatorPackageName = allowedPackageName;
    }
    @Nullable
    public String getAllowedHandwritingDelegatorPackageName() {
        return mAllowedHandwritingDelegatorPackageName;
    }
    @FlaggedApi(FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR)
    public void setHandwritingDelegateFlags(
            @InputMethodManager.HandwritingDelegateFlags int flags) {
        mHandwritingDelegateFlags = flags;
    }
    @FlaggedApi(FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR)
    public @InputMethodManager.HandwritingDelegateFlags int getHandwritingDelegateFlags() {
        return mHandwritingDelegateFlags;
    }
    public void getLocationInSurface(@NonNull @Size(2) int[] location) {
        getLocationInWindow(location);
        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
        }
    }
    public WindowInsets getRootWindowInsets() {
        if (mAttachInfo != null) {
        }
        return null;
    }
    public @Nullable WindowInsetsController getWindowInsetsController() {
        if (mAttachInfo != null) {
            return mAttachInfo.mViewRootImpl.getInsetsController();
        }
        ViewParent parent = getParent();
        if (parent instanceof View) {
            return ((View) parent).getWindowInsetsController();
        } else if (parent instanceof ViewRootImpl) {
            return ((ViewRootImpl) parent).getInsetsController();
        }
        return null;
    }
    @Nullable
    public final OnBackInvokedDispatcher findOnBackInvokedDispatcher() {
        ViewParent parent = getParent();
        if (parent != null) {
            return parent.findOnBackInvokedDispatcherForChild(this, this);
        }
        return null;
    }
    @Deprecated
    @UnsupportedAppUsage
    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
        WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
                outLocalInsets);
        inoutInsets.set(innerInsets.getSystemWindowInsetsAsRect());
        return innerInsets.isSystemWindowInsetsConsumed();
    }
    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
        boolean isOptionalFitSystemWindows = (mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
                || (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
        if (isOptionalFitSystemWindows && mAttachInfo != null) {
            OnContentApplyWindowInsetsListener listener =
                    mAttachInfo.mContentOnApplyWindowInsetsListener;
            if (listener == null) {
                outLocalInsets.setEmpty();
                return in;
            }
            Pair<Insets, WindowInsets> result = listener.onContentApplyWindowInsets(this, in);
            outLocalInsets.set(result.first.toRect());
            return result.second;
        } else {
            outLocalInsets.set(in.getSystemWindowInsetsAsRect());
            return in.consumeSystemWindowInsets().inset(outLocalInsets);
        }
    }
    protected boolean hasContentOnApplyWindowInsetsListener() {
        return mAttachInfo != null && mAttachInfo.mContentOnApplyWindowInsetsListener != null;
    }
    public void setFitsSystemWindows(boolean fitSystemWindows) {
        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
    }
    @ViewDebug.ExportedProperty
    @InspectableProperty
    public boolean getFitsSystemWindows() {
        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public boolean fitsSystemWindows() {
        return getFitsSystemWindows();
    }
    @Deprecated
    public void requestFitSystemWindows() {
        if (mParent != null) {
            mParent.requestFitSystemWindows();
        }
    }
    public void requestApplyInsets() {
        requestFitSystemWindows();
    }
    @UnsupportedAppUsage
    public void makeOptionalFitsSystemWindows() {
        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
    }
    public void makeFrameworkOptionalFitsSystemWindows() {
        mPrivateFlags4 |= PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS;
    }
    public boolean isFrameworkOptionalFitsSystemWindows() {
        return (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
    }
    @ViewDebug.ExportedProperty(mapping = {
        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
        @ViewDebug.IntToString(from = GONE,      to = "GONE")
    })
    @InspectableProperty(enumMapping = {
            @EnumEntry(value = VISIBLE, name = "visible"),
            @EnumEntry(value = INVISIBLE, name = "invisible"),
            @EnumEntry(value = GONE, name = "gone")
    })
    @Visibility
    public int getVisibility() {
        return mViewFlags & VISIBILITY_MASK;
    }
    @RemotableViewMethod
    public void setVisibility(@Visibility int visibility) {
        setFlags(visibility, VISIBILITY_MASK);
    }
    @ViewDebug.ExportedProperty
    @InspectableProperty
    public boolean isEnabled() {
        return (mViewFlags & ENABLED_MASK) == ENABLED;
    }
    @RemotableViewMethod
    public void setEnabled(boolean enabled) {
        if (enabled == isEnabled()) return;
        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
        refreshDrawableState();
        invalidate(true);
        if (!enabled) {
            cancelPendingInputEvents();
        }
        notifyViewAccessibilityStateChangedIfNeeded(
                AccessibilityEvent.CONTENT_CHANGE_TYPE_ENABLED);
    }
    @RemotableViewMethod
    public void setFocusable(boolean focusable) {
        setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
    }
    @RemotableViewMethod
    public void setFocusable(@Focusable int focusable) {
        if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
        }
        setFlags(focusable, FOCUSABLE_MASK);
    }
    @RemotableViewMethod
    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
        if (focusableInTouchMode) {
            setFlags(FOCUSABLE, FOCUSABLE_MASK);
        }
    }
    public void setAutofillHints(@Nullable String... autofillHints) {
        if (autofillHints == null || autofillHints.length == 0) {
            mAutofillHints = null;
        } else {
            mAutofillHints = autofillHints;
        }
        if (sensitiveContentAppProtection()) {
            if (getContentSensitivity() == CONTENT_SENSITIVITY_AUTO) {
                updateSensitiveViewsCountIfNeeded(isAggregatedVisible());
            }
        }
    }
    @TestApi
    public void setAutofilled(boolean isAutofilled, boolean hideHighlight) {
        boolean wasChanged = isAutofilled != isAutofilled();
        if (wasChanged) {
            if (isAutofilled) {
                mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
            } else {
                mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
            }
            if (hideHighlight) {
                mPrivateFlags4 |= PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
            } else {
                mPrivateFlags4 &= ~PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
            }
            invalidate();
        }
    }
    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
    }
    @ViewDebug.ExportedProperty
    @InspectableProperty
    public boolean isSoundEffectsEnabled() {
        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
    }
    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
    }
    @ViewDebug.ExportedProperty
    @InspectableProperty
    public boolean isHapticFeedbackEnabled() {
        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
    }
    @ViewDebug.ExportedProperty(category = "layout", mapping = {
        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
    })
    @InspectableProperty(hasAttributeId = false, enumMapping = {
            @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
            @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl"),
            @EnumEntry(value = LAYOUT_DIRECTION_INHERIT, name = "inherit"),
            @EnumEntry(value = LAYOUT_DIRECTION_LOCALE, name = "locale")
    })
    @LayoutDir
    public int getRawLayoutDirection() {
        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
    }
    @RemotableViewMethod
    public void setLayoutDirection(@LayoutDir int layoutDirection) {
        if (getRawLayoutDirection() != layoutDirection) {
            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
            resetRtlProperties();
            mPrivateFlags2 |=
                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
            resolveRtlPropertiesIfNeeded();
            requestLayout();
            invalidate(true);
        }
    }
    @ViewDebug.ExportedProperty(category = "layout", mapping = {
        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
    })
    @InspectableProperty(enumMapping = {
            @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
            @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl")
    })
    @ResolvedLayoutDir
    public int getLayoutDirection() {
        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
    }
    @ViewDebug.ExportedProperty(category = "layout")
    @UnsupportedAppUsage
    public boolean isLayoutRtl() {
        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
    }
    @ViewDebug.ExportedProperty(category = "layout")
    public boolean hasTransientState() {
        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
    }
    public void setHasTransientState(boolean hasTransientState) {
        final boolean oldHasTransientState = hasTransientState();
        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
                mTransientStateCount - 1;
        if (mTransientStateCount < 0) {
            mTransientStateCount = 0;
            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
                    "unmatched pair of setHasTransientState calls");
        } else if ((hasTransientState && mTransientStateCount == 1) ||
                (!hasTransientState && mTransientStateCount == 0)) {
            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
            final boolean newHasTransientState = hasTransientState();
            if (mParent != null && newHasTransientState != oldHasTransientState) {
                try {
                    mParent.childHasTransientStateChanged(this, newHasTransientState);
                } catch (AbstractMethodError e) {
                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                            " does not fully implement ViewParent", e);
                }
            }
        }
    }
    public void setHasTranslationTransientState(boolean hasTranslationTransientState) {
        if (hasTranslationTransientState) {
            mPrivateFlags4 |= PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
        } else {
            mPrivateFlags4 &= ~PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
        }
    }
    public boolean hasTranslationTransientState() {
        return (mPrivateFlags4 & PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE)
                == PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
    }
    public void clearTranslationState() {
        if (mViewTranslationCallback != null) {
            mViewTranslationCallback.onClearTranslation(this);
        }
        clearViewTranslationResponse();
        if (hasTranslationTransientState()) {
            setHasTransientState(false);
            setHasTranslationTransientState(false);
        }
    }
    public boolean isAttachedToWindow() {
        return mAttachInfo != null;
    }
    public boolean isLaidOut() {
        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
    }
    boolean isLayoutValid() {
        return isLaidOut() && ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == 0);
    }
    public void setWillNotDraw(boolean willNotDraw) {
        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    public boolean willNotDraw() {
        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
    }
    @Deprecated
    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @Deprecated
    public boolean willNotCacheDrawing() {
        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
    }
    @ViewDebug.ExportedProperty
    @InspectableProperty
    public boolean isClickable() {
        return (mViewFlags & CLICKABLE) == CLICKABLE;
    }
    public void setClickable(boolean clickable) {
        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
    }
    public void setAllowClickWhenDisabled(boolean clickableWhenDisabled) {
        if (clickableWhenDisabled) {
            mPrivateFlags4 |= PFLAG4_ALLOW_CLICK_WHEN_DISABLED;
        } else {
            mPrivateFlags4 &= ~PFLAG4_ALLOW_CLICK_WHEN_DISABLED;
        }
    }
    @InspectableProperty
    public boolean isLongClickable() {
        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
    }
    public void setLongClickable(boolean longClickable) {
        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
    }
    @InspectableProperty
    public boolean isContextClickable() {
        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
    }
    public void setContextClickable(boolean contextClickable) {
        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
    }
    private void setPressed(boolean pressed, float x, float y) {
        if (pressed) {
            drawableHotspotChanged(x, y);
        }
        setPressed(pressed);
    }
    public void setPressed(boolean pressed) {
        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
        if (pressed) {
            mPrivateFlags |= PFLAG_PRESSED;
        } else {
            mPrivateFlags &= ~PFLAG_PRESSED;
        }
        if (needsRefresh) {
            refreshDrawableState();
        }
        dispatchSetPressed(pressed);
    }
    protected void dispatchSetPressed(boolean pressed) {
    }
    @ViewDebug.ExportedProperty
    @InspectableProperty(hasAttributeId = false)
    public boolean isPressed() {
        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
    }
    public boolean isAssistBlocked() {
        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
    }
    @UnsupportedAppUsage
    public void setAssistBlocked(boolean enabled) {
        if (enabled) {
            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
        } else {
            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
        }
    }
    @InspectableProperty
    public boolean isSaveEnabled() {
        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
    }
    public void setSaveEnabled(boolean enabled) {
        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
    }
    @ViewDebug.ExportedProperty
    @InspectableProperty
    public boolean getFilterTouchesWhenObscured() {
        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
    }
    public void setFilterTouchesWhenObscured(boolean enabled) {
        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
                FILTER_TOUCHES_WHEN_OBSCURED);
        calculateAccessibilityDataSensitive();
    }
    public boolean isSaveFromParentEnabled() {
        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
    }
    public void setSaveFromParentEnabled(boolean enabled) {
        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
    }
    @ViewDebug.ExportedProperty(category = "focus")
    public final boolean isFocusable() {
        return FOCUSABLE == (mViewFlags & FOCUSABLE);
    }
    @ViewDebug.ExportedProperty(mapping = {
            @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
            @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
            @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
            }, category = "focus")
    @InspectableProperty(enumMapping = {
            @EnumEntry(value = NOT_FOCUSABLE, name = "false"),
            @EnumEntry(value = FOCUSABLE, name = "true"),
            @EnumEntry(value = FOCUSABLE_AUTO, name = "auto")
    })
    @Focusable
    public int getFocusable() {
        return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
    }
    @ViewDebug.ExportedProperty(category = "focus")
    @InspectableProperty
    public final boolean isFocusableInTouchMode() {
        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
    }
    @InspectableProperty
    public boolean isScreenReaderFocusable() {
        return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0;
    }
    public void setScreenReaderFocusable(boolean screenReaderFocusable) {
        updatePflags3AndNotifyA11yIfChanged(PFLAG3_SCREEN_READER_FOCUSABLE, screenReaderFocusable);
    }
    @InspectableProperty
    public boolean isAccessibilityHeading() {
        return (mPrivateFlags3 & PFLAG3_ACCESSIBILITY_HEADING) != 0;
    }
    public void setAccessibilityHeading(boolean isHeading) {
        updatePflags3AndNotifyA11yIfChanged(PFLAG3_ACCESSIBILITY_HEADING, isHeading);
    }
    private void updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue) {
        int pflags3 = mPrivateFlags3;
        if (newValue) {
            pflags3 |= mask;
        } else {
            pflags3 &= ~mask;
        }
        if (pflags3 != mPrivateFlags3) {
            mPrivateFlags3 = pflags3;
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
        }
    }
    public View focusSearch(@FocusRealDirection int direction) {
        if (mParent != null) {
            return mParent.focusSearch(this, direction);
        } else {
            return null;
        }
    }
    @ViewDebug.ExportedProperty(category = "focus")
    @InspectableProperty
    public final boolean isKeyboardNavigationCluster() {
        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
    }
    View findKeyboardNavigationCluster() {
        if (mParent instanceof View) {
            View cluster = ((View) mParent).findKeyboardNavigationCluster();
            if (cluster != null) {
                return cluster;
            } else if (isKeyboardNavigationCluster()) {
                return this;
            }
        }
        return null;
    }
    public void setKeyboardNavigationCluster(boolean isCluster) {
        if (isCluster) {
            mPrivateFlags3 |= PFLAG3_CLUSTER;
        } else {
            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
        }
    }
    @TestApi
    public final void setFocusedInCluster() {
        setFocusedInCluster(findKeyboardNavigationCluster());
    }
    private void setFocusedInCluster(View cluster) {
        if (this instanceof ViewGroup) {
            ((ViewGroup) this).mFocusedInCluster = null;
        }
        if (cluster == this) {
            return;
        }
        ViewParent parent = mParent;
        View child = this;
        while (parent instanceof ViewGroup) {
            ((ViewGroup) parent).mFocusedInCluster = child;
            if (parent == cluster) {
                break;
            }
            child = (View) parent;
            parent = parent.getParent();
        }
    }
    private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
        if (oldFocus != null) {
            View oldCluster = oldFocus.findKeyboardNavigationCluster();
            View cluster = findKeyboardNavigationCluster();
            if (oldCluster != cluster) {
                oldFocus.setFocusedInCluster(oldCluster);
                if (!(oldFocus.mParent instanceof ViewGroup)) {
                    return;
                }
                if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
                    ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
                } else if (oldFocus instanceof ViewGroup
                        && ((ViewGroup) oldFocus).getDescendantFocusability()
                                == ViewGroup.FOCUS_AFTER_DESCENDANTS
                        && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
                    ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
                }
            }
        }
    }
    @ViewDebug.ExportedProperty(category = "focus")
    @InspectableProperty
    public final boolean isFocusedByDefault() {
        return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
    }
    @RemotableViewMethod
    public void setFocusedByDefault(boolean isFocusedByDefault) {
        if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
            return;
        }
        if (isFocusedByDefault) {
            mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
        } else {
            mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
        }
        if (mParent instanceof ViewGroup) {
            if (isFocusedByDefault) {
                ((ViewGroup) mParent).setDefaultFocus(this);
            } else {
                ((ViewGroup) mParent).clearDefaultFocus(this);
            }
        }
    }
    boolean hasDefaultFocus() {
        return isFocusedByDefault();
    }
    public View keyboardNavigationClusterSearch(View currentCluster,
            @FocusDirection int direction) {
        if (isKeyboardNavigationCluster()) {
            currentCluster = this;
        }
        if (isRootNamespace()) {
            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
                    this, currentCluster, direction);
        } else if (mParent != null) {
            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
        }
        return null;
    }
    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
        return false;
    }
    public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
        mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
    }
    @ViewDebug.ExportedProperty(category = "focus")
    @InspectableProperty
    public final boolean getDefaultFocusHighlightEnabled() {
        return mDefaultFocusHighlightEnabled;
    }
    View findUserSetNextFocus(View root, @FocusDirection int direction) {
        switch (direction) {
            case FOCUS_LEFT:
                if (mNextFocusLeftId == View.NO_ID) return null;
                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
            case FOCUS_RIGHT:
                if (mNextFocusRightId == View.NO_ID) return null;
                return findViewInsideOutShouldExist(root, mNextFocusRightId);
            case FOCUS_UP:
                if (mNextFocusUpId == View.NO_ID) return null;
                return findViewInsideOutShouldExist(root, mNextFocusUpId);
            case FOCUS_DOWN:
                if (mNextFocusDownId == View.NO_ID) return null;
                return findViewInsideOutShouldExist(root, mNextFocusDownId);
            case FOCUS_FORWARD:
                if (mNextFocusForwardId == View.NO_ID) return null;
                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
            case FOCUS_BACKWARD: {
                if (mID == View.NO_ID) return null;
                final View rootView = root;
                final View startView = this;
                return root.findViewByPredicateInsideOut(startView,
                    t -> findViewInsideOutShouldExist(rootView, t, t.mNextFocusForwardId)
                            == startView);
            }
        }
        return null;
    }
    View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
        switch (direction) {
            case FOCUS_FORWARD:
                if (mNextClusterForwardId == View.NO_ID) return null;
                return findViewInsideOutShouldExist(root, mNextClusterForwardId);
            case FOCUS_BACKWARD: {
                if (mID == View.NO_ID) return null;
                final int id = mID;
                return root.findViewByPredicateInsideOut(this,
                        (Predicate<View>) t -> t.mNextClusterForwardId == id);
            }
        }
        return null;
    }
    private View findViewInsideOutShouldExist(View root, int id) {
        return findViewInsideOutShouldExist(root, this, id);
    }
    private View findViewInsideOutShouldExist(View root, View start, int id) {
        if (mMatchIdPredicate == null) {
            mMatchIdPredicate = new MatchIdPredicate();
        }
        mMatchIdPredicate.mId = id;
        View result = root.findViewByPredicateInsideOut(start, mMatchIdPredicate);
        if (result == null) {
            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
        }
        return result;
    }
    public ArrayList<View> getFocusables(@FocusDirection int direction) {
        ArrayList<View> result = new ArrayList<View>(24);
        addFocusables(result, direction);
        return result;
    }
    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
    }
    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
            @FocusableMode int focusableMode) {
        if (views == null) {
            return;
        }
        if (!canTakeFocus()) {
            return;
        }
        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
                && !isFocusableInTouchMode()) {
            return;
        }
        views.add(this);
    }
    public void addKeyboardNavigationClusters(
            @NonNull Collection<View> views,
            int direction) {
        if (!isKeyboardNavigationCluster()) {
            return;
        }
        if (!hasFocusable()) {
            return;
        }
        views.add(this);
    }
    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
            @FindViewFlags int flags) {
        if (getAccessibilityNodeProvider() != null) {
            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
                outViews.add(this);
            }
        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
                && (searched != null && searched.length() > 0)
                && (mContentDescription != null && mContentDescription.length() > 0)) {
            String searchedLowerCase = searched.toString().toLowerCase();
            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
                outViews.add(this);
            }
        }
    }
    public ArrayList<View> getTouchables() {
        ArrayList<View> result = new ArrayList<View>();
        addTouchables(result);
        return result;
    }
    public void addTouchables(ArrayList<View> views) {
        final int viewFlags = mViewFlags;
        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
                && (viewFlags & ENABLED_MASK) == ENABLED) {
            views.add(this);
        }
    }
    @InspectableProperty(hasAttributeId = false)
    public boolean isAccessibilityFocused() {
        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
    }
    @UnsupportedAppUsage
    public boolean requestAccessibilityFocus() {
        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
            return false;
        }
        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
            return false;
        }
        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
            ViewRootImpl viewRootImpl = getViewRootImpl();
            if (viewRootImpl != null) {
                viewRootImpl.setAccessibilityFocus(this, null);
            }
            invalidate();
            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
            return true;
        }
        return false;
    }
    @UnsupportedAppUsage
    public void clearAccessibilityFocus() {
        clearAccessibilityFocusNoCallbacks(0);
        final ViewRootImpl viewRootImpl = getViewRootImpl();
        if (viewRootImpl != null) {
            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
                viewRootImpl.setAccessibilityFocus(null, null);
            }
        }
    }
    private void sendAccessibilityHoverEvent(int eventType) {
        View source = this;
        while (true) {
            if (source.includeForAccessibility(false)) {
                source.sendAccessibilityEvent(eventType);
                return;
            }
            ViewParent parent = source.getParent();
            if (parent instanceof View) {
                source = (View) parent;
            } else {
                return;
            }
        }
    }
    void clearAccessibilityFocusNoCallbacks(int action) {
        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
            invalidate();
            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
                AccessibilityEvent event = AccessibilityEvent.obtain(
                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
                event.setAction(action);
                if (mAccessibilityDelegate != null) {
                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
                } else {
                    sendAccessibilityEventUnchecked(event);
                }
            }
            updatePreferKeepClearForFocus();
        }
    }
    public final boolean requestFocus() {
        return requestFocus(View.FOCUS_DOWN);
    }
    @TestApi
    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
        if (restoreDefaultFocus()) {
            return true;
        }
        return requestFocus(direction);
    }
    @TestApi
    public boolean restoreFocusNotInCluster() {
        return requestFocus(View.FOCUS_DOWN);
    }
    public boolean restoreDefaultFocus() {
        return requestFocus(View.FOCUS_DOWN);
    }
    public final boolean requestFocus(int direction) {
        return requestFocus(direction, null);
    }
    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
        return requestFocusNoSearch(direction, previouslyFocusedRect);
    }
    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
        if (!canTakeFocus()) {
            return false;
        }
        if (isInTouchMode() &&
            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
               return false;
        }
        if (hasAncestorThatBlocksDescendantFocus()) {
            return false;
        }
        if (!isLayoutValid()) {
            mPrivateFlags |= PFLAG_WANTS_FOCUS;
        } else {
            clearParentsWantFocus();
        }
        handleFocusGainInternal(direction, previouslyFocusedRect);
        return true;
    }
    void clearParentsWantFocus() {
        if (mParent instanceof View) {
            ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
            ((View) mParent).clearParentsWantFocus();
        }
    }
    public final boolean requestFocusFromTouch() {
        if (isInTouchMode()) {
            ViewRootImpl viewRoot = getViewRootImpl();
            if (viewRoot != null) {
                viewRoot.ensureTouchMode(false);
            }
        }
        return requestFocus(View.FOCUS_DOWN);
    }
    private boolean hasAncestorThatBlocksDescendantFocus() {
        final boolean focusableInTouchMode = isFocusableInTouchMode();
        ViewParent ancestor = mParent;
        while (ancestor instanceof ViewGroup) {
            final ViewGroup vgAncestor = (ViewGroup) ancestor;
            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
                return true;
            } else {
                ancestor = vgAncestor.getParent();
            }
        }
        return false;
    }
    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
                    to = "noHideDescendants")
        })
    @InspectableProperty(enumMapping = {
            @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_AUTO, name = "auto"),
            @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_YES, name = "yes"),
            @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO, name = "no"),
            @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
                    name = "noHideDescendants"),
    })
    public int getImportantForAccessibility() {
        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
    }
    public void setAccessibilityLiveRegion(int mode) {
        if (mode != getAccessibilityLiveRegion()) {
            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
        }
    }
    @InspectableProperty(enumMapping = {
            @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_NONE, name = "none"),
            @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_POLITE, name = "polite"),
            @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_ASSERTIVE, name = "assertive")
    })
    public int getAccessibilityLiveRegion() {
        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
    }
    public void setImportantForAccessibility(int mode) {
        final int oldMode = getImportantForAccessibility();
        if (mode != oldMode) {
            final boolean hideDescendants =
                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
                final View focusHost = findAccessibilityFocusHost(hideDescendants);
                if (focusHost != null) {
                    focusHost.clearAccessibilityFocus();
                }
            }
            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
            final boolean oldIncludeForAccessibility =
                    maySkipNotify && includeForAccessibility(false);
            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility(false)) {
                notifySubtreeAccessibilityStateChangedIfNeeded();
            } else {
                notifyViewAccessibilityStateChangedIfNeeded(
                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
            }
        }
    }
    private View findAccessibilityFocusHost(boolean searchDescendants) {
        if (isAccessibilityFocusedViewOrHost()) {
            return this;
        }
        if (searchDescendants) {
            final ViewRootImpl viewRoot = getViewRootImpl();
            if (viewRoot != null) {
                final View focusHost = viewRoot.getAccessibilityFocusedHost();
                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
                    return focusHost;
                }
            }
        }
        return null;
    }
    public boolean isImportantForAccessibility() {
        final int mode = getImportantForAccessibility();
        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
            return false;
        }
        ViewParent parent = mParent;
        while (parent instanceof View) {
            if (((View) parent).getImportantForAccessibility()
                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
                return false;
            }
            parent = parent.getParent();
        }
        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
                || getAccessibilityDelegate() != null
                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
                || isAccessibilityPane() || isAccessibilityHeading();
    }
    public ViewParent getParentForAccessibility() {
        if (mParent instanceof View) {
            View parentView = (View) mParent;
            if (parentView.includeForAccessibility()) {
                return mParent;
            } else {
                return mParent.getParentForAccessibility();
            }
        }
        return null;
    }
    @Nullable
    View getSelfOrParentImportantForA11y() {
        if (isImportantForAccessibility()) return this;
        ViewParent parent = getParentForAccessibility();
        if (parent instanceof View) return (View) parent;
        return null;
    }
    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
    }
    @UnsupportedAppUsage
    public boolean includeForAccessibility() {
        return includeForAccessibility(true);
    }
    public boolean includeForAccessibility(boolean forNodeTree) {
        if (mAttachInfo == null) {
            return false;
        }
        if (forNodeTree) {
            if (!AccessibilityManager.getInstance(mContext).isRequestFromAccessibilityTool()
                    && isAccessibilityDataSensitive()) {
                return false;
            }
        }
        return (mAttachInfo.mAccessibilityFetchFlags
                & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
                || isImportantForAccessibility();
    }
    @ViewDebug.ExportedProperty(category = "accessibility")
    public boolean isAccessibilityDataSensitive() {
        if (mInferredAccessibilityDataSensitive == ACCESSIBILITY_DATA_SENSITIVE_AUTO) {
            calculateAccessibilityDataSensitive();
        }
        return mInferredAccessibilityDataSensitive == ACCESSIBILITY_DATA_SENSITIVE_YES;
    }
    void calculateAccessibilityDataSensitive() {
        if (mExplicitAccessibilityDataSensitive != ACCESSIBILITY_DATA_SENSITIVE_AUTO) {
            mInferredAccessibilityDataSensitive = mExplicitAccessibilityDataSensitive;
        } else if (getFilterTouchesWhenObscured()) {
            mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_YES;
        } else if (mParent instanceof View && ((View) mParent).isAccessibilityDataSensitive()) {
            mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_YES;
        } else {
            mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_NO;
        }
    }
    public void setAccessibilityDataSensitive(
            @AccessibilityDataSensitive int accessibilityDataSensitive) {
        mExplicitAccessibilityDataSensitive = accessibilityDataSensitive;
        calculateAccessibilityDataSensitive();
    }
    public boolean isActionableForAccessibility() {
        return (isClickable() || isLongClickable() || isFocusable() || isContextClickable()
                || isScreenReaderFocusable());
    }
    private boolean hasListenersForAccessibility() {
        ListenerInfo info = getListenerInfo();
        return mTouchDelegate != null || info.mOnKeyListener != null
                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
                || info.mOnHoverListener != null || info.mOnDragListener != null;
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
            return;
        }
        if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE)
                && (isAccessibilityPane()
                || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)
                && isAggregatedVisible())) {
            if ((isAggregatedVisible())
                    || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) {
                final AccessibilityEvent event = AccessibilityEvent.obtain();
                onInitializeAccessibilityEvent(event);
                event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
                event.setContentChangeTypes(changeType);
                event.setSource(this);
                onPopulateAccessibilityEvent(event);
                if (mParent != null) {
                    try {
                        mParent.requestSendAccessibilityEvent(this, event);
                    } catch (AbstractMethodError e) {
                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
                                + " does not fully implement ViewParent", e);
                    }
                }
                return;
            }
        }
        if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
            final AccessibilityEvent event = AccessibilityEvent.obtain();
            event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
            event.setContentChangeTypes(changeType);
            sendAccessibilityEventUnchecked(event);
        } else if (mParent != null) {
            try {
                mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
            } catch (AbstractMethodError e) {
                Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                        " does not fully implement ViewParent", e);
            }
        }
    }
    @UnsupportedAppUsage
    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
            return;
        }
        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
            if (mParent != null) {
                try {
                    mParent.notifySubtreeAccessibilityStateChanged(
                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
                } catch (AbstractMethodError e) {
                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                            " does not fully implement ViewParent", e);
                }
            }
        }
    }
    private void notifySubtreeAccessibilityStateChangedByParentIfNeeded() {
        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
            return;
        }
        final View sendA11yEventView = (View) getParentForAccessibility();
        if (sendA11yEventView != null && sendA11yEventView.isShown()) {
            sendA11yEventView.notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
    public void setTransitionVisibility(@Visibility int visibility) {
        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
    }
    void resetSubtreeAccessibilityStateChanged() {
        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
    }
    public boolean dispatchNestedPrePerformAccessibilityAction(int action,
            @Nullable Bundle arguments) {
        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
                return true;
            }
        }
        return false;
    }
    public boolean performAccessibilityAction(int action, @Nullable Bundle arguments) {
      if (mAccessibilityDelegate != null) {
          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
      } else {
          return performAccessibilityActionInternal(action, arguments);
      }
    }
    @UnsupportedAppUsage
    public boolean performAccessibilityActionInternal(int action, @Nullable Bundle arguments) {
        if (isNestedScrollingEnabled()
                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
                || action == R.id.accessibilityActionScrollUp
                || action == R.id.accessibilityActionScrollLeft
                || action == R.id.accessibilityActionScrollDown
                || action == R.id.accessibilityActionScrollRight)) {
            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
                return true;
            }
        }
        switch (action) {
            case AccessibilityNodeInfo.ACTION_CLICK: {
                if (isClickable()) {
                    performClickInternal();
                    return true;
                }
            } break;
            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
                if (isLongClickable()) {
                    performLongClick();
                    return true;
                }
            } break;
            case AccessibilityNodeInfo.ACTION_FOCUS: {
                if (!hasFocus()) {
                    getViewRootImpl().ensureTouchMode(false);
                    return requestFocus();
                }
            } break;
            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
                if (hasFocus()) {
                    clearFocus();
                    return !isFocused();
                }
            } break;
            case AccessibilityNodeInfo.ACTION_SELECT: {
                if (!isSelected()) {
                    setSelected(true);
                    return isSelected();
                }
            } break;
            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
                if (isSelected()) {
                    setSelected(false);
                    return !isSelected();
                }
            } break;
            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
                if (!isAccessibilityFocused()) {
                    return requestAccessibilityFocus();
                }
            } break;
            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
                if (isAccessibilityFocused()) {
                    clearAccessibilityFocus();
                    return true;
                }
            } break;
            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
                if (arguments != null) {
                    final int granularity = arguments.getInt(
                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
                    final boolean extendSelection = arguments.getBoolean(
                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
                    return traverseAtGranularity(granularity, true, extendSelection);
                }
            } break;
            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
                if (arguments != null) {
                    final int granularity = arguments.getInt(
                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
                    final boolean extendSelection = arguments.getBoolean(
                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
                    return traverseAtGranularity(granularity, false, extendSelection);
                }
            } break;
            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
                CharSequence text = getIterableTextForAccessibility();
                if (text == null) {
                    return false;
                }
                final int start = (arguments != null) ? arguments.getInt(
                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
                final int end = (arguments != null) ? arguments.getInt(
                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
                if ((getAccessibilitySelectionStart() != start
                        || getAccessibilitySelectionEnd() != end)
                        && (start == end)) {
                    setAccessibilitySelection(start, end);
                    notifyViewAccessibilityStateChangedIfNeeded(
                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
                    return true;
                }
            } break;
            case R.id.accessibilityActionShowOnScreen: {
                if (mAttachInfo != null) {
                    final Rect r = mAttachInfo.mTmpInvalRect;
                    getDrawingRect(r);
                    return requestRectangleOnScreen(r, true);
                }
            } break;
            case R.id.accessibilityActionContextClick: {
                if (isContextClickable()) {
                    performContextClick();
                    return true;
                }
            } break;
            case R.id.accessibilityActionShowTooltip: {
                if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) {
                    return false;
                }
                return showLongClickTooltip(0, 0);
            }
            case R.id.accessibilityActionHideTooltip: {
                if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) {
                    return false;
                }
                hideTooltip();
                return true;
            }
            case R.id.accessibilityActionDragDrop: {
                if (!canAcceptAccessibilityDrop()) {
                    return false;
                }
                try {
                    if (mAttachInfo != null && mAttachInfo.mSession != null) {
                        final int[] location = new int[2];
                        getLocationInWindow(location);
                        final int centerX = location[0] + getWidth() / 2;
                        final int centerY = location[1] + getHeight() / 2;
                        return mAttachInfo.mSession.dropForAccessibility(mAttachInfo.mWindow,
                                centerX, centerY);
                    }
                } catch (RemoteException e) {
                    Log.e(VIEW_LOG_TAG, "Unable to drop for accessibility", e);
                }
                return false;
            }
            case R.id.accessibilityActionDragCancel: {
                if (!startedSystemDragForAccessibility()) {
                    return false;
                }
                if (mAttachInfo != null && mAttachInfo.mDragToken != null) {
                    cancelDragAndDrop();
                    return true;
                }
                return false;
            }
        }
        return false;
    }
    private boolean canAcceptAccessibilityDrop() {
        if (!canAcceptDrag()) {
            return false;
        }
        ListenerInfo li = mListenerInfo;
        return (li != null) && (li.mOnDragListener != null || li.mOnReceiveContentListener != null);
    }
    private boolean traverseAtGranularity(int granularity, boolean forward,
            boolean extendSelection) {
        CharSequence text = getIterableTextForAccessibility();
        if (text == null || text.length() == 0) {
            return false;
        }
        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
        if (iterator == null) {
            return false;
        }
        int current = getAccessibilitySelectionEnd();
        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
            current = forward ? 0 : text.length();
        }
        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
        if (range == null) {
            return false;
        }
        final int segmentStart = range[0];
        final int segmentEnd = range[1];
        int selectionStart;
        int selectionEnd;
        if (extendSelection && isAccessibilitySelectionExtendable()) {
            prepareForExtendedAccessibilitySelection();
            selectionStart = getAccessibilitySelectionStart();
            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
                selectionStart = forward ? segmentStart : segmentEnd;
            }
            selectionEnd = forward ? segmentEnd : segmentStart;
        } else {
            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
        }
        setAccessibilitySelection(selectionStart, selectionEnd);
        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
        return true;
    }
    @UnsupportedAppUsage
    public CharSequence getIterableTextForAccessibility() {
        return getContentDescription();
    }
    public boolean isAccessibilitySelectionExtendable() {
        return false;
    }
    public void prepareForExtendedAccessibilitySelection() {
        return;
    }
    public int getAccessibilitySelectionStart() {
        return mAccessibilityCursorPosition;
    }
    public int getAccessibilitySelectionEnd() {
        return getAccessibilitySelectionStart();
    }
    public void setAccessibilitySelection(int start, int end) {
        if (start ==  end && end == mAccessibilityCursorPosition) {
            return;
        }
        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
            mAccessibilityCursorPosition = start;
        } else {
            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
        }
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
    }
    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
            int fromIndex, int toIndex) {
        if (mParent == null) {
            return;
        }
        AccessibilityEvent event = AccessibilityEvent.obtain(
                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
        onInitializeAccessibilityEvent(event);
        onPopulateAccessibilityEvent(event);
        event.setFromIndex(fromIndex);
        event.setToIndex(toIndex);
        event.setAction(action);
        event.setMovementGranularity(granularity);
        mParent.requestSendAccessibilityEvent(this, event);
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public TextSegmentIterator getIteratorForGranularity(int granularity) {
        switch (granularity) {
            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
                CharSequence text = getIterableTextForAccessibility();
                if (text != null && text.length() > 0) {
                    CharacterTextSegmentIterator iterator =
                        CharacterTextSegmentIterator.getInstance(
                                mContext.getResources().getConfiguration().locale);
                    iterator.initialize(text.toString());
                    return iterator;
                }
            } break;
            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
                CharSequence text = getIterableTextForAccessibility();
                if (text != null && text.length() > 0) {
                    WordTextSegmentIterator iterator =
                        WordTextSegmentIterator.getInstance(
                                mContext.getResources().getConfiguration().locale);
                    iterator.initialize(text.toString());
                    return iterator;
                }
            } break;
            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
                CharSequence text = getIterableTextForAccessibility();
                if (text != null && text.length() > 0) {
                    ParagraphTextSegmentIterator iterator =
                        ParagraphTextSegmentIterator.getInstance();
                    iterator.initialize(text.toString());
                    return iterator;
                }
            } break;
        }
        return null;
    }
    public final boolean isTemporarilyDetached() {
        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
    }
    @CallSuper
    public void dispatchStartTemporaryDetach() {
        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
        notifyEnterOrExitForAutoFillIfNeeded(false);
        notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
        onStartTemporaryDetach();
    }
    public void onStartTemporaryDetach() {
        removeUnsetPressCallback();
        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
    }
    @CallSuper
    public void dispatchFinishTemporaryDetach() {
        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
        onFinishTemporaryDetach();
        if (hasWindowFocus() && hasFocus()) {
        }
        notifyEnterOrExitForAutoFillIfNeeded(true);
        notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
    }
    public void onFinishTemporaryDetach() {
    }
    public KeyEvent.DispatcherState getKeyDispatcherState() {
        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
    }
    public boolean dispatchKeyEventPreIme(KeyEvent event) {
        return onKeyPreIme(event.getKeyCode(), event);
    }
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
        }
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
            return true;
        }
        if (event.dispatch(this, mAttachInfo != null
                ? mAttachInfo.mKeyDispatchState : null, this)) {
            return true;
        }
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
        }
        return false;
    }
    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
        return onKeyShortcut(event.getKeyCode(), event);
    }
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (event.isTargetAccessibilityFocus()) {
            if (!isAccessibilityFocusedViewOrHost()) {
                return false;
            }
            event.setTargetAccessibilityFocus(false);
        }
        boolean result = false;
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
        }
        final int actionMasked = event.getActionMasked();
        if (actionMasked == MotionEvent.ACTION_DOWN) {
            stopNestedScroll();
        }
        if (onFilterTouchEventForSecurity(event)) {
            result = performOnTouchCallback(event);
        }
        if (!result && mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
        }
        if (actionMasked == MotionEvent.ACTION_UP ||
                actionMasked == MotionEvent.ACTION_CANCEL ||
                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
            stopNestedScroll();
        }
        return result;
    }
    private boolean performOnTouchCallback(MotionEvent event) {
        boolean handled = false;
        if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
            handled = true;
        }
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED) {
            try {
                Trace.traceBegin(TRACE_TAG_VIEW, "View.onTouchListener#onTouch");
                handled = li.mOnTouchListener.onTouch(this, event);
            } finally {
                Trace.traceEnd(TRACE_TAG_VIEW);
            }
        }
        if (handled) {
            return true;
        }
        try {
            Trace.traceBegin(TRACE_TAG_VIEW, "View#onTouchEvent");
            return onTouchEvent(event);
        } finally {
            Trace.traceEnd(TRACE_TAG_VIEW);
        }
    }
    boolean isAccessibilityFocusedViewOrHost() {
        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
                .getAccessibilityFocusedHost() == this);
    }
    protected boolean canReceivePointerEvents() {
        return (mViewFlags & VISIBILITY_MASK) == VISIBLE || getAnimation() != null;
    }
    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
            return false;
        }
        return true;
    }
    public boolean dispatchTrackballEvent(MotionEvent event) {
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
        }
        return onTrackballEvent(event);
    }
    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
        if (!hasPointerCapture()) {
            return false;
        }
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnCapturedPointerListener != null
                && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
            return true;
        }
        return onCapturedPointerEvent(event);
    }
    public boolean dispatchGenericMotionEvent(MotionEvent event) {
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
        }
        final int source = event.getSource();
        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
            final int action = event.getAction();
            if (action == MotionEvent.ACTION_HOVER_ENTER
                    || action == MotionEvent.ACTION_HOVER_MOVE
                    || action == MotionEvent.ACTION_HOVER_EXIT) {
                if (dispatchHoverEvent(event)) {
                    return true;
                }
            } else if (dispatchGenericPointerEvent(event)) {
                return true;
            }
        } else if (dispatchGenericFocusedEvent(event)) {
            return true;
        }
        if (dispatchGenericMotionEventInternal(event)) {
            return true;
        }
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
        }
        return false;
    }
    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
        final boolean isRotaryEncoderEvent = event.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER);
        if (isRotaryEncoderEvent) {
            if ((mPrivateFlags4 & PFLAG4_ROTARY_HAPTICS_DETERMINED) == 0) {
                if (ViewConfiguration.get(mContext)
                        .isViewBasedRotaryEncoderHapticScrollFeedbackEnabled()) {
                    mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_ENABLED;
                }
                mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_DETERMINED;
            }
        }
        final boolean processForRotaryScrollHaptics =
                isRotaryEncoderEvent && ((mPrivateFlags4 & PFLAG4_ROTARY_HAPTICS_ENABLED) != 0);
        if (processForRotaryScrollHaptics) {
            mPrivateFlags4 &= ~PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT;
            mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT;
        }
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnGenericMotionListener != null
                && (mViewFlags & ENABLED_MASK) == ENABLED
                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
            return true;
        }
        final boolean onGenericMotionEventResult = onGenericMotionEvent(event);
        if (processForRotaryScrollHaptics) {
            if ((mPrivateFlags4 & PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT) != 0) {
                doRotaryProgressForScrollHaptics(event);
            } else {
                doRotaryLimitForScrollHaptics(event);
            }
        }
        if (onGenericMotionEventResult) {
            return true;
        }
        final int actionButton = event.getActionButton();
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_BUTTON_PRESS:
                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
                    if (performContextClick(event.getX(), event.getY())) {
                        mInContextButtonPress = true;
                        setPressed(true, event.getX(), event.getY());
                        removeTapCallback();
                        removeLongPressCallback();
                        return true;
                    }
                }
                break;
            case MotionEvent.ACTION_BUTTON_RELEASE:
                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
                    mInContextButtonPress = false;
                    mIgnoreNextUpEvent = true;
                }
                break;
        }
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
        }
        return false;
    }
    protected boolean dispatchHoverEvent(MotionEvent event) {
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnHoverListener != null
                && (mViewFlags & ENABLED_MASK) == ENABLED
                && li.mOnHoverListener.onHover(this, event)) {
            return true;
        }
        return onHoverEvent(event);
    }
    protected boolean hasHoveredChild() {
        return false;
    }
    protected boolean pointInHoveredChild(MotionEvent event) {
        return false;
    }
    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
        return false;
    }
    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
        return false;
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public final boolean dispatchPointerEvent(MotionEvent event) {
        if (event.isTouchEvent()) {
            return dispatchTouchEvent(event);
        } else {
            return dispatchGenericMotionEvent(event);
        }
    }
    public void dispatchWindowFocusChanged(boolean hasFocus) {
        onWindowFocusChanged(hasFocus);
    }
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        if (!hasWindowFocus) {
            if (isPressed()) {
                setPressed(false);
            }
            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
            if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
            }
            removeLongPressCallback();
            removeTapCallback();
            onFocusLost();
        } else if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
            ViewRootImpl viewRoot = getViewRootImpl();
            if (viewRoot != null && initiationWithoutInputConnection() && onCheckIsTextEditor()) {
                viewRoot.getHandwritingInitiator().onEditorFocused(this);
            }
        }
        refreshDrawableState();
    }
    public boolean hasWindowFocus() {
        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
    }
    public boolean hasImeFocus() {
        return getViewRootImpl() != null && getViewRootImpl().getImeFocusController().hasImeFocus();
    }
    protected void dispatchVisibilityChanged(@NonNull View changedView,
            @Visibility int visibility) {
        onVisibilityChanged(changedView, visibility);
    }
    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
    }
    public void dispatchDisplayHint(@Visibility int hint) {
        onDisplayHint(hint);
    }
    protected void onDisplayHint(@Visibility int hint) {
    }
    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
        onWindowVisibilityChanged(visibility);
    }
    protected void onWindowVisibilityChanged(@Visibility int visibility) {
        if (visibility == VISIBLE) {
            initialAwakenScrollBars();
        }
    }
    public boolean isAggregatedVisible() {
        return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
    }
    boolean dispatchVisibilityAggregated(boolean isVisible) {
        final boolean thisVisible = getVisibility() == VISIBLE;
        if (thisVisible || !isVisible) {
            onVisibilityAggregated(isVisible);
        }
        return thisVisible && isVisible;
    }
    @CallSuper
    public void onVisibilityAggregated(boolean isVisible) {
        boolean oldVisible = isAggregatedVisible();
        mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
                : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
        if (isVisible && mAttachInfo != null) {
            initialAwakenScrollBars();
        }
        final Drawable dr = mBackground;
        if (dr != null && isVisible != dr.isVisible()) {
            dr.setVisible(isVisible, false);
        }
        final Drawable hl = mDefaultFocusHighlight;
        if (hl != null && isVisible != hl.isVisible()) {
            hl.setVisible(isVisible, false);
        }
        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
        if (fg != null && isVisible != fg.isVisible()) {
            fg.setVisible(isVisible, false);
        }
        notifyAutofillManagerViewVisibilityChanged(isVisible);
        if (isVisible != oldVisible) {
            if (isAccessibilityPane()) {
                notifyViewAccessibilityStateChangedIfNeeded(isVisible
                        ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
                        : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
            }
            notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
            updateSensitiveViewsCountIfNeeded(isVisible);
            if (!getSystemGestureExclusionRects().isEmpty()) {
                postUpdate(this::updateSystemGestureExclusionRects);
            }
            if (!collectPreferKeepClearRects().isEmpty()) {
                postUpdate(this::updateKeepClearRects);
            }
        }
    }
    private void notifyAutofillManagerViewVisibilityChanged(boolean isVisible) {
        if (isAutofillable()) {
            AutofillManager afm = getAutofillManager();
            if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
                if (mVisibilityChangeForAutofillHandler != null) {
                    mVisibilityChangeForAutofillHandler.removeMessages(0);
                }
                if (isVisible) {
                    afm.notifyViewVisibilityChanged(this, true);
                } else {
                    if (mVisibilityChangeForAutofillHandler == null) {
                        mVisibilityChangeForAutofillHandler =
                                new VisibilityChangeForAutofillHandler(afm, this);
                    }
                    mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
                }
            }
        }
    }
    @Visibility
    public int getWindowVisibility() {
        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
    }
    public void getWindowVisibleDisplayFrame(Rect outRect) {
        if (mAttachInfo != null) {
            mAttachInfo.mViewRootImpl.getWindowVisibleDisplayFrame(outRect);
            return;
        }
        final WindowManager windowManager = mContext.getSystemService(WindowManager.class);
        final WindowMetrics metrics = windowManager.getMaximumWindowMetrics();
        final Insets insets = metrics.getWindowInsets().getInsets(
                WindowInsets.Type.navigationBars() | WindowInsets.Type.displayCutout());
        outRect.set(metrics.getBounds());
        outRect.inset(insets);
        outRect.offsetTo(0, 0);
    }
    @UnsupportedAppUsage
    @TestApi
    public void getWindowDisplayFrame(@NonNull Rect outRect) {
        if (mAttachInfo != null) {
            mAttachInfo.mViewRootImpl.getDisplayFrame(outRect);
            return;
        }
        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
        d.getRectSize(outRect);
    }
    public void dispatchConfigurationChanged(Configuration newConfig) {
        onConfigurationChanged(newConfig);
    }
    protected void onConfigurationChanged(Configuration newConfig) {
    }
    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
        performCollectViewAttributes(attachInfo, visibility);
    }
    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
                attachInfo.mKeepScreenOn = true;
            }
            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
                attachInfo.mHasSystemUiListeners = true;
            }
        }
    }
    void needGlobalAttributesUpdate(boolean force) {
        final AttachInfo ai = mAttachInfo;
        if (ai != null && !ai.mRecomputeGlobalAttributes) {
            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
                    || ai.mHasSystemUiListeners) {
                ai.mRecomputeGlobalAttributes = true;
            }
        }
    }
    @ViewDebug.ExportedProperty
    public boolean isInTouchMode() {
        if (mAttachInfo != null) {
            return mAttachInfo.mInTouchMode;
        }
        return mResources.getBoolean(com.android.internal.R.bool.config_defaultInTouchMode);
    }
    @ViewDebug.CapturedViewProperty
    @UiContext
    public final Context getContext() {
        return mContext;
    }
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        return false;
    }
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) {
            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
                return true;
            }
            if (event.getRepeatCount() == 0) {
                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
                    final float x = getWidth() / 2f;
                    final float y = getHeight() / 2f;
                    if (clickable) {
                        setPressed(true, x, y);
                    }
                    checkForLongClick(
                            ViewConfiguration.getLongPressTimeout(),
                            x,
                            y,
                            TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION);
                    return true;
                }
            }
        }
        return false;
    }
    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
        return false;
    }
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) {
            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
                return true;
            }
            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
                setPressed(false);
                if (!mHasPerformedLongPress) {
                    removeLongPressCallback();
                    if (!event.isCanceled()) {
                        return performClickInternal();
                    }
                }
            }
        }
        return false;
    }
    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
        return false;
    }
    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
        return false;
    }
    public boolean onCheckIsTextEditor() {
        return false;
    }
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        return null;
    }
    public void onInputConnectionOpenedInternal(@NonNull InputConnection inputConnection,
            @NonNull EditorInfo editorInfo, @Nullable Handler handler) {}
    public void onInputConnectionClosedInternal() {}
    public boolean checkInputConnectionProxy(View view) {
        return false;
    }
    public void createContextMenu(ContextMenu menu) {
        ContextMenuInfo menuInfo = getContextMenuInfo();
        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
        onCreateContextMenu(menu);
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnCreateContextMenuListener != null) {
            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
        }
        ((MenuBuilder)menu).setCurrentMenuInfo(null);
        if (mParent != null) {
            mParent.createContextMenu(menu);
        }
    }
    protected ContextMenuInfo getContextMenuInfo() {
        return null;
    }
    protected void onCreateContextMenu(ContextMenu menu) {
    }
    public boolean onTrackballEvent(MotionEvent event) {
        return false;
    }
    public boolean onGenericMotionEvent(MotionEvent event) {
        return false;
    }
    private boolean dispatchTouchExplorationHoverEvent(MotionEvent event) {
        final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
            return false;
        }
        final boolean oldHoveringTouchDelegate = mHoveringTouchDelegate;
        final int action = event.getActionMasked();
        boolean pointInDelegateRegion = false;
        boolean handled = false;
        final AccessibilityNodeInfo.TouchDelegateInfo info = mTouchDelegate.getTouchDelegateInfo();
        for (int i = 0; i < info.getRegionCount(); i++) {
            Region r = info.getRegionAt(i);
            if (r.contains((int) event.getX(), (int) event.getY())) {
                pointInDelegateRegion = true;
            }
        }
        if (!oldHoveringTouchDelegate) {
            if ((action == MotionEvent.ACTION_HOVER_ENTER
                    || action == MotionEvent.ACTION_HOVER_MOVE)
                    && !pointInHoveredChild(event)
                    && pointInDelegateRegion) {
                mHoveringTouchDelegate = true;
            }
        } else {
            if (action == MotionEvent.ACTION_HOVER_EXIT
                    || (action == MotionEvent.ACTION_HOVER_MOVE
                        && (pointInHoveredChild(event) || !pointInDelegateRegion))) {
                mHoveringTouchDelegate = false;
            }
        }
        switch (action) {
            case MotionEvent.ACTION_HOVER_MOVE:
                if (oldHoveringTouchDelegate && mHoveringTouchDelegate) {
                    handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
                } else if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
                    MotionEvent eventNoHistory = (event.getHistorySize() == 0)
                            ? event : MotionEvent.obtainNoHistory(event);
                    eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
                    handled = mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
                    eventNoHistory.setAction(action);
                    handled |= mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
                } else if (oldHoveringTouchDelegate && !mHoveringTouchDelegate) {
                    final boolean hoverExitPending = event.isHoverExitPending();
                    event.setHoverExitPending(true);
                    mTouchDelegate.onTouchExplorationHoverEvent(event);
                    MotionEvent eventNoHistory = (event.getHistorySize() == 0)
                            ? event : MotionEvent.obtainNoHistory(event);
                    eventNoHistory.setHoverExitPending(hoverExitPending);
                    eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
                    mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
                }                break;
            case MotionEvent.ACTION_HOVER_ENTER:
                if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
                    handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
                }
                break;
            case MotionEvent.ACTION_HOVER_EXIT:
                if (oldHoveringTouchDelegate) {
                    mTouchDelegate.onTouchExplorationHoverEvent(event);
                }
                break;
        }
        return handled;
    }
    public boolean onHoverEvent(MotionEvent event) {
        if (mTouchDelegate != null && dispatchTouchExplorationHoverEvent(event)) {
            return true;
        }
        final int action = event.getActionMasked();
        if (!mSendingHoverAccessibilityEvents) {
            if ((action == MotionEvent.ACTION_HOVER_ENTER
                    || action == MotionEvent.ACTION_HOVER_MOVE)
                    && !hasHoveredChild()
                    && pointInView(event.getX(), event.getY())) {
                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
                mSendingHoverAccessibilityEvents = true;
            }
        } else {
            if (action == MotionEvent.ACTION_HOVER_EXIT
                    || (action == MotionEvent.ACTION_HOVER_MOVE
                            && !pointInView(event.getX(), event.getY()))) {
                mSendingHoverAccessibilityEvents = false;
                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
            }
        }
        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
                && event.isFromSource(InputDevice.SOURCE_MOUSE)
                && isOnScrollbar(event.getX(), event.getY())) {
            awakenScrollBars();
        }
        if (isHoverable() || isHovered()) {
            switch (action) {
                case MotionEvent.ACTION_HOVER_ENTER:
                    setHovered(true);
                    break;
                case MotionEvent.ACTION_HOVER_EXIT:
                    setHovered(false);
                    break;
            }
            dispatchGenericMotionEventInternal(event);
            return true;
        }
        return false;
    }
    private boolean isHoverable() {
        final int viewFlags = mViewFlags;
        if ((viewFlags & ENABLED_MASK) == DISABLED) {
            return false;
        }
        return (viewFlags & CLICKABLE) == CLICKABLE
                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
    }
    @ViewDebug.ExportedProperty
    public boolean isHovered() {
        return (mPrivateFlags & PFLAG_HOVERED) != 0;
    }
    public void setHovered(boolean hovered) {
        if (hovered) {
            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
                mPrivateFlags |= PFLAG_HOVERED;
                refreshDrawableState();
                onHoverChanged(true);
            }
        } else {
            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
                mPrivateFlags &= ~PFLAG_HOVERED;
                refreshDrawableState();
                onHoverChanged(false);
            }
        }
    }
    public void onHoverChanged(boolean hovered) {
    }
    protected boolean handleScrollBarDragging(MotionEvent event) {
        if (mScrollCache == null) {
            return false;
        }
        final float x = event.getX();
        final float y = event.getY();
        final int action = event.getAction();
        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
                && action != MotionEvent.ACTION_DOWN)
                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
            return false;
        }
        switch (action) {
            case MotionEvent.ACTION_MOVE:
                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
                    return false;
                }
                if (mScrollCache.mScrollBarDraggingState
                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
                    final Rect bounds = mScrollCache.mScrollBarBounds;
                    getVerticalScrollBarBounds(bounds, null);
                    final int range = computeVerticalScrollRange();
                    final int offset = computeVerticalScrollOffset();
                    final int extent = computeVerticalScrollExtent();
                    final int thumbLength = ScrollBarUtils.getThumbLength(
                            bounds.height(), bounds.width(), extent, range);
                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
                            bounds.height(), thumbLength, extent, range, offset);
                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
                    final float maxThumbOffset = bounds.height() - thumbLength;
                    final float newThumbOffset =
                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
                    final int height = getHeight();
                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
                            && height > 0 && extent > 0) {
                        final int newY = Math.round((range - extent)
                        if (newY != getScrollY()) {
                            mScrollCache.mScrollBarDraggingPos = y;
                            setScrollY(newY);
                        }
                    }
                    return true;
                }
                if (mScrollCache.mScrollBarDraggingState
                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
                    final Rect bounds = mScrollCache.mScrollBarBounds;
                    getHorizontalScrollBarBounds(bounds, null);
                    final int range = computeHorizontalScrollRange();
                    final int offset = computeHorizontalScrollOffset();
                    final int extent = computeHorizontalScrollExtent();
                    final int thumbLength = ScrollBarUtils.getThumbLength(
                            bounds.width(), bounds.height(), extent, range);
                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
                            bounds.width(), thumbLength, extent, range, offset);
                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
                    final float maxThumbOffset = bounds.width() - thumbLength;
                    final float newThumbOffset =
                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
                    final int width = getWidth();
                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
                            && width > 0 && extent > 0) {
                        final int newX = Math.round((range - extent)
                        if (newX != getScrollX()) {
                            mScrollCache.mScrollBarDraggingPos = x;
                            setScrollX(newX);
                        }
                    }
                    return true;
                }
            case MotionEvent.ACTION_DOWN:
                if (mScrollCache.state == ScrollabilityCache.OFF) {
                    return false;
                }
                if (isOnVerticalScrollbarThumb(x, y)) {
                    mScrollCache.mScrollBarDraggingState =
                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
                    mScrollCache.mScrollBarDraggingPos = y;
                    return true;
                }
                if (isOnHorizontalScrollbarThumb(x, y)) {
                    mScrollCache.mScrollBarDraggingState =
                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
                    mScrollCache.mScrollBarDraggingPos = x;
                    return true;
                }
        }
        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
        return false;
    }
    public boolean onTouchEvent(MotionEvent event) {
        final float x = event.getX();
        final float y = event.getY();
        final int viewFlags = mViewFlags;
        final int action = event.getAction();
        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
        if ((viewFlags & ENABLED_MASK) == DISABLED
                && (mPrivateFlags4 & PFLAG4_ALLOW_CLICK_WHEN_DISABLED) == 0) {
            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
                setPressed(false);
            }
            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
            return clickable;
        }
        if (mTouchDelegate != null) {
            if (mTouchDelegate.onTouchEvent(event)) {
                return true;
            }
        }
        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
            switch (action) {
                case MotionEvent.ACTION_UP:
                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
                        handleTooltipUp();
                    }
                    if (!clickable) {
                        removeTapCallback();
                        removeLongPressCallback();
                        mInContextButtonPress = false;
                        mHasPerformedLongPress = false;
                        mIgnoreNextUpEvent = false;
                        break;
                    }
                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
                        boolean focusTaken = false;
                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
                            focusTaken = requestFocus();
                        }
                        if (prepressed) {
                            setPressed(true, x, y);
                        }
                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
                            removeLongPressCallback();
                            if (!focusTaken) {
                                if (mPerformClick == null) {
                                    mPerformClick = new PerformClick();
                                }
                                if (!post(mPerformClick)) {
                                    performClickInternal();
                                }
                            }
                        }
                        if (mUnsetPressedState == null) {
                            mUnsetPressedState = new UnsetPressedState();
                        }
                        if (prepressed) {
                            postDelayed(mUnsetPressedState,
                                    ViewConfiguration.getPressedStateDuration());
                        } else if (!post(mUnsetPressedState)) {
                            mUnsetPressedState.run();
                        }
                        removeTapCallback();
                    }
                    mIgnoreNextUpEvent = false;
                    break;
                case MotionEvent.ACTION_DOWN:
                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
                    }
                    mHasPerformedLongPress = false;
                    if (!clickable) {
                        checkForLongClick(
                                ViewConfiguration.getLongPressTimeout(),
                                x,
                                y,
                                TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
                        break;
                    }
                    if (performButtonActionOnTouchDown(event)) {
                        break;
                    }
                    boolean isInScrollingContainer = isInScrollingContainer();
                    if (isInScrollingContainer) {
                        mPrivateFlags |= PFLAG_PREPRESSED;
                        if (mPendingCheckForTap == null) {
                            mPendingCheckForTap = new CheckForTap();
                        }
                        mPendingCheckForTap.x = event.getX();
                        mPendingCheckForTap.y = event.getY();
                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
                    } else {
                        setPressed(true, x, y);
                        checkForLongClick(
                                ViewConfiguration.getLongPressTimeout(),
                                x,
                                y,
                                TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
                    }
                    break;
                case MotionEvent.ACTION_CANCEL:
                    if (clickable) {
                        setPressed(false);
                    }
                    removeTapCallback();
                    removeLongPressCallback();
                    mInContextButtonPress = false;
                    mHasPerformedLongPress = false;
                    mIgnoreNextUpEvent = false;
                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (clickable) {
                        drawableHotspotChanged(x, y);
                    }
                    final int motionClassification = event.getClassification();
                    final boolean ambiguousGesture =
                            motionClassification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE;
                    int touchSlop = mTouchSlop;
                    if (ambiguousGesture && hasPendingLongPressCallback()) {
                        if (!pointInView(x, y, touchSlop)) {
                            removeLongPressCallback();
                            long delay = (long) (ViewConfiguration.getLongPressTimeout()
                            delay -= event.getEventTime() - event.getDownTime();
                            checkForLongClick(
                                    delay,
                                    x,
                                    y,
                                    TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
                        }
                    }
                    if (!pointInView(x, y, touchSlop)) {
                        removeTapCallback();
                        removeLongPressCallback();
                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
                            setPressed(false);
                        }
                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
                    }
                    final boolean deepPress =
                            motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS;
                    if (deepPress && hasPendingLongPressCallback()) {
                        removeLongPressCallback();
                        checkForLongClick(
                                x,
                                y,
                                TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS);
                    }
                    break;
            }
            return true;
        }
        return false;
    }
    private boolean hasExpensiveMeasuresDuringInputEvent() {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo == null || attachInfo.mRootView == null) {
            return false;
        }
        if (!attachInfo.mHandlingPointerEvent) {
            return false;
        }
        final ViewFrameInfo info = attachInfo.mViewRootImpl.mViewFrameInfo;
        final long durationFromVsyncTimeMs = (System.nanoTime()
                - Choreographer.getInstance().getLastFrameTimeNanos()) / TimeUtils.NANOS_PER_MS;
        return durationFromVsyncTimeMs > 3L || info.getAndIncreaseViewMeasuredCount() > 10;
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public boolean isInScrollingContainer() {
        ViewParent p = getParent();
        while (p != null && p instanceof ViewGroup) {
            if (((ViewGroup) p).shouldDelayChildPressedState()) {
                return true;
            }
            p = p.getParent();
        }
        return false;
    }
    private void removeLongPressCallback() {
        if (mPendingCheckForLongPress != null) {
            removeCallbacks(mPendingCheckForLongPress);
        }
    }
    private boolean hasPendingLongPressCallback() {
        if (mPendingCheckForLongPress == null) {
            return false;
        }
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo == null) {
            return false;
        }
        return attachInfo.mHandler.hasCallbacks(mPendingCheckForLongPress);
    }
    @UnsupportedAppUsage
    private void removePerformClickCallback() {
        if (mPerformClick != null) {
            removeCallbacks(mPerformClick);
        }
    }
    private void removeUnsetPressCallback() {
        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
            setPressed(false);
            removeCallbacks(mUnsetPressedState);
        }
    }
    private void removeTapCallback() {
        if (mPendingCheckForTap != null) {
            mPrivateFlags &= ~PFLAG_PREPRESSED;
            removeCallbacks(mPendingCheckForTap);
        }
    }
    public void cancelLongPress() {
        removeLongPressCallback();
        removeTapCallback();
    }
    public void setTouchDelegate(TouchDelegate delegate) {
        mTouchDelegate = delegate;
    }
    public TouchDelegate getTouchDelegate() {
        return mTouchDelegate;
    }
    public final void requestUnbufferedDispatch(MotionEvent event) {
        final int action = event.getAction();
        if (mAttachInfo == null
                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
                || !event.isTouchEvent()) {
            return;
        }
        mAttachInfo.mUnbufferedDispatchRequested = true;
    }
    public final void requestUnbufferedDispatch(@InputSourceClass int source) {
        if (mUnbufferedInputSource == source) {
            return;
        }
        mUnbufferedInputSource = source;
        if (mParent != null) {
            mParent.onDescendantUnbufferedRequested();
        }
    }
    private boolean hasSize() {
        return (mBottom > mTop) && (mRight > mLeft);
    }
    private boolean canTakeFocus() {
        return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
                && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
                && ((mViewFlags & ENABLED_MASK) == ENABLED)
                && (sCanFocusZeroSized || !isLayoutValid() || hasSize());
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    void setFlags(int flags, int mask) {
        final boolean accessibilityEnabled =
                AccessibilityManager.getInstance(mContext).isEnabled();
        final boolean oldIncludeForAccessibility =
                accessibilityEnabled && includeForAccessibility(false);
        int old = mViewFlags;
        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
        int changed = mViewFlags ^ old;
        if (changed == 0) {
            return;
        }
        int privateFlags = mPrivateFlags;
        boolean shouldNotifyFocusableAvailable = false;
        int focusableChangedByAuto = 0;
        if (((mViewFlags & FOCUSABLE_AUTO) != 0)
                && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
            final int newFocus;
            if ((mViewFlags & CLICKABLE) != 0) {
                newFocus = FOCUSABLE;
            } else {
                newFocus = NOT_FOCUSABLE;
            }
            mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
            focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
            changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
        }
        if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
            if (((old & FOCUSABLE) == FOCUSABLE)
                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
                clearFocus();
                if (mParent instanceof ViewGroup) {
                    ((ViewGroup) mParent).clearFocusedInCluster();
                }
            } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
                if (mParent != null) {
                    ViewRootImpl viewRootImpl = getViewRootImpl();
                    if (!sAutoFocusableOffUIThreadWontNotifyParents
                            || focusableChangedByAuto == 0
                            || viewRootImpl == null
                            || viewRootImpl.mThread == Thread.currentThread()) {
                        shouldNotifyFocusableAvailable = canTakeFocus();
                    }
                }
            }
        }
        final int newVisibility = flags & VISIBILITY_MASK;
        if (newVisibility == VISIBLE) {
            if ((changed & VISIBILITY_MASK) != 0) {
                mPrivateFlags |= PFLAG_DRAWN;
                invalidate(true);
                needGlobalAttributesUpdate(true);
                shouldNotifyFocusableAvailable = hasSize();
            }
        }
        if ((changed & ENABLED_MASK) != 0) {
            if ((mViewFlags & ENABLED_MASK) == ENABLED) {
                shouldNotifyFocusableAvailable = canTakeFocus();
            } else {
                if (isFocused()) clearFocus();
            }
        }
        if (shouldNotifyFocusableAvailable && mParent != null) {
            mParent.focusableViewAvailable(this);
        }
        if ((changed & GONE) != 0) {
            needGlobalAttributesUpdate(false);
            requestLayout();
            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
                if (hasFocus()) {
                    clearFocus();
                    if (mParent instanceof ViewGroup) {
                        ((ViewGroup) mParent).clearFocusedInCluster();
                    }
                }
                clearAccessibilityFocus();
                destroyDrawingCache();
                if (mParent instanceof View) {
                    ((View) mParent).invalidate(true);
                }
                mPrivateFlags |= PFLAG_DRAWN;
            }
            if (mAttachInfo != null) {
                mAttachInfo.mViewVisibilityChanged = true;
            }
        }
        if ((changed & INVISIBLE) != 0) {
            needGlobalAttributesUpdate(false);
            mPrivateFlags |= PFLAG_DRAWN;
            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
                if (getRootView() != this) {
                    if (hasFocus()) {
                        clearFocus();
                        if (mParent instanceof ViewGroup) {
                            ((ViewGroup) mParent).clearFocusedInCluster();
                        }
                    }
                    clearAccessibilityFocus();
                }
            }
            if (mAttachInfo != null) {
                mAttachInfo.mViewVisibilityChanged = true;
            }
        }
        if ((changed & VISIBILITY_MASK) != 0) {
            if (newVisibility != VISIBLE && mAttachInfo != null) {
                cleanupDraw();
            }
            if (mParent instanceof ViewGroup) {
                ViewGroup parent = (ViewGroup) mParent;
                parent.onChildVisibilityChanged(this, (changed & VISIBILITY_MASK),
                        newVisibility);
                parent.invalidate(true);
            } else if (mParent != null) {
                mParent.invalidateChild(this, null);
            }
            if (mAttachInfo != null) {
                dispatchVisibilityChanged(this, newVisibility);
                if (mParent != null && getWindowVisibility() == VISIBLE &&
                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
                }
                if ((old & VISIBILITY_MASK) == VISIBLE) {
                    notifySubtreeAccessibilityStateChangedByParentIfNeeded();
                } else {
                    notifySubtreeAccessibilityStateChangedIfNeeded();
                }
            }
        }
        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
            destroyDrawingCache();
        }
        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
            destroyDrawingCache();
            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
            invalidateParentCaches();
        }
        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
            destroyDrawingCache();
            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
        }
        if ((changed & DRAW_MASK) != 0) {
            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
                if (mBackground != null
                        || mDefaultFocusHighlight != null
                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
                } else {
                    mPrivateFlags |= PFLAG_SKIP_DRAW;
                }
            } else {
                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
            }
            requestLayout();
            invalidate(true);
        }
        if ((changed & KEEP_SCREEN_ON) != 0) {
            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
                mParent.recomputeViewAttributes(this);
            }
        }
        if (accessibilityEnabled) {
            if (isAccessibilityPane()) {
                changed &= ~VISIBILITY_MASK;
            }
            if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
                    || (changed & CONTEXT_CLICKABLE) != 0) {
                if (oldIncludeForAccessibility != includeForAccessibility(false)) {
                    notifySubtreeAccessibilityStateChangedIfNeeded();
                } else {
                    notifyViewAccessibilityStateChangedIfNeeded(
                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
                }
            } else if ((changed & ENABLED_MASK) != 0) {
                notifyViewAccessibilityStateChangedIfNeeded(
                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
            }
        }
    }
    public void bringToFront() {
        if (mParent != null) {
            mParent.bringChildToFront(this);
        }
    }
    private HapticScrollFeedbackProvider getScrollFeedbackProvider() {
        if (mScrollFeedbackProvider == null) {
            mScrollFeedbackProvider = new HapticScrollFeedbackProvider(this,
        }
        return mScrollFeedbackProvider;
    }
    private void doRotaryProgressForScrollHaptics(MotionEvent rotaryEvent) {
        final float axisScrollValue = rotaryEvent.getAxisValue(MotionEvent.AXIS_SCROLL);
        final float verticalScrollFactor =
                ViewConfiguration.get(mContext).getScaledVerticalScrollFactor();
        getScrollFeedbackProvider().onScrollProgress(
                rotaryEvent.getDeviceId(), InputDevice.SOURCE_ROTARY_ENCODER,
                MotionEvent.AXIS_SCROLL, scrollAmount);
    }
    private void doRotaryLimitForScrollHaptics(MotionEvent rotaryEvent) {
        final boolean isStart = rotaryEvent.getAxisValue(MotionEvent.AXIS_SCROLL) > 0;
        getScrollFeedbackProvider().onScrollLimit(
                rotaryEvent.getDeviceId(), InputDevice.SOURCE_ROTARY_ENCODER,
                MotionEvent.AXIS_SCROLL, isStart);
    }
    private void processScrollEventForRotaryEncoderHaptics() {
        if ((mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT) != 0) {
            mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT;
            mPrivateFlags4 &= ~PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT;
        }
    }
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        notifySubtreeAccessibilityStateChangedIfNeeded();
        postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
        processScrollEventForRotaryEncoderHaptics();
        mBackgroundSizeChanged = true;
        mDefaultFocusHighlightSizeChanged = true;
        if (mForegroundInfo != null) {
            mForegroundInfo.mBoundsChanged = true;
        }
        final AttachInfo ai = mAttachInfo;
        if (ai != null) {
            ai.mViewScrollChanged = true;
        }
        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
        }
    }
    public interface OnScrollChangeListener {
        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
    }
    public interface OnLayoutChangeListener {
        void onLayoutChange(View v, int left, int top, int right, int bottom,
            int oldLeft, int oldTop, int oldRight, int oldBottom);
    }
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    }
    protected void dispatchDraw(@NonNull Canvas canvas) {
    }
    public final ViewParent getParent() {
        return mParent;
    }
    public void setScrollX(int value) {
        scrollTo(value, mScrollY);
    }
    public void setScrollY(int value) {
        scrollTo(mScrollX, value);
    }
    @InspectableProperty
    public final int getScrollX() {
        return mScrollX;
    }
    @InspectableProperty
    public final int getScrollY() {
        return mScrollY;
    }
    @ViewDebug.ExportedProperty(category = "layout")
    public final int getWidth() {
        return mRight - mLeft;
    }
    @ViewDebug.ExportedProperty(category = "layout")
    public final int getHeight() {
        return mBottom - mTop;
    }
    public void getDrawingRect(Rect outRect) {
        outRect.left = mScrollX;
        outRect.top = mScrollY;
        outRect.right = mScrollX + (mRight - mLeft);
        outRect.bottom = mScrollY + (mBottom - mTop);
    }
    public final int getMeasuredWidth() {
        return mMeasuredWidth & MEASURED_SIZE_MASK;
    }
    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
                    name = "MEASURED_STATE_TOO_SMALL"),
    })
    public final int getMeasuredWidthAndState() {
        return mMeasuredWidth;
    }
    public final int getMeasuredHeight() {
        return mMeasuredHeight & MEASURED_SIZE_MASK;
    }
    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
                    name = "MEASURED_STATE_TOO_SMALL"),
    })
    public final int getMeasuredHeightAndState() {
        return mMeasuredHeight;
    }
    public final int getMeasuredState() {
        return (mMeasuredWidth&MEASURED_STATE_MASK)
                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
    }
    public Matrix getMatrix() {
        ensureTransformationInfo();
        final Matrix matrix = mTransformationInfo.mMatrix;
        mRenderNode.getMatrix(matrix);
        return matrix;
    }
    @UnsupportedAppUsage
    public final boolean hasIdentityMatrix() {
        return mRenderNode.hasIdentityMatrix();
    }
    @UnsupportedAppUsage
    void ensureTransformationInfo() {
        if (mTransformationInfo == null) {
            mTransformationInfo = new TransformationInfo();
        }
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public final Matrix getInverseMatrix() {
        ensureTransformationInfo();
        if (mTransformationInfo.mInverseMatrix == null) {
            mTransformationInfo.mInverseMatrix = new Matrix();
        }
        final Matrix matrix = mTransformationInfo.mInverseMatrix;
        mRenderNode.getInverseMatrix(matrix);
        return matrix;
    }
    public float getCameraDistance() {
        final float dpi = mResources.getDisplayMetrics().densityDpi;
    }
    public void setCameraDistance(float distance) {
        final float dpi = mResources.getDisplayMetrics().densityDpi;
        invalidateViewProperty(true, false);
        mRenderNode.setCameraDistance(Math.abs(distance) / dpi);
        invalidateViewProperty(false, false);
        invalidateParentIfNeededAndWasQuickRejected();
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @InspectableProperty
    public float getRotation() {
        return mRenderNode.getRotationZ();
    }
    @RemotableViewMethod
    public void setRotation(float rotation) {
        if (rotation != getRotation()) {
            invalidateViewProperty(true, false);
            mRenderNode.setRotationZ(rotation);
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @InspectableProperty
    public float getRotationY() {
        return mRenderNode.getRotationY();
    }
    @RemotableViewMethod
    public void setRotationY(float rotationY) {
        if (rotationY != getRotationY()) {
            invalidateViewProperty(true, false);
            mRenderNode.setRotationY(rotationY);
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @InspectableProperty
    public float getRotationX() {
        return mRenderNode.getRotationX();
    }
    @RemotableViewMethod
    public void setRotationX(float rotationX) {
        if (rotationX != getRotationX()) {
            invalidateViewProperty(true, false);
            mRenderNode.setRotationX(rotationX);
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @InspectableProperty
    public float getScaleX() {
        return mRenderNode.getScaleX();
    }
    @RemotableViewMethod
    public void setScaleX(float scaleX) {
        if (scaleX != getScaleX()) {
            scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX");
            invalidateViewProperty(true, false);
            mRenderNode.setScaleX(scaleX);
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @InspectableProperty
    public float getScaleY() {
        return mRenderNode.getScaleY();
    }
    @RemotableViewMethod
    public void setScaleY(float scaleY) {
        if (scaleY != getScaleY()) {
            scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY");
            invalidateViewProperty(true, false);
            mRenderNode.setScaleY(scaleY);
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @InspectableProperty(name = "transformPivotX")
    public float getPivotX() {
        return mRenderNode.getPivotX();
    }
    @RemotableViewMethod
    public void setPivotX(float pivotX) {
        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
            invalidateViewProperty(true, false);
            mRenderNode.setPivotX(pivotX);
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
        }
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @InspectableProperty(name = "transformPivotY")
    public float getPivotY() {
        return mRenderNode.getPivotY();
    }
    @RemotableViewMethod
    public void setPivotY(float pivotY) {
        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
            invalidateViewProperty(true, false);
            mRenderNode.setPivotY(pivotY);
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
        }
    }
    public boolean isPivotSet() {
        return mRenderNode.isPivotExplicitlySet();
    }
    public void resetPivot() {
        if (mRenderNode.resetPivot()) {
            invalidateViewProperty(false, false);
        }
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @InspectableProperty
    public float getAlpha() {
        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
    }
    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
        if (hasOverlappingRendering) {
            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
        } else {
            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
        }
    }
    public final boolean getHasOverlappingRendering() {
        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
                hasOverlappingRendering();
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    public boolean hasOverlappingRendering() {
        return true;
    }
    @RemotableViewMethod
    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
        ensureTransformationInfo();
        if (mTransformationInfo.mAlpha != alpha) {
            setAlphaInternal(alpha);
                mPrivateFlags |= PFLAG_ALPHA_SET;
                invalidateParentCaches();
                invalidate(true);
            } else {
                mPrivateFlags &= ~PFLAG_ALPHA_SET;
                invalidateViewProperty(true, false);
                mRenderNode.setAlpha(getFinalAlpha());
            }
        }
    }
    @UnsupportedAppUsage(maxTargetSdk  = Build.VERSION_CODES.P, trackingBug = 123768435)
    boolean setAlphaNoInvalidation(float alpha) {
        ensureTransformationInfo();
        if (mTransformationInfo.mAlpha != alpha) {
            setAlphaInternal(alpha);
            if (subclassHandlesAlpha) {
                mPrivateFlags |= PFLAG_ALPHA_SET;
                return true;
            } else {
                mPrivateFlags &= ~PFLAG_ALPHA_SET;
                mRenderNode.setAlpha(getFinalAlpha());
            }
        }
        return false;
    }
    void setAlphaInternal(float alpha) {
        float oldAlpha = mTransformationInfo.mAlpha;
        mTransformationInfo.mAlpha = alpha;
        if ((alpha == 0) ^ (oldAlpha == 0)) {
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
    public void setTransitionAlpha(float alpha) {
        ensureTransformationInfo();
        if (mTransformationInfo.mTransitionAlpha != alpha) {
            mTransformationInfo.mTransitionAlpha = alpha;
            mPrivateFlags &= ~PFLAG_ALPHA_SET;
            invalidateViewProperty(true, false);
            mRenderNode.setAlpha(getFinalAlpha());
        }
    }
    private float getFinalAlpha() {
        if (mTransformationInfo != null) {
        }
        return 1;
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    public float getTransitionAlpha() {
        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
    }
    public void setForceDarkAllowed(boolean allow) {
        if (mRenderNode.setForceDarkAllowed(allow)) {
            invalidate();
        }
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @InspectableProperty
    public boolean isForceDarkAllowed() {
        return mRenderNode.isForceDarkAllowed();
    }
    @ViewDebug.CapturedViewProperty
    public final int getTop() {
        return mTop;
    }
    public final void setTop(int top) {
        if (top != mTop) {
            final boolean matrixIsIdentity = hasIdentityMatrix();
            if (matrixIsIdentity) {
                if (mAttachInfo != null) {
                    int minTop;
                    int yLoc;
                    if (top < mTop) {
                        minTop = top;
                        yLoc = top - mTop;
                    } else {
                        minTop = mTop;
                        yLoc = 0;
                    }
                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
                }
            } else {
                invalidate(true);
            }
            int width = mRight - mLeft;
            int oldHeight = mBottom - mTop;
            mTop = top;
            mRenderNode.setTop(mTop);
            sizeChange(width, mBottom - mTop, width, oldHeight);
            if (!matrixIsIdentity) {
                mPrivateFlags |= PFLAG_DRAWN;                invalidate(true);
            }
            mBackgroundSizeChanged = true;
            mDefaultFocusHighlightSizeChanged = true;
            if (mForegroundInfo != null) {
                mForegroundInfo.mBoundsChanged = true;
            }
            invalidateParentIfNeeded();
        }
    }
    @ViewDebug.CapturedViewProperty
    public final int getBottom() {
        return mBottom;
    }
    public boolean isDirty() {
        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
    }
    public final void setBottom(int bottom) {
        if (bottom != mBottom) {
            final boolean matrixIsIdentity = hasIdentityMatrix();
            if (matrixIsIdentity) {
                if (mAttachInfo != null) {
                    int maxBottom;
                    if (bottom < mBottom) {
                        maxBottom = mBottom;
                    } else {
                        maxBottom = bottom;
                    }
                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
                }
            } else {
                invalidate(true);
            }
            int width = mRight - mLeft;
            int oldHeight = mBottom - mTop;
            mBottom = bottom;
            mRenderNode.setBottom(mBottom);
            sizeChange(width, mBottom - mTop, width, oldHeight);
            if (!matrixIsIdentity) {
                mPrivateFlags |= PFLAG_DRAWN;                invalidate(true);
            }
            mBackgroundSizeChanged = true;
            mDefaultFocusHighlightSizeChanged = true;
            if (mForegroundInfo != null) {
                mForegroundInfo.mBoundsChanged = true;
            }
            invalidateParentIfNeeded();
        }
    }
    @ViewDebug.CapturedViewProperty
    public final int getLeft() {
        return mLeft;
    }
    public final void setLeft(int left) {
        if (left != mLeft) {
            mPrivateFlags4 |= PFLAG4_HAS_MOVED;
            final boolean matrixIsIdentity = hasIdentityMatrix();
            if (matrixIsIdentity) {
                if (mAttachInfo != null) {
                    int minLeft;
                    int xLoc;
                    if (left < mLeft) {
                        minLeft = left;
                        xLoc = left - mLeft;
                    } else {
                        minLeft = mLeft;
                        xLoc = 0;
                    }
                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
                }
            } else {
                invalidate(true);
            }
            int oldWidth = mRight - mLeft;
            int height = mBottom - mTop;
            mLeft = left;
            mRenderNode.setLeft(left);
            sizeChange(mRight - mLeft, height, oldWidth, height);
            if (!matrixIsIdentity) {
                mPrivateFlags |= PFLAG_DRAWN;                invalidate(true);
            }
            mBackgroundSizeChanged = true;
            mDefaultFocusHighlightSizeChanged = true;
            if (mForegroundInfo != null) {
                mForegroundInfo.mBoundsChanged = true;
            }
            invalidateParentIfNeeded();
        }
    }
    @ViewDebug.CapturedViewProperty
    public final int getRight() {
        return mRight;
    }
    public final void setRight(int right) {
        if (right != mRight) {
            final boolean matrixIsIdentity = hasIdentityMatrix();
            if (matrixIsIdentity) {
                if (mAttachInfo != null) {
                    int maxRight;
                    if (right < mRight) {
                        maxRight = mRight;
                    } else {
                        maxRight = right;
                    }
                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
                }
            } else {
                invalidate(true);
            }
            int oldWidth = mRight - mLeft;
            int height = mBottom - mTop;
            mRight = right;
            mRenderNode.setRight(mRight);
            sizeChange(mRight - mLeft, height, oldWidth, height);
            if (!matrixIsIdentity) {
                mPrivateFlags |= PFLAG_DRAWN;                invalidate(true);
            }
            mBackgroundSizeChanged = true;
            mDefaultFocusHighlightSizeChanged = true;
            if (mForegroundInfo != null) {
                mForegroundInfo.mBoundsChanged = true;
            }
            invalidateParentIfNeeded();
        }
    }
    private static float sanitizeFloatPropertyValue(float value, String propertyName) {
        return sanitizeFloatPropertyValue(value, propertyName, -Float.MAX_VALUE, Float.MAX_VALUE);
    }
    private static float sanitizeFloatPropertyValue(float value, String propertyName,
            float min, float max) {
        if (value >= min && value <= max) return value;
        if (value < min || value == Float.NEGATIVE_INFINITY) {
            if (sThrowOnInvalidFloatProperties) {
                throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
                        + value + ", the value must be >= " + min);
            }
            return min;
        }
        if (value > max || value == Float.POSITIVE_INFINITY) {
            if (sThrowOnInvalidFloatProperties) {
                throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
                        + value + ", the value must be <= " + max);
            }
            return max;
        }
        if (Float.isNaN(value)) {
            if (sThrowOnInvalidFloatProperties) {
                throw new IllegalArgumentException(
                        "Cannot set '" + propertyName + "' to Float.NaN");
            }
            return 0;        }
        throw new IllegalStateException("How do you get here?? " + value);
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    public float getX() {
        return mLeft + getTranslationX();
    }
    public void setX(float x) {
        setTranslationX(x - mLeft);
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    public float getY() {
        return mTop + getTranslationY();
    }
    public void setY(float y) {
        setTranslationY(y - mTop);
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    public float getZ() {
        return getElevation() + getTranslationZ();
    }
    public void setZ(float z) {
        setTranslationZ(z - getElevation());
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @InspectableProperty
    public float getElevation() {
        return mRenderNode.getElevation();
    }
    @RemotableViewMethod
    public void setElevation(float elevation) {
        if (elevation != getElevation()) {
            elevation = sanitizeFloatPropertyValue(elevation, "elevation");
            invalidateViewProperty(true, false);
            mRenderNode.setElevation(elevation);
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
        }
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @InspectableProperty
    public float getTranslationX() {
        return mRenderNode.getTranslationX();
    }
    @RemotableViewMethod
    public void setTranslationX(float translationX) {
        if (translationX != getTranslationX()) {
            mPrivateFlags4 |= PFLAG4_HAS_MOVED;
            invalidateViewProperty(true, false);
            mRenderNode.setTranslationX(translationX);
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @InspectableProperty
    public float getTranslationY() {
        return mRenderNode.getTranslationY();
    }
    @RemotableViewMethod
    public void setTranslationY(float translationY) {
        if (translationY != getTranslationY()) {
            mPrivateFlags4 |= PFLAG4_HAS_MOVED;
            invalidateViewProperty(true, false);
            mRenderNode.setTranslationY(translationY);
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @InspectableProperty
    public float getTranslationZ() {
        return mRenderNode.getTranslationZ();
    }
    @RemotableViewMethod
    public void setTranslationZ(float translationZ) {
        if (translationZ != getTranslationZ()) {
            translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ");
            invalidateViewProperty(true, false);
            mRenderNode.setTranslationZ(translationZ);
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
        }
    }
    public void setAnimationMatrix(@Nullable Matrix matrix) {
        invalidateViewProperty(true, false);
        mRenderNode.setAnimationMatrix(matrix);
        invalidateViewProperty(false, true);
        invalidateParentIfNeededAndWasQuickRejected();
    }
    @Nullable
    public Matrix getAnimationMatrix() {
        return mRenderNode.getAnimationMatrix();
    }
    @InspectableProperty
    public StateListAnimator getStateListAnimator() {
        return mStateListAnimator;
    }
    public void setStateListAnimator(StateListAnimator stateListAnimator) {
        if (mStateListAnimator == stateListAnimator) {
            return;
        }
        if (mStateListAnimator != null) {
            mStateListAnimator.setTarget(null);
        }
        mStateListAnimator = stateListAnimator;
        if (stateListAnimator != null) {
            stateListAnimator.setTarget(this);
            if (isAttachedToWindow()) {
                stateListAnimator.setState(getDrawableState());
            }
        }
    }
    public final boolean getClipToOutline() {
        return mRenderNode.getClipToOutline();
    }
    @RemotableViewMethod
    public void setClipToOutline(boolean clipToOutline) {
        damageInParent();
        if (getClipToOutline() != clipToOutline) {
            mRenderNode.setClipToOutline(clipToOutline);
        }
    }
    private static final int PROVIDER_BACKGROUND = 0;
    private static final int PROVIDER_NONE = 1;
    private static final int PROVIDER_BOUNDS = 2;
    private static final int PROVIDER_PADDED_BOUNDS = 3;
    private void setOutlineProviderFromAttribute(int providerInt) {
        switch (providerInt) {
            case PROVIDER_BACKGROUND:
                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
                break;
            case PROVIDER_NONE:
                setOutlineProvider(null);
                break;
            case PROVIDER_BOUNDS:
                setOutlineProvider(ViewOutlineProvider.BOUNDS);
                break;
            case PROVIDER_PADDED_BOUNDS:
                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
                break;
        }
    }
    public void setOutlineProvider(ViewOutlineProvider provider) {
        if (mOutlineProvider != provider) {
            mOutlineProvider = provider;
            invalidateOutline();
        }
    }
    @InspectableProperty
    public ViewOutlineProvider getOutlineProvider() {
        return mOutlineProvider;
    }
    public void invalidateOutline() {
        rebuildOutline();
        notifySubtreeAccessibilityStateChangedIfNeeded();
        invalidateViewProperty(false, false);
    }
    private void rebuildOutline() {
        if (mAttachInfo == null) return;
        if (mOutlineProvider == null) {
            mRenderNode.setOutline(null);
        } else {
            final Outline outline = mAttachInfo.mTmpOutline;
            outline.setEmpty();
            outline.setAlpha(1.0f);
            mOutlineProvider.getOutline(this, outline);
            mRenderNode.setOutline(outline);
        }
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    public boolean hasShadow() {
        return mRenderNode.hasShadow();
    }
    public void setOutlineSpotShadowColor(@ColorInt int color) {
        if (mRenderNode.setSpotShadowColor(color)) {
            invalidateViewProperty(true, true);
        }
    }
    @InspectableProperty
    public @ColorInt int getOutlineSpotShadowColor() {
        return mRenderNode.getSpotShadowColor();
    }
    public void setOutlineAmbientShadowColor(@ColorInt int color) {
        if (mRenderNode.setAmbientShadowColor(color)) {
            invalidateViewProperty(true, true);
        }
    }
    @InspectableProperty
    public @ColorInt int getOutlineAmbientShadowColor() {
        return mRenderNode.getAmbientShadowColor();
    }
    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
        mRenderNode.setRevealClip(shouldClip, x, y, radius);
        invalidateViewProperty(false, false);
    }
    public void getHitRect(Rect outRect) {
        if (hasIdentityMatrix() || mAttachInfo == null) {
            outRect.set(mLeft, mTop, mRight, mBottom);
        } else {
            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
            tmpRect.set(0, 0, getWidth(), getHeight());
            getMatrix().mapRect(tmpRect);            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
        }
    }
        return pointInView(localX, localY, 0);
    }
    @UnsupportedAppUsage
    public boolean pointInView(float localX, float localY, float slop) {
        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
                localY < ((mBottom - mTop) + slop);
    }
    public void getFocusedRect(Rect r) {
        getDrawingRect(r);
    }
    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
        int width = mRight - mLeft;
        int height = mBottom - mTop;
        if (width > 0 && height > 0) {
            r.set(0, 0, width, height);
            if (globalOffset != null) {
                globalOffset.set(-mScrollX, -mScrollY);
            }
            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
        }
        return false;
    }
    public final boolean getGlobalVisibleRect(Rect r) {
        return getGlobalVisibleRect(r, null);
    }
    public final boolean getLocalVisibleRect(Rect r) {
        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
        if (getGlobalVisibleRect(r, offset)) {
            r.offset(-offset.x, -offset.y);            return true;
        }
        return false;
    }
    public void offsetTopAndBottom(int offset) {
        if (offset != 0) {
            final boolean matrixIsIdentity = hasIdentityMatrix();
            if (matrixIsIdentity) {
                if (isHardwareAccelerated()) {
                    invalidateViewProperty(false, false);
                } else {
                    final ViewParent p = mParent;
                    if (p != null && mAttachInfo != null) {
                        final Rect r = mAttachInfo.mTmpInvalRect;
                        int minTop;
                        int maxBottom;
                        int yLoc;
                        if (offset < 0) {
                            minTop = mTop + offset;
                            maxBottom = mBottom;
                            yLoc = offset;
                        } else {
                            minTop = mTop;
                            maxBottom = mBottom + offset;
                            yLoc = 0;
                        }
                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
                        p.invalidateChild(this, r);
                    }
                }
            } else {
                invalidateViewProperty(false, false);
            }
            mTop += offset;
            mBottom += offset;
            mRenderNode.offsetTopAndBottom(offset);
            if (isHardwareAccelerated()) {
                invalidateViewProperty(false, false);
                invalidateParentIfNeededAndWasQuickRejected();
            } else {
                if (!matrixIsIdentity) {
                    invalidateViewProperty(false, true);
                }
                invalidateParentIfNeeded();
            }
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
    public void offsetLeftAndRight(int offset) {
        if (offset != 0) {
            final boolean matrixIsIdentity = hasIdentityMatrix();
            if (matrixIsIdentity) {
                if (isHardwareAccelerated()) {
                    invalidateViewProperty(false, false);
                } else {
                    final ViewParent p = mParent;
                    if (p != null && mAttachInfo != null) {
                        final Rect r = mAttachInfo.mTmpInvalRect;
                        int minLeft;
                        int maxRight;
                        if (offset < 0) {
                            minLeft = mLeft + offset;
                            maxRight = mRight;
                        } else {
                            minLeft = mLeft;
                            maxRight = mRight + offset;
                        }
                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
                        p.invalidateChild(this, r);
                    }
                }
            } else {
                invalidateViewProperty(false, false);
            }
            mLeft += offset;
            mRight += offset;
            mRenderNode.offsetLeftAndRight(offset);
            if (isHardwareAccelerated()) {
                invalidateViewProperty(false, false);
                invalidateParentIfNeededAndWasQuickRejected();
            } else {
                if (!matrixIsIdentity) {
                    invalidateViewProperty(false, true);
                }
                invalidateParentIfNeeded();
            }
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
    public ViewGroup.LayoutParams getLayoutParams() {
        return mLayoutParams;
    }
    public void setLayoutParams(ViewGroup.LayoutParams params) {
        if (params == null) {
            throw new NullPointerException("Layout parameters cannot be null");
        }
        mLayoutParams = params;
        resolveLayoutParams();
        if (mParent instanceof ViewGroup) {
            ((ViewGroup) mParent).onSetLayoutParams(this, params);
        }
        requestLayout();
    }
    public void resolveLayoutParams() {
        if (mLayoutParams != null) {
            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
        }
    }
    public void scrollTo(int x, int y) {
        if (mScrollX != x || mScrollY != y) {
            int oldX = mScrollX;
            int oldY = mScrollY;
            mScrollX = x;
            mScrollY = y;
            invalidateParentCaches();
            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
            if (!awakenScrollBars()) {
                postInvalidateOnAnimation();
            }
        }
    }
    public void scrollBy(int x, int y) {
        scrollTo(mScrollX + x, mScrollY + y);
    }
    protected boolean awakenScrollBars() {
        return mScrollCache != null &&
                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
    }
    private boolean initialAwakenScrollBars() {
        return mScrollCache != null &&
    }
    protected boolean awakenScrollBars(int startDelay) {
        return awakenScrollBars(startDelay, true);
    }
    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
        final ScrollabilityCache scrollCache = mScrollCache;
        if (scrollCache == null || !scrollCache.fadeScrollBars) {
            return false;
        }
        if (scrollCache.scrollBar == null) {
            scrollCache.scrollBar = new ScrollBarDrawable();
            scrollCache.scrollBar.setState(getDrawableState());
            scrollCache.scrollBar.setCallback(this);
        }
        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
            if (invalidate) {
                postInvalidateOnAnimation();
            }
            if (scrollCache.state == ScrollabilityCache.OFF) {
                final int KEY_REPEAT_FIRST_DELAY = 750;
                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
            }
            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
            scrollCache.fadeStartTime = fadeStartTime;
            scrollCache.state = ScrollabilityCache.ON;
            if (mAttachInfo != null) {
                mAttachInfo.mHandler.removeCallbacks(scrollCache);
                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
            }
            return true;
        }
        return false;
    }
    private boolean skipInvalidate() {
        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
                (!(mParent instanceof ViewGroup) ||
                        !((ViewGroup) mParent).isViewTransitioning(this));
    }
    @Deprecated
    public void invalidate(Rect dirty) {
        final int scrollX = mScrollX;
        final int scrollY = mScrollY;
        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
    }
    @Deprecated
    public void invalidate(int l, int t, int r, int b) {
        final int scrollX = mScrollX;
        final int scrollY = mScrollY;
        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
    }
    public void invalidate() {
        invalidate(true);
    }
    @UnsupportedAppUsage
    public void invalidate(boolean invalidateCache) {
        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
    }
    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
            boolean fullInvalidate) {
        if (mGhostView != null) {
            mGhostView.invalidate(true);
            return;
        }
        if (skipInvalidate()) {
            return;
        }
        mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
        mContentCaptureSessionCached = false;
        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
            if (fullInvalidate) {
                mLastIsOpaque = isOpaque();
                mPrivateFlags &= ~PFLAG_DRAWN;
            }
            mPrivateFlags |= PFLAG_DIRTY;
            if (invalidateCache) {
                mPrivateFlags |= PFLAG_INVALIDATED;
                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
            }
            final AttachInfo ai = mAttachInfo;
            final ViewParent p = mParent;
            if (p != null && ai != null && l < r && t < b) {
                final Rect damage = ai.mTmpInvalRect;
                damage.set(l, t, r, b);
                p.invalidateChild(this, damage);
            }
            if (mBackground != null && mBackground.isProjected()) {
                final View receiver = getProjectionReceiver();
                if (receiver != null) {
                    receiver.damageInParent();
                }
            }
        }
    }
    private View getProjectionReceiver() {
        ViewParent p = getParent();
        while (p != null && p instanceof View) {
            final View v = (View) p;
            if (v.isProjectionReceiver()) {
                return v;
            }
            p = p.getParent();
        }
        return null;
    }
    private boolean isProjectionReceiver() {
        return mBackground != null;
    }
    @UnsupportedAppUsage
    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
        if (!isHardwareAccelerated()
                || !mRenderNode.hasDisplayList()
                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
            if (invalidateParent) {
                invalidateParentCaches();
            }
            if (forceRedraw) {
                mPrivateFlags |= PFLAG_DRAWN;            }
            invalidate(false);
        } else {
            damageInParent();
        }
        mPrivateFlags4 |= PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION;
    }
    protected void damageInParent() {
        if (mParent != null && mAttachInfo != null) {
            mParent.onDescendantInvalidated(this, this);
        }
    }
    @UnsupportedAppUsage
    protected void invalidateParentCaches() {
        if (mParent instanceof View) {
            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
        }
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    protected void invalidateParentIfNeeded() {
        if (isHardwareAccelerated() && mParent instanceof View) {
            ((View) mParent).invalidate(true);
        }
    }
    protected void invalidateParentIfNeededAndWasQuickRejected() {
        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
            invalidateParentIfNeeded();
        }
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    public boolean isOpaque() {
        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
                getFinalAlpha() >= 1.0f;
    }
    @UnsupportedAppUsage
    protected void computeOpaqueFlags() {
        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
        } else {
            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
        }
        final int flags = mViewFlags;
        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
        } else {
            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
        }
    }
    protected boolean hasOpaqueScrollbars() {
        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
    }
    public Handler getHandler() {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            return attachInfo.mHandler;
        }
        return null;
    }
    private HandlerActionQueue getRunQueue() {
        if (mRunQueue == null) {
            mRunQueue = new HandlerActionQueue();
        }
        return mRunQueue;
    }
    @UnsupportedAppUsage
    public ViewRootImpl getViewRootImpl() {
        if (mAttachInfo != null) {
            return mAttachInfo.mViewRootImpl;
        }
        return null;
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public ThreadedRenderer getThreadedRenderer() {
        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
    }
    public boolean post(Runnable action) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            return attachInfo.mHandler.post(action);
        }
        getRunQueue().post(action);
        return true;
    }
    public boolean postDelayed(Runnable action, long delayMillis) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            return attachInfo.mHandler.postDelayed(action, delayMillis);
        }
        getRunQueue().postDelayed(action, delayMillis);
        return true;
    }
    public void postOnAnimation(Runnable action) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            attachInfo.mViewRootImpl.mChoreographer.postCallback(
                    Choreographer.CALLBACK_ANIMATION, action, null);
        } else {
            getRunQueue().post(action);
        }
    }
    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
        } else {
            getRunQueue().postDelayed(action, delayMillis);
        }
    }
    public boolean removeCallbacks(Runnable action) {
        if (action != null) {
            final AttachInfo attachInfo = mAttachInfo;
            if (attachInfo != null) {
                attachInfo.mHandler.removeCallbacks(action);
                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
                        Choreographer.CALLBACK_ANIMATION, action, null);
            }
            getRunQueue().removeCallbacks(action);
        }
        return true;
    }
    public void postInvalidate() {
        postInvalidateDelayed(0);
    }
    public void postInvalidate(int left, int top, int right, int bottom) {
        postInvalidateDelayed(0, left, top, right, bottom);
    }
    public void postInvalidateDelayed(long delayMilliseconds) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
        }
    }
    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
            int right, int bottom) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
            info.target = this;
            info.left = left;
            info.top = top;
            info.right = right;
            info.bottom = bottom;
            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
        }
    }
    public void postInvalidateOnAnimation() {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
        }
    }
    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
            info.target = this;
            info.left = left;
            info.top = top;
            info.right = right;
            info.bottom = bottom;
            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
        }
    }
    private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
            AccessibilityEvent event =
                    AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
            event.setScrollDeltaX(dx);
            event.setScrollDeltaY(dy);
            sendAccessibilityEventUnchecked(event);
        }
    }
    public void computeScroll() {
    }
    public boolean isHorizontalFadingEdgeEnabled() {
        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
    }
    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
            if (horizontalFadingEdgeEnabled) {
                initScrollCache();
            }
            mViewFlags ^= FADING_EDGE_HORIZONTAL;
        }
    }
    public boolean isVerticalFadingEdgeEnabled() {
        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
    }
    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
            if (verticalFadingEdgeEnabled) {
                initScrollCache();
            }
            mViewFlags ^= FADING_EDGE_VERTICAL;
        }
    }
    @InspectableProperty(name = "requiresFadingEdge", flagMapping = {
            @FlagEntry(target = FADING_EDGE_NONE, mask = FADING_EDGE_MASK, name = "none"),
            @FlagEntry(target = FADING_EDGE_VERTICAL, name = "vertical"),
            @FlagEntry(target = FADING_EDGE_HORIZONTAL, name = "horizontal")
    })
    public int getFadingEdge() {
        return mViewFlags & FADING_EDGE_MASK;
    }
    @InspectableProperty
    public int getFadingEdgeLength() {
        if (mScrollCache != null && (mViewFlags & FADING_EDGE_MASK) != FADING_EDGE_NONE) {
            return mScrollCache.fadingEdgeLength;
        }
        return 0;
    }
    protected float getTopFadingEdgeStrength() {
        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
    }
    protected float getBottomFadingEdgeStrength() {
        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
                computeVerticalScrollRange() ? 1.0f : 0.0f;
    }
    protected float getLeftFadingEdgeStrength() {
        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
    }
    protected float getRightFadingEdgeStrength() {
        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
                computeHorizontalScrollRange() ? 1.0f : 0.0f;
    }
    public boolean isHorizontalScrollBarEnabled() {
        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
    }
    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
            mViewFlags ^= SCROLLBARS_HORIZONTAL;
            computeOpaqueFlags();
            resolvePadding();
        }
    }
    public boolean isVerticalScrollBarEnabled() {
        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
    }
    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
            mViewFlags ^= SCROLLBARS_VERTICAL;
            computeOpaqueFlags();
            resolvePadding();
        }
    }
    @UnsupportedAppUsage
    protected void recomputePadding() {
        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
    }
    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
        initScrollCache();
        final ScrollabilityCache scrollabilityCache = mScrollCache;
        scrollabilityCache.fadeScrollBars = fadeScrollbars;
        if (fadeScrollbars) {
            scrollabilityCache.state = ScrollabilityCache.OFF;
        } else {
            scrollabilityCache.state = ScrollabilityCache.ON;
        }
    }
    public boolean isScrollbarFadingEnabled() {
        return mScrollCache != null && mScrollCache.fadeScrollBars;
    }
    @InspectableProperty(name = "scrollbarDefaultDelayBeforeFade")
    public int getScrollBarDefaultDelayBeforeFade() {
        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
                mScrollCache.scrollBarDefaultDelayBeforeFade;
    }
    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
    }
    @InspectableProperty(name = "scrollbarFadeDuration")
    public int getScrollBarFadeDuration() {
        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
                mScrollCache.scrollBarFadeDuration;
    }
    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
    }
    @InspectableProperty(name = "scrollbarSize")
    public int getScrollBarSize() {
        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
                mScrollCache.scrollBarSize;
    }
    public void setScrollBarSize(int scrollBarSize) {
        getScrollCache().scrollBarSize = scrollBarSize;
    }
    public void setScrollBarStyle(@ScrollBarStyle int style) {
        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
            computeOpaqueFlags();
            resolvePadding();
        }
    }
    @ViewDebug.ExportedProperty(mapping = {
            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
    })
    @InspectableProperty(name = "scrollbarStyle", enumMapping = {
            @EnumEntry(value = SCROLLBARS_INSIDE_OVERLAY, name = "insideOverlay"),
            @EnumEntry(value = SCROLLBARS_INSIDE_INSET, name = "insideInset"),
            @EnumEntry(value = SCROLLBARS_OUTSIDE_OVERLAY, name = "outsideOverlay"),
            @EnumEntry(value = SCROLLBARS_OUTSIDE_INSET, name = "outsideInset")
    })
    @ScrollBarStyle
    public int getScrollBarStyle() {
        return mViewFlags & SCROLLBARS_STYLE_MASK;
    }
    protected int computeHorizontalScrollRange() {
        return getWidth();
    }
    protected int computeHorizontalScrollOffset() {
        return mScrollX;
    }
    protected int computeHorizontalScrollExtent() {
        return getWidth();
    }
    protected int computeVerticalScrollRange() {
        return getHeight();
    }
    protected int computeVerticalScrollOffset() {
        return mScrollY;
    }
    protected int computeVerticalScrollExtent() {
        return getHeight();
    }
    public boolean canScrollHorizontally(int direction) {
        final int offset = computeHorizontalScrollOffset();
        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
        if (range == 0) return false;
        if (direction < 0) {
            return offset > 0;
        } else {
            return offset < range - 1;
        }
    }
    public boolean canScrollVertically(int direction) {
        final int offset = computeVerticalScrollOffset();
        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
        if (range == 0) return false;
        if (direction < 0) {
            return offset > 0;
        } else {
            return offset < range - 1;
        }
    }
    void getScrollIndicatorBounds(@NonNull Rect out) {
        out.left = mScrollX;
        out.right = mScrollX + mRight - mLeft;
        out.top = mScrollY;
        out.bottom = mScrollY + mBottom - mTop;
    }
    private void onDrawScrollIndicators(@NonNull Canvas c) {
        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
            return;
        }
        final Drawable dr = mScrollIndicatorDrawable;
        if (dr == null) {
            return;
        }
        if (mAttachInfo == null) {
            return;
        }
        final int h = dr.getIntrinsicHeight();
        final int w = dr.getIntrinsicWidth();
        final Rect rect = mAttachInfo.mTmpInvalRect;
        getScrollIndicatorBounds(rect);
        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
            final boolean canScrollUp = canScrollVertically(-1);
            if (canScrollUp) {
                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
                dr.draw(c);
            }
        }
        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
            final boolean canScrollDown = canScrollVertically(1);
            if (canScrollDown) {
                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
                dr.draw(c);
            }
        }
        final int leftRtl;
        final int rightRtl;
        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
        } else {
            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
        }
        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
        if ((mPrivateFlags3 & leftMask) != 0) {
            final boolean canScrollLeft = canScrollHorizontally(-1);
            if (canScrollLeft) {
                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
                dr.draw(c);
            }
        }
        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
        if ((mPrivateFlags3 & rightMask) != 0) {
            final boolean canScrollRight = canScrollHorizontally(1);
            if (canScrollRight) {
                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
                dr.draw(c);
            }
        }
    }
    private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
            @Nullable Rect touchBounds) {
        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
        if (bounds == null) {
            return;
        }
        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
                && !isVerticalScrollBarHidden();
        final int size = getHorizontalScrollbarHeight();
        final int verticalScrollBarGap = drawVerticalScrollBar ?
                getVerticalScrollbarWidth() : 0;
        final int width = mRight - mLeft;
        final int height = mBottom - mTop;
        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
        bounds.left = mScrollX + (mPaddingLeft & inside);
        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
        bounds.bottom = bounds.top + size;
        if (touchBounds == null) {
            return;
        }
        if (touchBounds != bounds) {
            touchBounds.set(bounds);
        }
        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
        if (touchBounds.height() < minTouchTarget) {
            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
            touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
            touchBounds.top = touchBounds.bottom - minTouchTarget;
        }
        if (touchBounds.width() < minTouchTarget) {
            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
            touchBounds.left -= adjust;
            touchBounds.right = touchBounds.left + minTouchTarget;
        }
    }
    private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
        if (mRoundScrollbarRenderer == null) {
            getStraightVerticalScrollBarBounds(bounds, touchBounds);
        } else {
            mRoundScrollbarRenderer.getRoundVerticalScrollBarBounds(
                    bounds != null ? bounds : touchBounds);
        }
    }
    private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
            @Nullable Rect touchBounds) {
        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
        if (bounds == null) {
            return;
        }
        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
        final int size = getVerticalScrollbarWidth();
        int verticalScrollbarPosition = mVerticalScrollbarPosition;
        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
            verticalScrollbarPosition = isLayoutRtl() ?
                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
        }
        final int width = mRight - mLeft;
        final int height = mBottom - mTop;
        switch (verticalScrollbarPosition) {
            default:
            case SCROLLBAR_POSITION_RIGHT:
                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
                break;
            case SCROLLBAR_POSITION_LEFT:
                bounds.left = mScrollX + (mUserPaddingLeft & inside);
                break;
        }
        bounds.top = mScrollY + (mPaddingTop & inside);
        bounds.right = bounds.left + size;
        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
        if (touchBounds == null) {
            return;
        }
        if (touchBounds != bounds) {
            touchBounds.set(bounds);
        }
        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
        if (touchBounds.width() < minTouchTarget) {
            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
            if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
                touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
                touchBounds.left = touchBounds.right - minTouchTarget;
            } else {
                touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
                touchBounds.right = touchBounds.left + minTouchTarget;
            }
        }
        if (touchBounds.height() < minTouchTarget) {
            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
            touchBounds.top -= adjust;
            touchBounds.bottom = touchBounds.top + minTouchTarget;
        }
    }
    protected final void onDrawScrollBars(@NonNull Canvas canvas) {
        final ScrollabilityCache cache = mScrollCache;
        if (cache != null) {
            int state = cache.state;
            if (state == ScrollabilityCache.OFF) {
                return;
            }
            boolean invalidate = false;
            if (state == ScrollabilityCache.FADING) {
                if (cache.interpolatorValues == null) {
                    cache.interpolatorValues = new float[1];
                }
                float[] values = cache.interpolatorValues;
                if (cache.scrollBarInterpolator.timeToValues(values) ==
                        Interpolator.Result.FREEZE_END) {
                    cache.state = ScrollabilityCache.OFF;
                } else {
                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
                }
                invalidate = true;
            } else {
                cache.scrollBar.mutate().setAlpha(255);
            }
            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
                    && !isVerticalScrollBarHidden();
            if (mRoundScrollbarRenderer != null) {
                if (drawVerticalScrollBar) {
                    final Rect bounds = cache.mScrollBarBounds;
                    getVerticalScrollBarBounds(bounds, null);
                    boolean shouldDrawScrollbarAtLeft =
                            (mVerticalScrollbarPosition == SCROLLBAR_POSITION_LEFT)
                                    || (mVerticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT
                                    && isLayoutRtl());
                    mRoundScrollbarRenderer.drawRoundScrollbars(
                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds,
                            shouldDrawScrollbarAtLeft);
                    if (invalidate) {
                        invalidate();
                    }
                }
            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
                final ScrollBarDrawable scrollBar = cache.scrollBar;
                if (drawHorizontalScrollBar) {
                    scrollBar.setParameters(computeHorizontalScrollRange(),
                            computeHorizontalScrollOffset(),
                            computeHorizontalScrollExtent(), false);
                    final Rect bounds = cache.mScrollBarBounds;
                    getHorizontalScrollBarBounds(bounds, null);
                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
                            bounds.right, bounds.bottom);
                    if (invalidate) {
                        invalidate(bounds);
                    }
                }
                if (drawVerticalScrollBar) {
                    scrollBar.setParameters(computeVerticalScrollRange(),
                            computeVerticalScrollOffset(),
                            computeVerticalScrollExtent(), true);
                    final Rect bounds = cache.mScrollBarBounds;
                    getVerticalScrollBarBounds(bounds, null);
                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
                            bounds.right, bounds.bottom);
                    if (invalidate) {
                        invalidate(bounds);
                    }
                }
            }
        }
    }
    protected boolean isVerticalScrollBarHidden() {
        return false;
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    protected void onDrawHorizontalScrollBar(@NonNull Canvas canvas, Drawable scrollBar,
            int l, int t, int r, int b) {
        scrollBar.setBounds(l, t, r, b);
        scrollBar.draw(canvas);
    }
    @UnsupportedAppUsage
    protected void onDrawVerticalScrollBar(@NonNull Canvas canvas, Drawable scrollBar,
            int l, int t, int r, int b) {
        scrollBar.setBounds(l, t, r, b);
        scrollBar.draw(canvas);
    }
    protected void onDraw(@NonNull Canvas canvas) {
    }
    @UnsupportedAppUsage
    void assignParent(ViewParent parent) {
        if (mParent == null) {
            mParent = parent;
        } else if (parent == null) {
            mParent = null;
        } else {
            throw new RuntimeException("view " + this + " being added, but"
                    + " it already has a parent");
        }
    }
    @CallSuper
    protected void onAttachedToWindow() {
        if (mParent != null && (mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
            mParent.requestTransparentRegion(this);
        }
        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
        jumpDrawablesToCurrentState();
        AccessibilityNodeIdManager.getInstance().registerViewWithId(this, getAccessibilityViewId());
        resetSubtreeAccessibilityStateChanged();
        rebuildOutline();
        if (isFocused()) {
        }
        if (sTraceLayoutSteps) {
            setTraversalTracingEnabled(true);
        }
        if (sTraceRequestLayoutClass != null
                && sTraceRequestLayoutClass.equals(getClass().getSimpleName())) {
            setRelayoutTracingEnabled(true);
        }
    }
    public boolean resolveRtlPropertiesIfNeeded() {
        if (!needRtlPropertiesResolution()) return false;
        if (!isLayoutDirectionResolved()) {
            resolveLayoutDirection();
            resolveLayoutParams();
        }
        if (!isTextDirectionResolved()) {
            resolveTextDirection();
        }
        if (!isTextAlignmentResolved()) {
            resolveTextAlignment();
        }
        if (!areDrawablesResolved()) {
            resolveDrawables();
        }
        if (!isPaddingResolved()) {
            resolvePadding();
        }
        onRtlPropertiesChanged(getLayoutDirection());
        return true;
    }
    @TestApi
    public void resetRtlProperties() {
        resetResolvedLayoutDirection();
        resetResolvedTextDirection();
        resetResolvedTextAlignment();
        resetResolvedPadding();
        resetResolvedDrawables();
    }
    void dispatchScreenStateChanged(int screenState) {
        onScreenStateChanged(screenState);
    }
    public void onScreenStateChanged(int screenState) {
    }
    void dispatchMovedToDisplay(Display display, Configuration config) {
        mAttachInfo.mDisplay = display;
        mAttachInfo.mDisplayState = display.getState();
        onMovedToDisplay(display.getDisplayId(), config);
    }
    public void onMovedToDisplay(int displayId, Configuration config) {
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private boolean hasRtlSupport() {
        return mContext.getApplicationInfo().hasRtlSupport();
    }
    private boolean isRtlCompatibilityMode() {
        return !hasRtlSupport();
    }
    private boolean needRtlPropertiesResolution() {
        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
    }
    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
    }
    public boolean resolveLayoutDirection() {
        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
        if (hasRtlSupport()) {
            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
                case LAYOUT_DIRECTION_INHERIT:
                    if (!canResolveLayoutDirection()) return false;
                    try {
                        if (!mParent.isLayoutDirectionResolved()) return false;
                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
                        }
                    } catch (AbstractMethodError e) {
                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                                " does not fully implement ViewParent", e);
                    }
                    break;
                case LAYOUT_DIRECTION_RTL:
                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
                    break;
                case LAYOUT_DIRECTION_LOCALE:
                    if((LAYOUT_DIRECTION_RTL ==
                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
                    }
                    break;
                default:
            }
        }
        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
        return true;
    }
    public boolean canResolveLayoutDirection() {
        switch (getRawLayoutDirection()) {
            case LAYOUT_DIRECTION_INHERIT:
                if (mParent != null) {
                    try {
                        return mParent.canResolveLayoutDirection();
                    } catch (AbstractMethodError e) {
                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                                " does not fully implement ViewParent", e);
                    }
                }
                return false;
            default:
                return true;
        }
    }
    @TestApi
    public void resetResolvedLayoutDirection() {
        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
    }
    public boolean isLayoutDirectionInherited() {
        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
    }
    public boolean isLayoutDirectionResolved() {
        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
    }
    @UnsupportedAppUsage
    boolean isPaddingResolved() {
        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public void resolvePadding() {
        final int resolvedLayoutDirection = getLayoutDirection();
        if (!isRtlCompatibilityMode()) {
            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
                Rect padding = sThreadLocal.get();
                if (padding == null) {
                    padding = new Rect();
                    sThreadLocal.set(padding);
                }
                mBackground.getPadding(padding);
                if (!mLeftPaddingDefined) {
                    mUserPaddingLeftInitial = padding.left;
                }
                if (!mRightPaddingDefined) {
                    mUserPaddingRightInitial = padding.right;
                }
            }
            switch (resolvedLayoutDirection) {
                case LAYOUT_DIRECTION_RTL:
                    if (mUserPaddingStart != UNDEFINED_PADDING) {
                        mUserPaddingRight = mUserPaddingStart;
                    } else {
                        mUserPaddingRight = mUserPaddingRightInitial;
                    }
                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
                        mUserPaddingLeft = mUserPaddingEnd;
                    } else {
                        mUserPaddingLeft = mUserPaddingLeftInitial;
                    }
                    break;
                case LAYOUT_DIRECTION_LTR:
                default:
                    if (mUserPaddingStart != UNDEFINED_PADDING) {
                        mUserPaddingLeft = mUserPaddingStart;
                    } else {
                        mUserPaddingLeft = mUserPaddingLeftInitial;
                    }
                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
                        mUserPaddingRight = mUserPaddingEnd;
                    } else {
                        mUserPaddingRight = mUserPaddingRightInitial;
                    }
            }
            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
        }
        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
        onRtlPropertiesChanged(resolvedLayoutDirection);
        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
    }
    @TestApi
    public void resetResolvedPadding() {
        resetResolvedPaddingInternal();
    }
    void resetResolvedPaddingInternal() {
        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
    }
    @CallSuper
    protected void onDetachedFromWindow() {
    }
    @CallSuper
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    protected void onDetachedFromWindowInternal() {
        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
        removeUnsetPressCallback();
        removeLongPressCallback();
        removePerformClickCallback();
        clearAccessibilityThrottles();
        stopNestedScroll();
        jumpDrawablesToCurrentState();
        destroyDrawingCache();
        cleanupDraw();
        mCurrentAnimation = null;
        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
            removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
            removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
            hideTooltip();
        }
        AccessibilityNodeIdManager.getInstance().unregisterViewWithId(getAccessibilityViewId());
        if (mBackgroundRenderNode != null) {
            mBackgroundRenderNode.forceEndAnimators();
        }
        mRenderNode.forceEndAnimators();
    }
    private void cleanupDraw() {
        resetDisplayList();
        if (mAttachInfo != null) {
            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
        }
    }
    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
    }
    protected int getWindowAttachCount() {
        return mWindowAttachCount;
    }
    public IBinder getWindowToken() {
        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
    }
    public WindowId getWindowId() {
        AttachInfo ai = mAttachInfo;
        if (ai == null) {
            return null;
        }
        if (ai.mWindowId == null) {
            try {
                ai.mIWindowId = ai.mSession.getWindowId(ai.mWindowToken);
                if (ai.mIWindowId != null) {
                    ai.mWindowId = new WindowId(ai.mIWindowId);
                }
            } catch (RemoteException e) {
            }
        }
        return ai.mWindowId;
    }
    public IBinder getApplicationWindowToken() {
        AttachInfo ai = mAttachInfo;
        if (ai != null) {
            IBinder appWindowToken = ai.mPanelParentWindowToken;
            if (appWindowToken == null) {
                appWindowToken = ai.mWindowToken;
            }
            return appWindowToken;
        }
        return null;
    }
    public Display getDisplay() {
        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
        return mAttachInfo != null ? mAttachInfo.mSession : null;
    }
    protected IWindow getWindow() {
        return mAttachInfo != null ? mAttachInfo.mWindow : null;
    }
    int combineVisibility(int vis1, int vis2) {
        return Math.max(vis1, vis2);
    }
    private boolean mShouldFakeFocus = false;
    public void fakeFocusAfterAttachingToWindow() {
        mShouldFakeFocus = true;
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
        mAttachInfo = info;
        if (mOverlay != null) {
            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
        }
        mWindowAttachCount++;
        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
        if (mFloatingTreeObserver != null) {
            info.mTreeObserver.merge(mFloatingTreeObserver);
            mFloatingTreeObserver = null;
        }
        registerPendingFrameMetricsObservers();
        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
            mAttachInfo.mScrollContainers.add(this);
            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
        }
        if (mRunQueue != null) {
            mRunQueue.executeActions(info.mHandler);
            mRunQueue = null;
        }
        performCollectViewAttributes(mAttachInfo, visibility);
        onAttachedToWindow();
        ListenerInfo li = mListenerInfo;
        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
                li != null ? li.mOnAttachStateChangeListeners : null;
        if (listeners != null && listeners.size() > 0) {
            for (OnAttachStateChangeListener listener : listeners) {
                listener.onViewAttachedToWindow(this);
            }
        }
        int vis = info.mWindowVisibility;
        if (vis != GONE) {
            onWindowVisibilityChanged(vis);
            if (isShown()) {
                onVisibilityAggregated(vis == VISIBLE);
            }
        }
        onVisibilityChanged(this, visibility);
        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
            refreshDrawableState();
        }
        needGlobalAttributesUpdate(false);
        notifyEnterOrExitForAutoFillIfNeeded(true);
        notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
        if (mShouldFakeFocus) {
            getViewRootImpl().dispatchCompatFakeFocus();
            mShouldFakeFocus = false;
        }
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    void dispatchDetachedFromWindow() {
        AttachInfo info = mAttachInfo;
        if (info != null) {
            int vis = info.mWindowVisibility;
            if (vis != GONE) {
                onWindowVisibilityChanged(GONE);
                if (isShown()) {
                    onVisibilityAggregated(false);
                } else {
                    notifyAutofillManagerViewVisibilityChanged(false);
                }
            }
        }
        onDetachedFromWindow();
        onDetachedFromWindowInternal();
        if (info != null) {
            info.mViewRootImpl.getImeFocusController().onViewDetachedFromWindow(this);
        }
        ListenerInfo li = mListenerInfo;
        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
                li != null ? li.mOnAttachStateChangeListeners : null;
        if (listeners != null && listeners.size() > 0) {
            for (OnAttachStateChangeListener listener : listeners) {
                listener.onViewDetachedFromWindow(this);
            }
        }
        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
            mAttachInfo.mScrollContainers.remove(this);
            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
        }
        notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
        updateSensitiveViewsCountIfNeeded(false);
        mAttachInfo = null;
        if (mOverlay != null) {
            mOverlay.getOverlayView().dispatchDetachedFromWindow();
        }
        notifyEnterOrExitForAutoFillIfNeeded(false);
        if (info != null && !collectPreferKeepClearRects().isEmpty()) {
            info.mViewRootImpl.updateKeepClearRectsForView(this);
        }
    }
    public final void cancelPendingInputEvents() {
        dispatchCancelPendingInputEvents();
    }
    void dispatchCancelPendingInputEvents() {
        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
        onCancelPendingInputEvents();
        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
                    " did not call through to super.onCancelPendingInputEvents()");
        }
    }
    public void onCancelPendingInputEvents() {
        removePerformClickCallback();
        cancelLongPress();
        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
    }
    public void saveHierarchyState(SparseArray<Parcelable> container) {
        dispatchSaveInstanceState(container);
    }
    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
            Parcelable state = onSaveInstanceState();
            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
                throw new IllegalStateException(
                        "Derived class did not call super.onSaveInstanceState()");
            }
            if (state != null) {
                container.put(mID, state);
            }
        }
    }
    @CallSuper
    @Nullable protected Parcelable onSaveInstanceState() {
        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
        if (mStartActivityRequestWho != null || isAutofilled()
                || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
            if (mStartActivityRequestWho != null) {
                state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
            }
            if (isAutofilled()) {
                state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
            }
            if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
                state.mSavedData |= BaseSavedState.AUTOFILL_ID;
            }
            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
            state.mIsAutofilled = isAutofilled();
            state.mHideHighlight = hideAutofillHighlight();
            state.mAutofillViewId = mAutofillViewId;
            return state;
        }
        return BaseSavedState.EMPTY_STATE;
    }
    public void restoreHierarchyState(SparseArray<Parcelable> container) {
        dispatchRestoreInstanceState(container);
    }
    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
        if (mID != NO_ID) {
            Parcelable state = container.get(mID);
            if (state != null) {
                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
                onRestoreInstanceState(state);
                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
                    throw new IllegalStateException(
                            "Derived class did not call super.onRestoreInstanceState()");
                }
            }
        }
    }
    @CallSuper
    protected void onRestoreInstanceState(Parcelable state) {
        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
        if (state != null && !(state instanceof AbsSavedState)) {
            throw new IllegalArgumentException("Wrong state class, expecting View State but "
                    + "received " + state.getClass().toString() + " instead. This usually happens "
                    + "when two views of different type have the same id in the same hierarchy. "
                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
                    + "other views do not use the same id.");
        }
        if (state != null && state instanceof BaseSavedState) {
            BaseSavedState baseState = (BaseSavedState) state;
            if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
                mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
            }
            if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
                setAutofilled(baseState.mIsAutofilled, baseState.mHideHighlight);
            }
            if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
                ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
                if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) {
                    if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.DEBUG)) {
                        Log.d(AUTOFILL_LOG_TAG, "onRestoreInstanceState(): not setting autofillId "
                                + "to " + baseState.mAutofillViewId + " because view explicitly set"
                                + " it to " + mAutofillId);
                    }
                } else {
                    mAutofillViewId = baseState.mAutofillViewId;
                    mAutofillId = null;                }
            }
        }
    }
    public long getDrawingTime() {
        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
    }
    public void setDuplicateParentStateEnabled(boolean enabled) {
        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
    }
    @InspectableProperty(name = "duplicateParentState")
    public boolean isDuplicateParentStateEnabled() {
        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
    }
    public void setLayerType(@LayerType int layerType, @Nullable Paint paint) {
        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
        }
        boolean typeChanged = mRenderNode.setLayerType(layerType);
        if (!typeChanged) {
            setLayerPaint(paint);
            return;
        }
        if (layerType != LAYER_TYPE_SOFTWARE) {
            destroyDrawingCache();
        }
        mLayerType = layerType;
        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
        mRenderNode.setLayerPaint(mLayerPaint);
        invalidateParentCaches();
        invalidate(true);
    }
    public void setRenderEffect(@Nullable RenderEffect renderEffect) {
        if (mRenderNode.setRenderEffect(renderEffect)) {
            invalidateViewProperty(true, true);
        }
    }
    public void setBackdropRenderEffect(@Nullable RenderEffect renderEffect) {
        if (mRenderNode.setBackdropRenderEffect(renderEffect)) {
            invalidateViewProperty(true, true);
        }
    }
    public void setLayerPaint(@Nullable Paint paint) {
        int layerType = getLayerType();
        if (layerType != LAYER_TYPE_NONE) {
            mLayerPaint = paint;
            if (layerType == LAYER_TYPE_HARDWARE) {
                if (mRenderNode.setLayerPaint(paint)) {
                    invalidateViewProperty(false, false);
                }
            } else {
                invalidate();
            }
        }
    }
    @InspectableProperty(enumMapping = {
            @EnumEntry(value = LAYER_TYPE_NONE, name = "none"),
            @EnumEntry(value = LAYER_TYPE_SOFTWARE, name = "software"),
            @EnumEntry(value = LAYER_TYPE_HARDWARE, name = "hardware")
    })
    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
    })
    @LayerType
    public int getLayerType() {
        return mLayerType;
    }
    public void buildLayer() {
        if (mLayerType == LAYER_TYPE_NONE) return;
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo == null) {
            throw new IllegalStateException("This view must be attached to a window first");
        }
        if (getWidth() == 0 || getHeight() == 0) {
            return;
        }
        switch (mLayerType) {
            case LAYER_TYPE_HARDWARE:
                updateDisplayListIfDirty();
                if (attachInfo.mThreadedRenderer != null && mRenderNode.hasDisplayList()) {
                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
                }
                break;
            case LAYER_TYPE_SOFTWARE:
                buildDrawingCache(true);
                break;
        }
    }
    public boolean probablyHasInput() {
        ViewRootImpl viewRootImpl = getViewRootImpl();
        if (viewRootImpl == null) {
            return false;
        }
        return viewRootImpl.probablyHasInput();
    }
    @CallSuper
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    protected void destroyHardwareResources() {
        if (mOverlay != null) {
            mOverlay.getOverlayView().destroyHardwareResources();
        }
        if (mGhostView != null) {
            mGhostView.destroyHardwareResources();
        }
    }
    @Deprecated
    public void setDrawingCacheEnabled(boolean enabled) {
        mCachingFailed = false;
        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
    }
    @Deprecated
    @ViewDebug.ExportedProperty(category = "drawing")
    public boolean isDrawingCacheEnabled() {
        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
    }
    @SuppressWarnings({"UnusedDeclaration"})
    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
        Log.d(VIEW_LOG_TAG, indent + this + "             DIRTY("
                + (mPrivateFlags & View.PFLAG_DIRTY_MASK)
                + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID("
                + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID)
                + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
        if (clear) {
            mPrivateFlags &= clearMask;
        }
        if (this instanceof ViewGroup) {
            ViewGroup parent = (ViewGroup) this;
            final int count = parent.getChildCount();
            for (int i = 0; i < count; i++) {
                final View child = parent.getChildAt(i);
                child.outputDirtyFlags(indent + "  ", clear, clearMask);
            }
        }
    }
    protected void dispatchGetDisplayList() {}
    public boolean canHaveDisplayList() {
        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
    }
    @NonNull
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public RenderNode updateDisplayListIfDirty() {
        final RenderNode renderNode = mRenderNode;
        if (!canHaveDisplayList()) {
            return renderNode;
        }
        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
                || !renderNode.hasDisplayList()
                || (mRecreateDisplayList)) {
            if (renderNode.hasDisplayList()
                    && !mRecreateDisplayList) {
                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                dispatchGetDisplayList();
                return renderNode;            }
            mRecreateDisplayList = true;
            int width = mRight - mLeft;
            int height = mBottom - mTop;
            int layerType = getLayerType();
            renderNode.clearStretch();
            final RecordingCanvas canvas = renderNode.beginRecording(width, height);
            try {
                if (layerType == LAYER_TYPE_SOFTWARE) {
                    buildDrawingCache(true);
                    Bitmap cache = getDrawingCache(true);
                    if (cache != null) {
                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
                    }
                } else {
                    computeScroll();
                    canvas.translate(-mScrollX, -mScrollY);
                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                    mPrivateFlags4 |= PFLAG4_HAS_DRAWN;
                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                        dispatchDraw(canvas);
                        drawAutofilledHighlight(canvas);
                        if (mOverlay != null && !mOverlay.isEmpty()) {
                            mOverlay.getOverlayView().draw(canvas);
                        }
                        if (isShowingLayoutBounds()) {
                            debugDrawFocus(canvas);
                        }
                    } else {
                        draw(canvas);
                    }
                }
                if (sToolkitSetFrameRateReadOnlyFlagValue
                        && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
                    votePreferredFrameRate();
                }
            } finally {
                renderNode.endRecording();
                setDisplayListProperties(renderNode);
            }
        } else {
            if ((mPrivateFlags4 & PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION)
                    == PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION) {
                if (sToolkitSetFrameRateReadOnlyFlagValue
                        && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
                    votePreferredFrameRate();
                }
                mPrivateFlags4 &= ~PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION;
            }
            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
        }
        mPrivateFlags4 &= ~PFLAG4_HAS_MOVED;
        mFrameContentVelocity = -1;
        return renderNode;
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private void resetDisplayList() {
        mRenderNode.discardDisplayList();
        if (mBackgroundRenderNode != null) {
            mBackgroundRenderNode.discardDisplayList();
        }
    }
    @Deprecated
    public Bitmap getDrawingCache() {
        return getDrawingCache(false);
    }
    @Deprecated
    public Bitmap getDrawingCache(boolean autoScale) {
        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
            return null;
        }
        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
            buildDrawingCache(autoScale);
        }
        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
    }
    @Deprecated
    public void destroyDrawingCache() {
        if (mDrawingCache != null) {
            mDrawingCache.recycle();
            mDrawingCache = null;
        }
        if (mUnscaledDrawingCache != null) {
            mUnscaledDrawingCache.recycle();
            mUnscaledDrawingCache = null;
        }
    }
    @Deprecated
    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
        if (color != mDrawingCacheBackgroundColor) {
            mDrawingCacheBackgroundColor = color;
            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
        }
    }
    @Deprecated
    @ColorInt
    public int getDrawingCacheBackgroundColor() {
        return mDrawingCacheBackgroundColor;
    }
    @Deprecated
    public void buildDrawingCache() {
        buildDrawingCache(false);
    }
    @Deprecated
    public void buildDrawingCache(boolean autoScale) {
        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
                mDrawingCache == null : mUnscaledDrawingCache == null)) {
            if (Trace.isTagEnabled(TRACE_TAG_VIEW)) {
                Trace.traceBegin(TRACE_TAG_VIEW,
                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
            }
            try {
                buildDrawingCacheImpl(autoScale);
            } finally {
                Trace.traceEnd(TRACE_TAG_VIEW);
            }
        }
    }
    private void buildDrawingCacheImpl(boolean autoScale) {
        mCachingFailed = false;
        int width = mRight - mLeft;
        int height = mBottom - mTop;
        final AttachInfo attachInfo = mAttachInfo;
        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
        if (autoScale && scalingRequired) {
        }
        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
        final long drawingCacheSize =
                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
            if (width > 0 && height > 0) {
                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
                        + " too large to fit into a software layer (or drawing cache), needs "
                        + projectedBitmapSize + " bytes, only "
                        + drawingCacheSize + " available");
            }
            destroyDrawingCache();
            mCachingFailed = true;
            return;
        }
        boolean clear = true;
        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
            Bitmap.Config quality;
            if (!opaque) {
                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
                    case DRAWING_CACHE_QUALITY_AUTO:
                    case DRAWING_CACHE_QUALITY_LOW:
                    case DRAWING_CACHE_QUALITY_HIGH:
                    default:
                        quality = Bitmap.Config.ARGB_8888;
                        break;
                }
            } else {
                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
            }
            if (bitmap != null) bitmap.recycle();
            try {
                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
                        width, height, quality);
                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
                if (autoScale) {
                    mDrawingCache = bitmap;
                } else {
                    mUnscaledDrawingCache = bitmap;
                }
                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
            } catch (OutOfMemoryError e) {
                if (autoScale) {
                    mDrawingCache = null;
                } else {
                    mUnscaledDrawingCache = null;
                }
                mCachingFailed = true;
                return;
            }
            clear = drawingCacheBackgroundColor != 0;
        }
        Canvas canvas;
        if (attachInfo != null) {
            canvas = attachInfo.mCanvas;
            if (canvas == null) {
                canvas = new Canvas();
            }
            canvas.setBitmap(bitmap);
            attachInfo.mCanvas = null;
        } else {
            canvas = new Canvas(bitmap);
        }
        if (clear) {
            bitmap.eraseColor(drawingCacheBackgroundColor);
        }
        computeScroll();
        final int restoreCount = canvas.save();
        if (autoScale && scalingRequired) {
            final float scale = attachInfo.mApplicationScale;
            canvas.scale(scale, scale);
        }
        canvas.translate(-mScrollX, -mScrollY);
        mPrivateFlags |= PFLAG_DRAWN;
        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
                mLayerType != LAYER_TYPE_NONE) {
            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
        }
        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
            dispatchDraw(canvas);
            drawAutofilledHighlight(canvas);
            if (mOverlay != null && !mOverlay.isEmpty()) {
                mOverlay.getOverlayView().draw(canvas);
            }
        } else {
            draw(canvas);
        }
        canvas.restoreToCount(restoreCount);
        canvas.setBitmap(null);
        if (attachInfo != null) {
            attachInfo.mCanvas = canvas;
        }
    }
    @UnsupportedAppUsage
    public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
        int width = mRight - mLeft;
        int height = mBottom - mTop;
        final AttachInfo attachInfo = mAttachInfo;
        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
        Canvas oldCanvas = null;
        try {
            Canvas canvas = canvasProvider.getCanvas(this,
                    width > 0 ? width : 1, height > 0 ? height : 1);
            if (attachInfo != null) {
                oldCanvas = attachInfo.mCanvas;
                attachInfo.mCanvas = null;
            }
            computeScroll();
            final int restoreCount = canvas.save();
            canvas.scale(scale, scale);
            canvas.translate(-mScrollX, -mScrollY);
            int flags = mPrivateFlags;
            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                dispatchDraw(canvas);
                drawAutofilledHighlight(canvas);
                if (mOverlay != null && !mOverlay.isEmpty()) {
                    mOverlay.getOverlayView().draw(canvas);
                }
            } else {
                draw(canvas);
            }
            mPrivateFlags = flags;
            canvas.restoreToCount(restoreCount);
            return canvasProvider.createBitmap();
        } finally {
            if (oldCanvas != null) {
                attachInfo.mCanvas = oldCanvas;
            }
        }
    }
    public boolean isInEditMode() {
        return false;
    }
    protected boolean isPaddingOffsetRequired() {
        return false;
    }
    protected int getLeftPaddingOffset() {
        return 0;
    }
    protected int getRightPaddingOffset() {
        return 0;
    }
    protected int getTopPaddingOffset() {
        return 0;
    }
    protected int getBottomPaddingOffset() {
        return 0;
    }
    protected int getFadeTop(boolean offsetRequired) {
        int top = mPaddingTop;
        if (offsetRequired) top += getTopPaddingOffset();
        return top;
    }
    protected int getFadeHeight(boolean offsetRequired) {
        int padding = mPaddingTop;
        if (offsetRequired) padding += getTopPaddingOffset();
        return mBottom - mTop - mPaddingBottom - padding;
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    public boolean isHardwareAccelerated() {
        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
    }
    public void setClipBounds(Rect clipBounds) {
        if (clipBounds == mClipBounds
                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
            return;
        }
        if (clipBounds != null) {
            if (mClipBounds == null) {
                mClipBounds = new Rect(clipBounds);
            } else {
                mClipBounds.set(clipBounds);
            }
        } else {
            mClipBounds = null;
        }
        mRenderNode.setClipRect(mClipBounds);
        invalidateViewProperty(false, false);
    }
    public Rect getClipBounds() {
        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
    }
    public boolean getClipBounds(Rect outRect) {
        if (mClipBounds != null) {
            outRect.set(mClipBounds);
            return true;
        }
        return false;
    }
    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
            Animation a, boolean scalingRequired) {
        Transformation invalidationTransform;
        final int flags = parent.mGroupFlags;
        final boolean initialized = a.isInitialized();
        if (!initialized) {
            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
            onAnimationStart();
        }
        final Transformation t = parent.getChildTransformation();
        boolean more = a.getTransformation(drawingTime, t, 1f);
        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
            if (parent.mInvalidationTransformation == null) {
                parent.mInvalidationTransformation = new Transformation();
            }
            invalidationTransform = parent.mInvalidationTransformation;
            a.getTransformation(drawingTime, invalidationTransform, 1f);
        } else {
            invalidationTransform = t;
        }
        if (more) {
            if (!a.willChangeBounds()) {
                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
                    parent.invalidate(mLeft, mTop, mRight, mBottom);
                }
            } else {
                if (parent.mInvalidateRegion == null) {
                    parent.mInvalidateRegion = new RectF();
                }
                final RectF region = parent.mInvalidateRegion;
                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
                        invalidationTransform);
                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
                final int left = mLeft + (int) region.left;
                final int top = mTop + (int) region.top;
                parent.invalidate(left, top, left + (int) (region.width() + .5f),
                        top + (int) (region.height() + .5f));
            }
        }
        return more;
    }
    void setDisplayListProperties(RenderNode renderNode) {
        if (renderNode != null) {
            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
            renderNode.setClipToBounds(mParent instanceof ViewGroup
                    && ((ViewGroup) mParent).getClipChildren());
            float alpha = 1;
            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
                ViewGroup parentVG = (ViewGroup) mParent;
                final Transformation t = parentVG.getChildTransformation();
                if (parentVG.getChildStaticTransformation(this, t)) {
                    final int transformType = t.getTransformationType();
                    if (transformType != Transformation.TYPE_IDENTITY) {
                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
                            alpha = t.getAlpha();
                        }
                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
                            renderNode.setStaticMatrix(t.getMatrix());
                        }
                    }
                }
            }
            if (mTransformationInfo != null) {
                if (alpha < 1) {
                    if (onSetAlpha(multipliedAlpha)) {
                        alpha = 1;
                    }
                }
                renderNode.setAlpha(alpha);
            } else if (alpha < 1) {
                renderNode.setAlpha(alpha);
            }
        }
    }
    protected final boolean drawsWithRenderNode(@NonNull Canvas canvas) {
        return mAttachInfo != null
                && mAttachInfo.mHardwareAccelerated
                && canvas.isHardwareAccelerated();
    }
    boolean draw(@NonNull Canvas canvas, ViewGroup parent, long drawingTime) {
        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
        boolean drawingWithRenderNode = drawsWithRenderNode(canvas);
        boolean more = false;
        final boolean childHasIdentityMatrix = hasIdentityMatrix();
        final int parentFlags = parent.mGroupFlags;
        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
            parent.getChildTransformation().clear();
            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
        }
        Transformation transformToApply = null;
        boolean concatMatrix = false;
        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
        final Animation a = getAnimation();
        if (a != null) {
            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
            concatMatrix = a.willChangeTransformationMatrix();
            if (concatMatrix) {
                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
            }
            transformToApply = parent.getChildTransformation();
        } else {
            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
                mRenderNode.setAnimationMatrix(null);
                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
            }
            if (!drawingWithRenderNode
                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
                final Transformation t = parent.getChildTransformation();
                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
                if (hasTransform) {
                    final int transformType = t.getTransformationType();
                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
                }
            }
        }
        concatMatrix |= !childHasIdentityMatrix;
        mPrivateFlags |= PFLAG_DRAWN;
        if (!concatMatrix &&
                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
                canvas.quickReject(mLeft, mTop, mRight, mBottom) &&
                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
            return more;
        }
        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
        if (hardwareAcceleratedCanvas) {
            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
            mPrivateFlags &= ~PFLAG_INVALIDATED;
        }
        RenderNode renderNode = null;
        Bitmap cache = null;
        int layerType = getLayerType();        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
             if (layerType != LAYER_TYPE_NONE) {
                 layerType = LAYER_TYPE_SOFTWARE;
                 buildDrawingCache(true);
            }
            cache = getDrawingCache(true);
        }
        if (drawingWithRenderNode) {
            renderNode = updateDisplayListIfDirty();
            if (!renderNode.hasDisplayList()) {
                renderNode = null;
                drawingWithRenderNode = false;
            }
        }
        int sx = 0;
        int sy = 0;
        if (!drawingWithRenderNode) {
            computeScroll();
            sx = mScrollX;
            sy = mScrollY;
        }
        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
        int restoreTo = -1;
        if (!drawingWithRenderNode || transformToApply != null) {
            restoreTo = canvas.save();
        }
        if (offsetForScroll) {
            canvas.translate(mLeft - sx, mTop - sy);
        } else {
            if (!drawingWithRenderNode) {
                canvas.translate(mLeft, mTop);
            }
            if (scalingRequired) {
                if (drawingWithRenderNode) {
                    restoreTo = canvas.save();
                }
                final float scale = 1.0f / mAttachInfo.mApplicationScale;
                canvas.scale(scale, scale);
            }
        }
        if (transformToApply != null
                || alpha < 1
                || !hasIdentityMatrix()
                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
            if (transformToApply != null || !childHasIdentityMatrix) {
                int transX = 0;
                int transY = 0;
                if (offsetForScroll) {
                    transX = -sx;
                    transY = -sy;
                }
                if (transformToApply != null) {
                    if (concatMatrix) {
                        if (drawingWithRenderNode) {
                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
                        } else {
                            canvas.translate(-transX, -transY);
                            canvas.concat(transformToApply.getMatrix());
                            canvas.translate(transX, transY);
                        }
                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
                    }
                    float transformAlpha = transformToApply.getAlpha();
                    if (transformAlpha < 1) {
                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
                    }
                }
                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
                    canvas.translate(-transX, -transY);
                    canvas.concat(getMatrix());
                    canvas.translate(transX, transY);
                }
            }
            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
                if (alpha < 1) {
                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
                } else {
                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
                }
                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
                if (!drawingWithDrawingCache) {
                    if (!onSetAlpha(multipliedAlpha)) {
                        if (drawingWithRenderNode) {
                        } else if (layerType == LAYER_TYPE_NONE) {
                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
                                    multipliedAlpha);
                        }
                    } else {
                        mPrivateFlags |= PFLAG_ALPHA_SET;
                    }
                }
            }
        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
            onSetAlpha(255);
            mPrivateFlags &= ~PFLAG_ALPHA_SET;
        }
        if (!drawingWithRenderNode) {
            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
                if (offsetForScroll) {
                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
                } else {
                    if (!scalingRequired || cache == null) {
                        canvas.clipRect(0, 0, getWidth(), getHeight());
                    } else {
                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
                    }
                }
            }
            if (mClipBounds != null) {
                canvas.clipRect(mClipBounds);
            }
        }
        if (!drawingWithDrawingCache) {
            if (drawingWithRenderNode) {
                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                ((RecordingCanvas) canvas).drawRenderNode(renderNode);
            } else {
                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                    dispatchDraw(canvas);
                } else {
                    draw(canvas);
                }
            }
        } else if (cache != null) {
            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
                Paint cachePaint = parent.mCachePaint;
                if (cachePaint == null) {
                    cachePaint = new Paint();
                    cachePaint.setDither(false);
                    parent.mCachePaint = cachePaint;
                }
                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
            } else {
                int layerPaintAlpha = mLayerPaint.getAlpha();
                if (alpha < 1) {
                }
                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
                if (alpha < 1) {
                    mLayerPaint.setAlpha(layerPaintAlpha);
                }
            }
        }
        if (restoreTo >= 0) {
            canvas.restoreToCount(restoreTo);
        }
        if (a != null && !more) {
            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
                onSetAlpha(255);
            }
            parent.finishAnimatingView(this, a);
        }
        if (more && hardwareAcceleratedCanvas) {
            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
                invalidate(true);
            }
        }
        mRecreateDisplayList = false;
        return more;
    }
    static Paint getDebugPaint() {
        if (sDebugPaint == null) {
            sDebugPaint = new Paint();
            sDebugPaint.setAntiAlias(false);
        }
        return sDebugPaint;
    }
    final int dipsToPixels(int dips) {
        float scale = getContext().getResources().getDisplayMetrics().density;
    }
    private void debugDrawFocus(@NonNull Canvas canvas) {
        if (isFocused()) {
            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
            final int l = mScrollX;
            final int r = l + mRight - mLeft;
            final int t = mScrollY;
            final int b = t + mBottom - mTop;
            final Paint paint = getDebugPaint();
            paint.setColor(DEBUG_CORNERS_COLOR);
            paint.setStyle(Paint.Style.FILL);
            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
            paint.setStyle(Paint.Style.STROKE);
            canvas.drawLine(l, t, r, b, paint);
            canvas.drawLine(l, b, r, t, paint);
        }
    }
    @CallSuper
    public void draw(@NonNull Canvas canvas) {
        final int privateFlags = mPrivateFlags;
        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
        int saveCount;
        drawBackground(canvas);
        final int viewFlags = mViewFlags;
        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
        if (!verticalEdges && !horizontalEdges) {
            onDraw(canvas);
            dispatchDraw(canvas);
            drawAutofilledHighlight(canvas);
            if (mOverlay != null && !mOverlay.isEmpty()) {
                mOverlay.getOverlayView().dispatchDraw(canvas);
            }
            onDrawForeground(canvas);
            drawDefaultFocusHighlight(canvas);
            if (isShowingLayoutBounds()) {
                debugDrawFocus(canvas);
            }
            return;
        }
        boolean drawTop = false;
        boolean drawBottom = false;
        boolean drawLeft = false;
        boolean drawRight = false;
        float topFadeStrength = 0.0f;
        float bottomFadeStrength = 0.0f;
        float leftFadeStrength = 0.0f;
        float rightFadeStrength = 0.0f;
        int paddingLeft = mPaddingLeft;
        final boolean offsetRequired = isPaddingOffsetRequired();
        if (offsetRequired) {
            paddingLeft += getLeftPaddingOffset();
        }
        int left = mScrollX + paddingLeft;
        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
        int top = mScrollY + getFadeTop(offsetRequired);
        int bottom = top + getFadeHeight(offsetRequired);
        if (offsetRequired) {
            right += getRightPaddingOffset();
            bottom += getBottomPaddingOffset();
        }
        final ScrollabilityCache scrollabilityCache = mScrollCache;
        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
        int length = (int) fadeHeight;
        if (verticalEdges && (top + length > bottom - length)) {
            length = (bottom - top) / 2;
        }
        if (horizontalEdges && (left + length > right - length)) {
            length = (right - left) / 2;
        }
        if (verticalEdges) {
            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
        }
        if (horizontalEdges) {
            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
        }
        saveCount = canvas.getSaveCount();
        int topSaveCount = -1;
        int bottomSaveCount = -1;
        int leftSaveCount = -1;
        int rightSaveCount = -1;
        int solidColor = getSolidColor();
        if (solidColor == 0) {
            if (drawTop) {
                topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
            }
            if (drawBottom) {
                bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
            }
            if (drawLeft) {
                leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
            }
            if (drawRight) {
                rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
            }
        } else {
            scrollabilityCache.setFadeColor(solidColor);
        }
        onDraw(canvas);
        dispatchDraw(canvas);
        final Paint p = scrollabilityCache.paint;
        final Matrix matrix = scrollabilityCache.matrix;
        final Shader fade = scrollabilityCache.shader;
        if (drawRight) {
            matrix.postRotate(90);
            matrix.postTranslate(right, top);
            fade.setLocalMatrix(matrix);
            p.setShader(fade);
            if (solidColor == 0) {
                canvas.restoreUnclippedLayer(rightSaveCount, p);
            } else {
                canvas.drawRect(right - length, top, right, bottom, p);
            }
        }
        if (drawLeft) {
            matrix.postRotate(-90);
            matrix.postTranslate(left, top);
            fade.setLocalMatrix(matrix);
            p.setShader(fade);
            if (solidColor == 0) {
                canvas.restoreUnclippedLayer(leftSaveCount, p);
            } else {
                canvas.drawRect(left, top, left + length, bottom, p);
            }
        }
        if (drawBottom) {
            matrix.postRotate(180);
            matrix.postTranslate(left, bottom);
            fade.setLocalMatrix(matrix);
            p.setShader(fade);
            if (solidColor == 0) {
                canvas.restoreUnclippedLayer(bottomSaveCount, p);
            } else {
                canvas.drawRect(left, bottom - length, right, bottom, p);
            }
        }
        if (drawTop) {
            matrix.postTranslate(left, top);
            fade.setLocalMatrix(matrix);
            p.setShader(fade);
            if (solidColor == 0) {
                canvas.restoreUnclippedLayer(topSaveCount, p);
            } else {
                canvas.drawRect(left, top, right, top + length, p);
            }
        }
        canvas.restoreToCount(saveCount);
        drawAutofilledHighlight(canvas);
        if (mOverlay != null && !mOverlay.isEmpty()) {
            mOverlay.getOverlayView().dispatchDraw(canvas);
        }
        onDrawForeground(canvas);
        drawDefaultFocusHighlight(canvas);
        if (isShowingLayoutBounds()) {
            debugDrawFocus(canvas);
        }
    }
    @UnsupportedAppUsage
    private void drawBackground(@NonNull Canvas canvas) {
        final Drawable background = mBackground;
        if (background == null) {
            return;
        }
        setBackgroundBounds();
        if (canvas.isHardwareAccelerated() && mAttachInfo != null
                && mAttachInfo.mThreadedRenderer != null) {
            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
            final RenderNode renderNode = mBackgroundRenderNode;
            if (renderNode != null && renderNode.hasDisplayList()) {
                setBackgroundRenderNodeProperties(renderNode);
                ((RecordingCanvas) canvas).drawRenderNode(renderNode);
                return;
            }
        }
        final int scrollX = mScrollX;
        final int scrollY = mScrollY;
        if ((scrollX | scrollY) == 0) {
            background.draw(canvas);
        } else {
            canvas.translate(scrollX, scrollY);
            background.draw(canvas);
            canvas.translate(-scrollX, -scrollY);
        }
    }
    void setBackgroundBounds() {
        if (mBackgroundSizeChanged && mBackground != null) {
            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
            mBackgroundSizeChanged = false;
            rebuildOutline();
        }
    }
    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
        renderNode.setTranslationX(mScrollX);
        renderNode.setTranslationY(mScrollY);
    }
    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
        if (renderNode == null) {
            renderNode = RenderNode.create(drawable.getClass().getName(),
                    new ViewAnimationHostBridge(this));
            renderNode.setUsageHint(RenderNode.USAGE_BACKGROUND);
        }
        final Rect bounds = drawable.getBounds();
        final int width = bounds.width();
        final int height = bounds.height();
        renderNode.clearStretch();
        final RecordingCanvas canvas = renderNode.beginRecording(width, height);
        canvas.translate(-bounds.left, -bounds.top);
        try {
            drawable.draw(canvas);
        } finally {
            renderNode.endRecording();
        }
        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
        renderNode.setProjectBackwards(drawable.isProjected());
        renderNode.setProjectionReceiver(true);
        renderNode.setClipToBounds(false);
        return renderNode;
    }
    public ViewOverlay getOverlay() {
        if (mOverlay == null) {
            mOverlay = new ViewOverlay(mContext, this);
        }
        return mOverlay;
    }
    @ViewDebug.ExportedProperty(category = "drawing")
    @InspectableProperty
    @ColorInt
    public int getSolidColor() {
        return 0;
    }
    private static String printFlags(int flags) {
        String output = "";
        int numFlags = 0;
        if ((flags & FOCUSABLE) == FOCUSABLE) {
            output += "TAKES_FOCUS";
            numFlags++;
        }
        switch (flags & VISIBILITY_MASK) {
        case INVISIBLE:
            if (numFlags > 0) {
                output += " ";
            }
            output += "INVISIBLE";
            break;
        case GONE:
            if (numFlags > 0) {
                output += " ";
            }
            output += "GONE";
            break;
        default:
            break;
        }
        return output;
    }
    private static String printPrivateFlags(int privateFlags) {
        String output = "";
        int numFlags = 0;
        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
            output += "WANTS_FOCUS";
            numFlags++;
        }
        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
            if (numFlags > 0) {
                output += " ";
            }
            output += "FOCUSED";
            numFlags++;
        }
        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
            if (numFlags > 0) {
                output += " ";
            }
            output += "SELECTED";
            numFlags++;
        }
        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
            if (numFlags > 0) {
                output += " ";
            }
            output += "IS_ROOT_NAMESPACE";
            numFlags++;
        }
        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
            if (numFlags > 0) {
                output += " ";
            }
            output += "HAS_BOUNDS";
            numFlags++;
        }
        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
            if (numFlags > 0) {
                output += " ";
            }
            output += "DRAWN";
        }
        return output;
    }
    public boolean isLayoutRequested() {
        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
    }
    public static boolean isLayoutModeOptical(Object o) {
        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
    }
    public static void setTraceLayoutSteps(boolean traceLayoutSteps) {
        sTraceLayoutSteps = traceLayoutSteps;
    }
    public static void setTracedRequestLayoutClassClass(String s) {
        sTraceRequestLayoutClass = s;
    }
    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
        Insets parentInsets = mParent instanceof View ?
                ((View) mParent).getOpticalInsets() : Insets.NONE;
        Insets childInsets = getOpticalInsets();
        return setFrame(
                left   + parentInsets.left - childInsets.left,
                top    + parentInsets.top  - childInsets.top,
                right  + parentInsets.left + childInsets.right,
                bottom + parentInsets.top  + childInsets.bottom);
    }
    @SuppressWarnings({"unchecked"})
    public void layout(int l, int t, int r, int b) {
        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
            if (isTraversalTracingEnabled()) {
                Trace.beginSection(mTracingStrings.onMeasureBeforeLayout);
            }
            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
            if (isTraversalTracingEnabled()) {
                Trace.endSection();
            }
            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
        }
        int oldL = mLeft;
        int oldT = mTop;
        int oldB = mBottom;
        int oldR = mRight;
        boolean changed = isLayoutModeOptical(mParent) ?
                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
            if (isTraversalTracingEnabled()) {
                Trace.beginSection(mTracingStrings.onLayout);
            }
            onLayout(changed, l, t, r, b);
            if (isTraversalTracingEnabled()) {
                Trace.endSection();
            }
            if (shouldDrawRoundScrollbar()) {
                if(mRoundScrollbarRenderer == null) {
                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
                }
            } else {
                mRoundScrollbarRenderer = null;
            }
            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnLayoutChangeListeners != null) {
                ArrayList<OnLayoutChangeListener> listenersCopy =
                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
                int numListeners = listenersCopy.size();
                for (int i = 0; i < numListeners; ++i) {
                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
                }
            }
        }
        final boolean wasLayoutValid = isLayoutValid();
        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
        if (!wasLayoutValid && isFocused()) {
            mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
            if (canTakeFocus()) {
                clearParentsWantFocus();
            } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) {
                clearParentsWantFocus();
            } else if (!hasParentWantsFocus()) {
            }
        } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
            mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
            View focused = findFocus();
            if (focused != null) {
                if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
                }
            }
        }
        if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
            mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
            notifyEnterOrExitForAutoFillIfNeeded(true);
        }
        notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
    }
    private boolean hasParentWantsFocus() {
        ViewParent parent = mParent;
        while (parent instanceof ViewGroup) {
            ViewGroup pv = (ViewGroup) parent;
            if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
                return true;
            }
            parent = pv.mParent;
        }
        return false;
    }
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    protected boolean setFrame(int left, int top, int right, int bottom) {
        boolean changed = false;
        if (DBG) {
            Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + ","
                    + right + "," + bottom + ")");
        }
        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
            changed = true;
            int drawn = mPrivateFlags & PFLAG_DRAWN;
            int oldWidth = mRight - mLeft;
            int oldHeight = mBottom - mTop;
            int newWidth = right - left;
            int newHeight = bottom - top;
            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
            invalidate(sizeChanged);
            mLeft = left;
            mTop = top;
            mRight = right;
            mBottom = bottom;
            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
            mPrivateFlags |= PFLAG_HAS_BOUNDS;
            if (sizeChanged) {
                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
            }
            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
                mPrivateFlags |= PFLAG_DRAWN;
                invalidate(sizeChanged);
                invalidateParentCaches();
            }
            mPrivateFlags |= drawn;
            mBackgroundSizeChanged = true;
            mDefaultFocusHighlightSizeChanged = true;
            if (mForegroundInfo != null) {
                mForegroundInfo.mBoundsChanged = true;
            }
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
        return changed;
    }
    public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {
        setFrame(left, top, right, bottom);
    }
    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
        if (mAttachInfo != null && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
            boolean isSmall;
            if (sToolkitFrameRateSmallUsesPercentReadOnlyFlagValue) {
                float percent = size / mAttachInfo.mDisplayPixelCount;
                isSmall = percent <= FRAME_RATE_SIZE_PERCENTAGE_THRESHOLD;
            } else {
                float density = mAttachInfo.mDensity;
                isSmall = newWidth <= narrowSize || newHeight <= narrowSize
                        || (newWidth <= smallSize && newHeight <= smallSize);
            }
            if (isSmall) {
                int category = sToolkitFrameRateBySizeReadOnlyFlagValue
                        ? FRAME_RATE_CATEGORY_LOW : FRAME_RATE_CATEGORY_NORMAL;
                mSizeBasedFrameRateCategoryAndReason = category | FRAME_RATE_CATEGORY_REASON_SMALL;
            } else {
                int category = sToolkitFrameRateDefaultNormalReadOnlyFlagValue
                        ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
                mSizeBasedFrameRateCategoryAndReason = category | FRAME_RATE_CATEGORY_REASON_LARGE;
            }
        }
        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
        if (mOverlay != null) {
            mOverlay.getOverlayView().setRight(newWidth);
            mOverlay.getOverlayView().setBottom(newHeight);
        }
        if (!sCanFocusZeroSized && isLayoutValid()
                && !(mParent instanceof ViewGroup && ((ViewGroup) mParent).isLayoutSuppressed())) {
            if (newWidth <= 0 || newHeight <= 0) {
                if (hasFocus()) {
                    clearFocus();
                    if (mParent instanceof ViewGroup) {
                        ((ViewGroup) mParent).clearFocusedInCluster();
                    }
                }
                clearAccessibilityFocus();
            } else if (oldWidth <= 0 || oldHeight <= 0) {
                if (mParent != null && canTakeFocus()) {
                    mParent.focusableViewAvailable(this);
                }
            }
        }
        rebuildOutline();
        if (onCheckIsTextEditor() || mHandwritingDelegatorCallback != null) {
            setHandwritingArea(new Rect(0, 0, newWidth, newHeight));
        }
    }
    @CallSuper
    protected void onFinishInflate() {
    }
    public Resources getResources() {
        return mResources;
    }
    @Override
    public void invalidateDrawable(@NonNull Drawable drawable) {
        if (verifyDrawable(drawable)) {
            final Rect dirty = drawable.getDirtyBounds();
            final int scrollX = mScrollX;
            final int scrollY = mScrollY;
            invalidate(dirty.left + scrollX, dirty.top + scrollY,
                    dirty.right + scrollX, dirty.bottom + scrollY);
            rebuildOutline();
        }
    }
    @Override
    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
        if (verifyDrawable(who) && what != null) {
            final long delay = when - SystemClock.uptimeMillis();
            if (mAttachInfo != null) {
                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
                        Choreographer.CALLBACK_ANIMATION, what, who,
                        Choreographer.subtractFrameDelay(delay));
            } else {
                getRunQueue().postDelayed(what, delay);
            }
        }
    }
    @Override
    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
        if (verifyDrawable(who) && what != null) {
            if (mAttachInfo != null) {
                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
                        Choreographer.CALLBACK_ANIMATION, what, who);
            }
            getRunQueue().removeCallbacks(what);
        }
    }
    public void unscheduleDrawable(Drawable who) {
        if (mAttachInfo != null && who != null) {
            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
                    Choreographer.CALLBACK_ANIMATION, null, who);
        }
    }
    protected void resolveDrawables() {
        if (!isLayoutDirectionResolved() &&
                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
            return;
        }
        final int layoutDirection = isLayoutDirectionResolved() ?
                getLayoutDirection() : getRawLayoutDirection();
        if (mBackground != null) {
            mBackground.setLayoutDirection(layoutDirection);
        }
        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
        }
        if (mDefaultFocusHighlight != null) {
            mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
        }
        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
        onResolveDrawables(layoutDirection);
    }
    boolean areDrawablesResolved() {
        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
    }
    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
    }
    @TestApi
    protected void resetResolvedDrawables() {
        resetResolvedDrawablesInternal();
    }
    void resetResolvedDrawablesInternal() {
        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
    }
    @CallSuper
    protected boolean verifyDrawable(@NonNull Drawable who) {
        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
                || (mDefaultFocusHighlight == who);
    }
    @CallSuper
    protected void drawableStateChanged() {
        final int[] state = getDrawableState();
        boolean changed = false;
        final Drawable bg = mBackground;
        if (bg != null && bg.isStateful()) {
            changed |= bg.setState(state);
        }
        final Drawable hl = mDefaultFocusHighlight;
        if (hl != null && hl.isStateful()) {
            changed |= hl.setState(state);
        }
        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
        if (fg != null && fg.isStateful()) {
            changed |= fg.setState(state);
        }
        if (mScrollCache != null) {
            final Drawable scrollBar = mScrollCache.scrollBar;
            if (scrollBar != null && scrollBar.isStateful()) {
                changed |= scrollBar.setState(state)
                        && mScrollCache.state != ScrollabilityCache.OFF;
            }
        }
        if (mStateListAnimator != null) {
            mStateListAnimator.setState(state);
        }
        if (!isAggregatedVisible()) {
            jumpDrawablesToCurrentState();
        }
        if (changed) {
            invalidate();
        }
    }
    @CallSuper
    public void drawableHotspotChanged(float x, float y) {
        if (mBackground != null) {
            mBackground.setHotspot(x, y);
        }
        if (mDefaultFocusHighlight != null) {
            mDefaultFocusHighlight.setHotspot(x, y);
        }
        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
            mForegroundInfo.mDrawable.setHotspot(x, y);
        }
        dispatchDrawableHotspotChanged(x, y);
    }
    public void dispatchDrawableHotspotChanged(float x, float y) {
    }
    public void refreshDrawableState() {
        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
        drawableStateChanged();
        ViewParent parent = mParent;
        if (parent != null) {
            parent.childDrawableStateChanged(this);
        }
    }
    private Drawable getDefaultFocusHighlightDrawable() {
        if (mDefaultFocusHighlightCache == null) {
            if (mContext != null) {
                final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
                final TypedArray ta = mContext.obtainStyledAttributes(attrs);
                mDefaultFocusHighlightCache = ta.getDrawable(0);
                ta.recycle();
            }
        }
        return mDefaultFocusHighlightCache;
    }
    private void setDefaultFocusHighlight(Drawable highlight) {
        mDefaultFocusHighlight = highlight;
        mDefaultFocusHighlightSizeChanged = true;
        if (highlight != null) {
            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
            }
            highlight.setLayoutDirection(getLayoutDirection());
            if (highlight.isStateful()) {
                highlight.setState(getDrawableState());
            }
            if (isAttachedToWindow()) {
                highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
            }
            highlight.setCallback(this);
        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
                && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
            mPrivateFlags |= PFLAG_SKIP_DRAW;
        }
        invalidate();
    }
    @TestApi
    public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
        final boolean lackFocusState = (background == null || !background.isStateful()
                || !background.hasFocusStateSpecified())
                && (foreground == null || !foreground.isStateful()
                || !foreground.hasFocusStateSpecified());
        return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
                && isAttachedToWindow() && sUseDefaultFocusHighlight;
    }
    private void switchDefaultFocusHighlight() {
        if (isFocused()) {
            final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
                    mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
            final boolean active = mDefaultFocusHighlight != null;
            if (needed && !active) {
                setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
            } else if (!needed && active) {
                setDefaultFocusHighlight(null);
            }
        }
    }
    private void drawDefaultFocusHighlight(@NonNull Canvas canvas) {
        if (mDefaultFocusHighlight != null && isFocused()) {
            if (mDefaultFocusHighlightSizeChanged) {
                mDefaultFocusHighlightSizeChanged = false;
                final int l = mScrollX;
                final int r = l + mRight - mLeft;
                final int t = mScrollY;
                final int b = t + mBottom - mTop;
                mDefaultFocusHighlight.setBounds(l, t, r, b);
            }
            mDefaultFocusHighlight.draw(canvas);
        }
    }
    public final int[] getDrawableState() {
        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
            return mDrawableState;
        } else {
            mDrawableState = onCreateDrawableState(0);
            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
            return mDrawableState;
        }
    }
    protected int[] onCreateDrawableState(int extraSpace) {
        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
                mParent instanceof View) {
            return ((View) mParent).onCreateDrawableState(extraSpace);
        }
        int[] drawableState;
        int privateFlags = mPrivateFlags;
        int viewStateIndex = 0;
        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested) {
            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
        }
        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
        final int privateFlags2 = mPrivateFlags2;
        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
        }
        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
        }
        drawableState = StateSet.get(viewStateIndex);
        if (false) {
            Log.i("View", "drawableStateIndex=" + viewStateIndex);
            Log.i("View", toString()
                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
                    + " fo=" + hasFocus()
                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
                    + " wf=" + hasWindowFocus()
                    + ": " + Arrays.toString(drawableState));
        }
        if (extraSpace == 0) {
            return drawableState;
        }
        final int[] fullState;
        if (drawableState != null) {
            fullState = new int[drawableState.length + extraSpace];
            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
        } else {
            fullState = new int[extraSpace];
        }
        return fullState;
    }
    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
        final int N = baseState.length;
        int i = N - 1;
        while (i >= 0 && baseState[i] == 0) {
            i--;
        }
        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
        return baseState;
    }
    @CallSuper
    public void jumpDrawablesToCurrentState() {
        if (mBackground != null) {
            mBackground.jumpToCurrentState();
        }
        if (mStateListAnimator != null) {
            mStateListAnimator.jumpToCurrentState();
        }
        if (mDefaultFocusHighlight != null) {
            mDefaultFocusHighlight.jumpToCurrentState();
        }
        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
            mForegroundInfo.mDrawable.jumpToCurrentState();
        }
    }
    @RemotableViewMethod
    public void setBackgroundColor(@ColorInt int color) {
        if (mBackground instanceof ColorDrawable) {
            ((ColorDrawable) mBackground.mutate()).setColor(color);
            computeOpaqueFlags();
            mBackgroundResource = 0;
        } else {
            setBackground(new ColorDrawable(color));
        }
    }
    @RemotableViewMethod
    public void setBackgroundResource(@DrawableRes int resid) {
        if (resid != 0 && resid == mBackgroundResource) {
            return;
        }
        Drawable d = null;
        if (resid != 0) {
            d = mContext.getDrawable(resid);
        }
        setBackground(d);
        mBackgroundResource = resid;
    }
    public void setBackground(Drawable background) {
        setBackgroundDrawable(background);
    }
    @Deprecated
    public void setBackgroundDrawable(Drawable background) {
        computeOpaqueFlags();
        if (background == mBackground) {
            return;
        }
        boolean requestLayout = false;
        mBackgroundResource = 0;
        if (mBackground != null) {
            if (isAttachedToWindow()) {
                mBackground.setVisible(false, false);
            }
            mBackground.setCallback(null);
            unscheduleDrawable(mBackground);
        }
        if (background != null) {
            Rect padding = sThreadLocal.get();
            if (padding == null) {
                padding = new Rect();
                sThreadLocal.set(padding);
            }
            resetResolvedDrawablesInternal();
            background.setLayoutDirection(getLayoutDirection());
            if (background.getPadding(padding)) {
                resetResolvedPaddingInternal();
                switch (background.getLayoutDirection()) {
                    case LAYOUT_DIRECTION_RTL:
                        mUserPaddingLeftInitial = padding.right;
                        mUserPaddingRightInitial = padding.left;
                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
                        break;
                    case LAYOUT_DIRECTION_LTR:
                    default:
                        mUserPaddingLeftInitial = padding.left;
                        mUserPaddingRightInitial = padding.right;
                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
                }
                mLeftPaddingDefined = false;
                mRightPaddingDefined = false;
            }
            if (mBackground == null
                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
                requestLayout = true;
            }
            mBackground = background;
            if (background.isStateful()) {
                background.setState(getDrawableState());
            }
            if (isAttachedToWindow()) {
                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
            }
            applyBackgroundTint();
            background.setCallback(this);
            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
                requestLayout = true;
            }
        } else {
            mBackground = null;
            if ((mViewFlags & WILL_NOT_DRAW) != 0
                    && (mDefaultFocusHighlight == null)
                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
                mPrivateFlags |= PFLAG_SKIP_DRAW;
            }
            requestLayout = true;
        }
        computeOpaqueFlags();
        if (requestLayout) {
            requestLayout();
        }
        mBackgroundSizeChanged = true;
        invalidate(true);
        invalidateOutline();
    }
    @InspectableProperty
    public Drawable getBackground() {
        return mBackground;
    }
    @RemotableViewMethod
    public void setBackgroundTintList(@Nullable ColorStateList tint) {
        if (mBackgroundTint == null) {
            mBackgroundTint = new TintInfo();
        }
        mBackgroundTint.mTintList = tint;
        mBackgroundTint.mHasTintList = true;
        applyBackgroundTint();
    }
    @InspectableProperty(name = "backgroundTint")
    @Nullable
    public ColorStateList getBackgroundTintList() {
        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
    }
    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
        BlendMode mode = null;
        if (tintMode != null) {
            mode = BlendMode.fromValue(tintMode.nativeInt);
        }
        setBackgroundTintBlendMode(mode);
    }
    @RemotableViewMethod
    public void setBackgroundTintBlendMode(@Nullable BlendMode blendMode) {
        if (mBackgroundTint == null) {
            mBackgroundTint = new TintInfo();
        }
        mBackgroundTint.mBlendMode = blendMode;
        mBackgroundTint.mHasTintMode = true;
        applyBackgroundTint();
    }
    @Nullable
    @InspectableProperty
    public PorterDuff.Mode getBackgroundTintMode() {
        PorterDuff.Mode porterDuffMode;
        if (mBackgroundTint != null && mBackgroundTint.mBlendMode != null) {
            porterDuffMode = BlendMode.blendModeToPorterDuffMode(mBackgroundTint.mBlendMode);
        } else {
            porterDuffMode = null;
        }
        return porterDuffMode;
    }
    public @Nullable BlendMode getBackgroundTintBlendMode() {
        return mBackgroundTint != null ? mBackgroundTint.mBlendMode : null;
    }
    private void applyBackgroundTint() {
        if (mBackground != null && mBackgroundTint != null) {
            final TintInfo tintInfo = mBackgroundTint;
            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
                mBackground = mBackground.mutate();
                if (tintInfo.mHasTintList) {
                    mBackground.setTintList(tintInfo.mTintList);
                }
                if (tintInfo.mHasTintMode) {
                    mBackground.setTintBlendMode(tintInfo.mBlendMode);
                }
                if (mBackground.isStateful()) {
                    mBackground.setState(getDrawableState());
                }
            }
        }
    }
    @InspectableProperty
    public Drawable getForeground() {
        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
    }
    public void setForeground(Drawable foreground) {
        if (mForegroundInfo == null) {
            if (foreground == null) {
                return;
            }
            mForegroundInfo = new ForegroundInfo();
        }
        if (foreground == mForegroundInfo.mDrawable) {
            return;
        }
        if (mForegroundInfo.mDrawable != null) {
            if (isAttachedToWindow()) {
                mForegroundInfo.mDrawable.setVisible(false, false);
            }
            mForegroundInfo.mDrawable.setCallback(null);
            unscheduleDrawable(mForegroundInfo.mDrawable);
        }
        mForegroundInfo.mDrawable = foreground;
        mForegroundInfo.mBoundsChanged = true;
        if (foreground != null) {
            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
            }
            foreground.setLayoutDirection(getLayoutDirection());
            if (foreground.isStateful()) {
                foreground.setState(getDrawableState());
            }
            applyForegroundTint();
            if (isAttachedToWindow()) {
                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
            }
            foreground.setCallback(this);
        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
                && (mDefaultFocusHighlight == null)) {
            mPrivateFlags |= PFLAG_SKIP_DRAW;
        }
        requestLayout();
        invalidate();
    }
    public boolean isForegroundInsidePadding() {
        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
    }
    @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY)
    public int getForegroundGravity() {
        return mForegroundInfo != null ? mForegroundInfo.mGravity
                : Gravity.START | Gravity.TOP;
    }
    public void setForegroundGravity(int gravity) {
        if (mForegroundInfo == null) {
            mForegroundInfo = new ForegroundInfo();
        }
        if (mForegroundInfo.mGravity != gravity) {
            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
                gravity |= Gravity.START;
            }
            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
                gravity |= Gravity.TOP;
            }
            mForegroundInfo.mGravity = gravity;
            requestLayout();
        }
    }
    @RemotableViewMethod
    public void setForegroundTintList(@Nullable ColorStateList tint) {
        if (mForegroundInfo == null) {
            mForegroundInfo = new ForegroundInfo();
        }
        if (mForegroundInfo.mTintInfo == null) {
            mForegroundInfo.mTintInfo = new TintInfo();
        }
        mForegroundInfo.mTintInfo.mTintList = tint;
        mForegroundInfo.mTintInfo.mHasTintList = true;
        applyForegroundTint();
    }
    @InspectableProperty(name = "foregroundTint")
    @Nullable
    public ColorStateList getForegroundTintList() {
        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
                ? mForegroundInfo.mTintInfo.mTintList : null;
    }
    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
        BlendMode mode = null;
        if (tintMode != null) {
            mode = BlendMode.fromValue(tintMode.nativeInt);
        }
        setForegroundTintBlendMode(mode);
    }
    @RemotableViewMethod
    public void setForegroundTintBlendMode(@Nullable BlendMode blendMode) {
        if (mForegroundInfo == null) {
            mForegroundInfo = new ForegroundInfo();
        }
        if (mForegroundInfo.mTintInfo == null) {
            mForegroundInfo.mTintInfo = new TintInfo();
        }
        mForegroundInfo.mTintInfo.mBlendMode = blendMode;
        mForegroundInfo.mTintInfo.mHasTintMode = true;
        applyForegroundTint();
    }
    @InspectableProperty
    @Nullable
    public PorterDuff.Mode getForegroundTintMode() {
        BlendMode blendMode = mForegroundInfo != null && mForegroundInfo.mTintInfo != null
                ? mForegroundInfo.mTintInfo.mBlendMode : null;
        if (blendMode != null) {
            return BlendMode.blendModeToPorterDuffMode(blendMode);
        } else {
            return null;
        }
    }
    public @Nullable BlendMode getForegroundTintBlendMode() {
        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
                ? mForegroundInfo.mTintInfo.mBlendMode : null;
    }
    private void applyForegroundTint() {
        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
                && mForegroundInfo.mTintInfo != null) {
            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
                if (tintInfo.mHasTintList) {
                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
                }
                if (tintInfo.mHasTintMode) {
                    mForegroundInfo.mDrawable.setTintBlendMode(tintInfo.mBlendMode);
                }
                if (mForegroundInfo.mDrawable.isStateful()) {
                    mForegroundInfo.mDrawable.setState(getDrawableState());
                }
            }
        }
    }
    @Nullable private Drawable getAutofilledDrawable() {
        if (mAttachInfo == null) {
            return null;
        }
        if (mAttachInfo.mAutofilledDrawable == null) {
            Context rootContext = getRootView().getContext();
            TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
            int attributeResourceId = a.getResourceId(0, 0);
            mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
            a.recycle();
        }
        return mAttachInfo.mAutofilledDrawable;
    }
    private void drawAutofilledHighlight(@NonNull Canvas canvas) {
        if (isAutofilled() && !hideAutofillHighlight()) {
            Drawable autofilledHighlight = getAutofilledDrawable();
            if (autofilledHighlight != null) {
                autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
                autofilledHighlight.draw(canvas);
            }
        }
    }
    public void onDrawForeground(@NonNull Canvas canvas) {
        onDrawScrollIndicators(canvas);
        onDrawScrollBars(canvas);
        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
        if (foreground != null) {
            if (mForegroundInfo.mBoundsChanged) {
                mForegroundInfo.mBoundsChanged = false;
                final Rect selfBounds = mForegroundInfo.mSelfBounds;
                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
                if (mForegroundInfo.mInsidePadding) {
                    selfBounds.set(0, 0, getWidth(), getHeight());
                } else {
                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
                }
                final int ld = getLayoutDirection();
                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
                foreground.setBounds(overlayBounds);
            }
            foreground.draw(canvas);
        }
    }
    public void setPadding(int left, int top, int right, int bottom) {
        resetResolvedPaddingInternal();
        mUserPaddingStart = UNDEFINED_PADDING;
        mUserPaddingEnd = UNDEFINED_PADDING;
        mUserPaddingLeftInitial = left;
        mUserPaddingRightInitial = right;
        mLeftPaddingDefined = true;
        mRightPaddingDefined = true;
        internalSetPadding(left, top, right, bottom);
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768420)
    protected void internalSetPadding(int left, int top, int right, int bottom) {
        mUserPaddingLeft = left;
        mUserPaddingRight = right;
        mUserPaddingBottom = bottom;
        final int viewFlags = mViewFlags;
        boolean changed = false;
        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
                        ? 0 : getVerticalScrollbarWidth();
                switch (mVerticalScrollbarPosition) {
                    case SCROLLBAR_POSITION_DEFAULT:
                        if (isLayoutRtl()) {
                            left += offset;
                        } else {
                            right += offset;
                        }
                        break;
                    case SCROLLBAR_POSITION_RIGHT:
                        right += offset;
                        break;
                    case SCROLLBAR_POSITION_LEFT:
                        left += offset;
                        break;
                }
            }
            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
                        ? 0 : getHorizontalScrollbarHeight();
            }
        }
        if (mPaddingLeft != left) {
            changed = true;
            mPaddingLeft = left;
        }
        if (mPaddingTop != top) {
            changed = true;
            mPaddingTop = top;
        }
        if (mPaddingRight != right) {
            changed = true;
            mPaddingRight = right;
        }
        if (mPaddingBottom != bottom) {
            changed = true;
            mPaddingBottom = bottom;
        }
        if (changed) {
            requestLayout();
            invalidateOutline();
        }
    }
    public void setPaddingRelative(int start, int top, int end, int bottom) {
        resetResolvedPaddingInternal();
        mUserPaddingStart = start;
        mUserPaddingEnd = end;
        mLeftPaddingDefined = true;
        mRightPaddingDefined = true;
        switch(getLayoutDirection()) {
            case LAYOUT_DIRECTION_RTL:
                mUserPaddingLeftInitial = end;
                mUserPaddingRightInitial = start;
                internalSetPadding(end, top, start, bottom);
                break;
            case LAYOUT_DIRECTION_LTR:
            default:
                mUserPaddingLeftInitial = start;
                mUserPaddingRightInitial = end;
                internalSetPadding(start, top, end, bottom);
        }
    }
    @LayoutRes
    public int getSourceLayoutResId() {
        return mSourceLayoutId;
    }
    @InspectableProperty
    public int getPaddingTop() {
        return mPaddingTop;
    }
    @InspectableProperty
    public int getPaddingBottom() {
        return mPaddingBottom;
    }
    @InspectableProperty
    public int getPaddingLeft() {
        if (!isPaddingResolved()) {
            resolvePadding();
        }
        return mPaddingLeft;
    }
    public int getPaddingStart() {
        if (!isPaddingResolved()) {
            resolvePadding();
        }
        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
                mPaddingRight : mPaddingLeft;
    }
    @InspectableProperty
    public int getPaddingRight() {
        if (!isPaddingResolved()) {
            resolvePadding();
        }
        return mPaddingRight;
    }
    public int getPaddingEnd() {
        if (!isPaddingResolved()) {
            resolvePadding();
        }
        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
                mPaddingLeft : mPaddingRight;
    }
    public boolean isPaddingRelative() {
        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
    }
    Insets computeOpticalInsets() {
        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
    }
    @UnsupportedAppUsage
    public void resetPaddingToInitialValues() {
        if (isRtlCompatibilityMode()) {
            mPaddingLeft = mUserPaddingLeftInitial;
            mPaddingRight = mUserPaddingRightInitial;
            return;
        }
        if (isLayoutRtl()) {
            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
        } else {
            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
        }
    }
    public Insets getOpticalInsets() {
        if (mLayoutInsets == null) {
            mLayoutInsets = computeOpticalInsets();
        }
        return mLayoutInsets;
    }
    public void setOpticalInsets(Insets insets) {
        mLayoutInsets = insets;
    }
    public void setSelected(boolean selected) {
        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
            if (!selected) resetPressedState();
            invalidate(true);
            refreshDrawableState();
            dispatchSetSelected(selected);
            if (selected) {
                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
            } else {
                notifyViewAccessibilityStateChangedIfNeeded(
                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
            }
        }
    }
    protected void dispatchSetSelected(boolean selected) {
    }
    @ViewDebug.ExportedProperty
    @InspectableProperty(hasAttributeId = false)
    public boolean isSelected() {
        return (mPrivateFlags & PFLAG_SELECTED) != 0;
    }
    public void setActivated(boolean activated) {
        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
            invalidate(true);
            refreshDrawableState();
            dispatchSetActivated(activated);
        }
    }
    protected void dispatchSetActivated(boolean activated) {
    }
    @ViewDebug.ExportedProperty
    @InspectableProperty(hasAttributeId = false)
    public boolean isActivated() {
        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
    }
    public ViewTreeObserver getViewTreeObserver() {
        if (mAttachInfo != null) {
            return mAttachInfo.mTreeObserver;
        }
        if (mFloatingTreeObserver == null) {
            mFloatingTreeObserver = new ViewTreeObserver(mContext);
        }
        return mFloatingTreeObserver;
    }
    public View getRootView() {
        if (mAttachInfo != null) {
            final View v = mAttachInfo.mRootView;
            if (v != null) {
                return v;
            }
        }
        View parent = this;
        while (parent.mParent instanceof View) {
            parent = (View) parent.mParent;
        }
        return parent;
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public boolean toGlobalMotionEvent(MotionEvent ev) {
        final AttachInfo info = mAttachInfo;
        if (info == null) {
            return false;
        }
        final Matrix m = info.mTmpMatrix;
        m.set(Matrix.IDENTITY_MATRIX);
        transformMatrixToGlobal(m);
        ev.transform(m);
        return true;
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public boolean toLocalMotionEvent(MotionEvent ev) {
        final AttachInfo info = mAttachInfo;
        if (info == null) {
            return false;
        }
        final Matrix m = info.mTmpMatrix;
        m.set(Matrix.IDENTITY_MATRIX);
        transformMatrixToLocal(m);
        ev.transform(m);
        return true;
    }
    public void transformMatrixToGlobal(@NonNull Matrix matrix) {
        final ViewParent parent = mParent;
        if (parent instanceof View) {
            final View vp = (View) parent;
            vp.transformMatrixToGlobal(matrix);
            matrix.preTranslate(-vp.mScrollX, -vp.mScrollY);
        } else if (parent instanceof ViewRootImpl) {
            final ViewRootImpl vr = (ViewRootImpl) parent;
            vr.transformMatrixToGlobal(matrix);
            matrix.preTranslate(0, -vr.mCurScrollY);
        }
        matrix.preTranslate(mLeft, mTop);
        if (!hasIdentityMatrix()) {
            matrix.preConcat(getMatrix());
        }
    }
    public void transformMatrixToLocal(@NonNull Matrix matrix) {
        final ViewParent parent = mParent;
        if (parent instanceof View) {
            final View vp = (View) parent;
            vp.transformMatrixToLocal(matrix);
            matrix.postTranslate(vp.mScrollX, vp.mScrollY);
        } else if (parent instanceof ViewRootImpl) {
            final ViewRootImpl vr = (ViewRootImpl) parent;
            vr.transformMatrixToLocal(matrix);
            matrix.postTranslate(0, vr.mCurScrollY);
        }
        matrix.postTranslate(-mLeft, -mTop);
        if (!hasIdentityMatrix()) {
            matrix.postConcat(getInverseMatrix());
        }
    }
    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
            @ViewDebug.IntToString(from = 0, to = "x"),
            @ViewDebug.IntToString(from = 1, to = "y")
    })
    @UnsupportedAppUsage
    public int[] getLocationOnScreen() {
        int[] location = new int[2];
        getLocationOnScreen(location);
        return location;
    }
    public void getLocationOnScreen(@Size(2) int[] outLocation) {
        getLocationInWindow(outLocation);
        final AttachInfo info = mAttachInfo;
        if (info != null) {
            outLocation[0] += info.mWindowLeft;
            outLocation[1] += info.mWindowTop;
            info.mViewRootImpl.applyViewLocationSandboxingIfNeeded(outLocation);
        }
    }
    public void getLocationInWindow(@Size(2) int[] outLocation) {
        if (outLocation == null || outLocation.length < 2) {
            throw new IllegalArgumentException("outLocation must be an array of two integers");
        }
        outLocation[0] = 0;
        outLocation[1] = 0;
        transformFromViewToWindowSpace(outLocation);
    }
    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
        if (inOutLocation == null || inOutLocation.length < 2) {
            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
        }
        if (mAttachInfo == null) {
            inOutLocation[0] = inOutLocation[1] = 0;
            return;
        }
        float position[] = mAttachInfo.mTmpTransformLocation;
        position[0] = inOutLocation[0];
        position[1] = inOutLocation[1];
        if (!hasIdentityMatrix()) {
            getMatrix().mapPoints(position);
        }
        position[0] += mLeft;
        position[1] += mTop;
        ViewParent viewParent = mParent;
        while (viewParent instanceof View) {
            final View view = (View) viewParent;
            position[0] -= view.mScrollX;
            position[1] -= view.mScrollY;
            if (!view.hasIdentityMatrix()) {
                view.getMatrix().mapPoints(position);
            }
            position[0] += view.mLeft;
            position[1] += view.mTop;
            viewParent = view.mParent;
         }
        if (viewParent instanceof ViewRootImpl) {
            final ViewRootImpl vr = (ViewRootImpl) viewParent;
            position[1] -= vr.mCurScrollY;
        }
        inOutLocation[0] = Math.round(position[0]);
        inOutLocation[1] = Math.round(position[1]);
    }
    protected <T extends View> T findViewTraversal(@IdRes int id) {
        if (id == mID) {
            return (T) this;
        }
        return null;
    }
    protected <T extends View> T findViewWithTagTraversal(Object tag) {
        if (tag != null && tag.equals(mTag)) {
            return (T) this;
        }
        return null;
    }
    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
            View childToSkip) {
        if (predicate.test(this)) {
            return (T) this;
        }
        return null;
    }
    public final <T extends View> T findViewById(@IdRes int id) {
        if (id == NO_ID) {
            return null;
        }
        return findViewTraversal(id);
    }
    @NonNull
    public final <T extends View> T requireViewById(@IdRes int id) {
        T view = findViewById(id);
        if (view == null) {
            throw new IllegalArgumentException("ID does not reference a View inside this View");
        }
        return view;
    }
    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
        if (getAccessibilityViewId() == accessibilityId) {
            return (T) this;
        }
        return null;
    }
    public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
        if (getAutofillViewId() == autofillId) {
            return (T) this;
        }
        return null;
    }
    public final <T extends View> T findViewWithTag(Object tag) {
        if (tag == null) {
            return null;
        }
        return findViewWithTagTraversal(tag);
    }
    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
        return findViewByPredicateTraversal(predicate, null);
    }
    public final <T extends View> T findViewByPredicateInsideOut(
            View start, Predicate<View> predicate) {
        View childToSkip = null;
        for (;;) {
            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
            if (view != null || start == this) {
                return view;
            }
            ViewParent parent = start.getParent();
            if (parent == null || !(parent instanceof View)) {
                return null;
            }
            childToSkip = start;
            start = (View) parent;
        }
    }
    public void setId(@IdRes int id) {
        mID = id;
        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
            mID = generateViewId();
        }
    }
    @UnsupportedAppUsage
    @TestApi
    public void setIsRootNamespace(boolean isRoot) {
        if (isRoot) {
            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
        } else {
            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
        }
    }
    @UnsupportedAppUsage
    public boolean isRootNamespace() {
        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
    }
    @IdRes
    @ViewDebug.CapturedViewProperty
    @InspectableProperty
    public int getId() {
        return mID;
    }
    public long getUniqueDrawingId() {
        return mRenderNode.getUniqueId();
    }
    @ViewDebug.ExportedProperty
    @InspectableProperty
    public Object getTag() {
        return mTag;
    }
    public void setTag(final Object tag) {
        mTag = tag;
    }
    public Object getTag(int key) {
        if (mKeyedTags != null) return mKeyedTags.get(key);
        return null;
    }
    public void setTag(int key, final Object tag) {
        if ((key >>> 24) < 2) {
            throw new IllegalArgumentException("The key must be an application-specific "
                    + "resource id.");
        }
        setKeyedTag(key, tag);
    }
    @UnsupportedAppUsage
    public void setTagInternal(int key, Object tag) {
        if ((key >>> 24) != 0x1) {
            throw new IllegalArgumentException("The key must be a framework-specific "
                    + "resource id.");
        }
        setKeyedTag(key, tag);
    }
    private void setKeyedTag(int key, Object tag) {
        if (mKeyedTags == null) {
            mKeyedTags = new SparseArray<Object>(2);
        }
        mKeyedTags.put(key, tag);
    }
    @UnsupportedAppUsage
    public void debug() {
        debug(0);
    }
    @UnsupportedAppUsage
    protected void debug(int depth) {
        String output = debugIndent(depth - 1);
        output += "+ " + this;
        int id = getId();
        if (id != -1) {
            output += " (id=" + id + ")";
        }
        Object tag = getTag();
        if (tag != null) {
            output += " (tag=" + tag + ")";
        }
        Log.d(VIEW_LOG_TAG, output);
        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
            output = debugIndent(depth) + " FOCUSED";
            Log.d(VIEW_LOG_TAG, output);
        }
        output = debugIndent(depth);
        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
                + "} ";
        Log.d(VIEW_LOG_TAG, output);
        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
                || mPaddingBottom != 0) {
            output = debugIndent(depth);
            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
            Log.d(VIEW_LOG_TAG, output);
        }
        output = debugIndent(depth);
        output += "mMeasureWidth=" + mMeasuredWidth +
                " mMeasureHeight=" + mMeasuredHeight;
        Log.d(VIEW_LOG_TAG, output);
        output = debugIndent(depth);
        if (mLayoutParams == null) {
            output += "BAD! no layout params";
        } else {
            output = mLayoutParams.debug(output);
        }
        Log.d(VIEW_LOG_TAG, output);
        output = debugIndent(depth);
        output += "flags={";
        output += View.printFlags(mViewFlags);
        output += "}";
        Log.d(VIEW_LOG_TAG, output);
        output = debugIndent(depth);
        output += "privateFlags={";
        output += View.printPrivateFlags(mPrivateFlags);
        output += "}";
        Log.d(VIEW_LOG_TAG, output);
    }
    protected static String debugIndent(int depth) {
            spaces.append(' ').append(' ');
        }
        return spaces.toString();
    }
    @ViewDebug.ExportedProperty(category = "layout")
    @InspectableProperty
    public int getBaseline() {
        return -1;
    }
    public boolean isInLayout() {
        ViewRootImpl viewRoot = getViewRootImpl();
        return (viewRoot != null && viewRoot.isInLayout());
    }
    private void printStackStrace(String name) {
        Log.d(VIEW_LOG_TAG, "---- ST:" + name);
        StringBuilder sb = new StringBuilder();
        StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
        int startIndex = 1;
        int endIndex = Math.min(stackTraceElements.length, startIndex + 20);        for (int i = startIndex; i < endIndex; i++) {
            StackTraceElement s = stackTraceElements[i];
            sb.append(s.getMethodName())
                    .append("(")
                    .append(s.getFileName())
                    .append(":")
                    .append(s.getLineNumber())
                    .append(") <- ");
        }
        Log.d(VIEW_LOG_TAG, name + ": " + sb);
    }
    @CallSuper
    public void requestLayout() {
        if (isRelayoutTracingEnabled()) {
            Trace.instantForTrack(TRACE_TAG_APP, "requestLayoutTracing",
                    mTracingStrings.classSimpleName);
            printStackStrace(mTracingStrings.requestLayoutStacktracePrefix);
        }
        if (mMeasureCache != null) mMeasureCache.clear();
        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
            ViewRootImpl viewRoot = getViewRootImpl();
            if (viewRoot != null && viewRoot.isInLayout()) {
                if (!viewRoot.requestLayoutDuringLayout(this)) {
                    return;
                }
            }
            mAttachInfo.mViewRequestingLayout = this;
        }
        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
        mPrivateFlags |= PFLAG_INVALIDATED;
        if (mParent != null && !mParent.isLayoutRequested()) {
            mParent.requestLayout();
        }
        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
            mAttachInfo.mViewRequestingLayout = null;
        }
    }
    public void forceLayout() {
        if (mMeasureCache != null) mMeasureCache.clear();
        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
        mPrivateFlags |= PFLAG_INVALIDATED;
    }
    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
        boolean optical = isLayoutModeOptical(this);
        if (optical != isLayoutModeOptical(mParent)) {
            Insets insets = getOpticalInsets();
            int oWidth  = insets.left + insets.right;
            int oHeight = insets.top  + insets.bottom;
            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
        }
        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
                || heightMeasureSpec != mOldHeightMeasureSpec;
        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
        final boolean needsLayout = specChanged
                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
        if (forceLayout || needsLayout) {
            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
            resolveRtlPropertiesIfNeeded();
            int cacheIndex;
            if (sUseMeasureCacheDuringForceLayoutFlagValue) {
                cacheIndex =  mMeasureCache.indexOfKey(key);
            } else {
                cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
            }
            if (cacheIndex < 0) {
                if (isTraversalTracingEnabled()) {
                    Trace.beginSection(mTracingStrings.onMeasure);
                }
                if (android.os.Flags.adpfMeasureDuringInputEventBoost()) {
                    final boolean notifyRenderer = hasExpensiveMeasuresDuringInputEvent();
                    if (notifyRenderer) {
                        Trace.traceBegin(Trace.TRACE_TAG_VIEW,
                                "CPU_LOAD_UP: " + "hasExpensiveMeasuresDuringInputEvent");
                        getViewRootImpl().notifyRendererOfExpensiveFrame();
                        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
                    }
                }
                onMeasure(widthMeasureSpec, heightMeasureSpec);
                if (isTraversalTracingEnabled()) {
                    Trace.endSection();
                }
                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
            } else {
                long value = mMeasureCache.valueAt(cacheIndex);
                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
            }
            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
                throw new IllegalStateException("View with id " + getId() + ": "
                        + getClass().getName() + "#onMeasure() did not set the"
                        + " measured dimension by calling"
                        + " setMeasuredDimension()");
            }
            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
        }
        mOldWidthMeasureSpec = widthMeasureSpec;
        mOldHeightMeasureSpec = heightMeasureSpec;
        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
                (long) mMeasuredHeight & 0xffffffffL);    }
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
    }
    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
        boolean optical = isLayoutModeOptical(this);
        if (optical != isLayoutModeOptical(mParent)) {
            Insets insets = getOpticalInsets();
            int opticalWidth  = insets.left + insets.right;
            int opticalHeight = insets.top  + insets.bottom;
            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
            measuredHeight += optical ? opticalHeight : -opticalHeight;
        }
        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
    }
    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
        mMeasuredWidth = measuredWidth;
        mMeasuredHeight = measuredHeight;
        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
    }
    public static int combineMeasuredStates(int curState, int newState) {
        return curState | newState;
    }
    public static int resolveSize(int size, int measureSpec) {
        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
    }
    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
        final int specMode = MeasureSpec.getMode(measureSpec);
        final int specSize = MeasureSpec.getSize(measureSpec);
        final int result;
        switch (specMode) {
            case MeasureSpec.AT_MOST:
                if (specSize < size) {
                    result = specSize | MEASURED_STATE_TOO_SMALL;
                } else {
                    result = size;
                }
                break;
            case MeasureSpec.EXACTLY:
                result = specSize;
                break;
            case MeasureSpec.UNSPECIFIED:
            default:
                result = size;
        }
        return result | (childMeasuredState & MEASURED_STATE_MASK);
    }
    public static int getDefaultSize(int size, int measureSpec) {
        int result = size;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        switch (specMode) {
        case MeasureSpec.UNSPECIFIED:
            result = size;
            break;
        case MeasureSpec.AT_MOST:
        case MeasureSpec.EXACTLY:
            result = specSize;
            break;
        }
        return result;
    }
    protected int getSuggestedMinimumHeight() {
        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
    }
    protected int getSuggestedMinimumWidth() {
        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
    }
    @InspectableProperty(name = "minHeight")
    public int getMinimumHeight() {
        return mMinHeight;
    }
    @RemotableViewMethod
    public void setMinimumHeight(int minHeight) {
        mMinHeight = minHeight;
        requestLayout();
    }
    @InspectableProperty(name = "minWidth")
    public int getMinimumWidth() {
        return mMinWidth;
    }
    @RemotableViewMethod
    public void setMinimumWidth(int minWidth) {
        mMinWidth = minWidth;
        requestLayout();
    }
    public Animation getAnimation() {
        return mCurrentAnimation;
    }
    public void startAnimation(Animation animation) {
        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
        setAnimation(animation);
        invalidateParentCaches();
        invalidate(true);
    }
    public void clearAnimation() {
        if (mCurrentAnimation != null) {
            mCurrentAnimation.detach();
        }
        mCurrentAnimation = null;
        invalidateParentIfNeeded();
    }
    public void setAnimation(Animation animation) {
        mCurrentAnimation = animation;
        if (animation != null) {
            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
            }
            animation.reset();
        }
    }
    @CallSuper
    protected void onAnimationStart() {
        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
    }
    @CallSuper
    protected void onAnimationEnd() {
        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
    }
    protected boolean onSetAlpha(int alpha) {
        return false;
    }
    public boolean gatherTransparentRegion(@Nullable Region region) {
        final AttachInfo attachInfo = mAttachInfo;
        if (region != null && attachInfo != null) {
            final int pflags = mPrivateFlags;
            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
                final int[] location = attachInfo.mTransparentLocation;
                getLocationInWindow(location);
                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
                        location[0] + mRight - mLeft + shadowOffset,
            } else {
                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
                    applyDrawableToTransparentRegion(mBackground, region);
                }
                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
                }
                if (mDefaultFocusHighlight != null
                        && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
                    applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
                }
            }
        }
        return true;
    }
    public void playSoundEffect(@SoundEffectConstants.SoundEffect int soundConstant) {
        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
            return;
        }
        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
    }
    public boolean performHapticFeedback(int feedbackConstant) {
        return performHapticFeedback(feedbackConstant, 0);
    }
    public boolean performHapticFeedback(int feedbackConstant, int flags) {
        if (feedbackConstant == HapticFeedbackConstants.NO_HAPTICS
                || mAttachInfo == null) {
            return false;
        }
        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
                && !isHapticFeedbackEnabled()) {
            return false;
        }
        final boolean always = (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0;
        boolean fromIme = false;
        if (mAttachInfo.mViewRootImpl != null) {
            fromIme = mAttachInfo.mViewRootImpl.mWindowAttributes.type == TYPE_INPUT_METHOD;
        }
        if (Flags.useVibratorHapticFeedback()) {
            if (!mAttachInfo.canPerformHapticFeedback()) {
                return false;
            }
            getSystemVibrator().performHapticFeedback(
                    feedbackConstant, always, "View#performHapticFeedback", fromIme);
            return true;
        }
        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, always, fromIme);
    }
    private Vibrator getSystemVibrator() {
        if (mVibrator != null) {
            return mVibrator;
        }
        return mVibrator = mContext.getSystemService(Vibrator.class);
    }
    @Deprecated
    public void setSystemUiVisibility(int visibility) {
        if (visibility != mSystemUiVisibility) {
            mSystemUiVisibility = visibility;
            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
                mParent.recomputeViewAttributes(this);
            }
        }
    }
    @Deprecated
    public int getSystemUiVisibility() {
        return mSystemUiVisibility;
    }
    @Deprecated
    public int getWindowSystemUiVisibility() {
        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
    }
    @Deprecated
    public void onWindowSystemUiVisibilityChanged(int visible) {
    }
    @Deprecated
    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
        onWindowSystemUiVisibilityChanged(visible);
    }
    @Deprecated
    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
            mParent.recomputeViewAttributes(this);
        }
    }
    @Deprecated
    public void dispatchSystemUiVisibilityChanged(int visibility) {
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
        }
    }
    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
        if (val != mSystemUiVisibility) {
            setSystemUiVisibility(val);
            return true;
        }
        return false;
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public void setDisabledSystemUiVisibility(int flags) {
        if (mAttachInfo != null) {
            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
                mAttachInfo.mDisabledSystemUiVisibility = flags;
                if (mParent != null) {
                    mParent.recomputeViewAttributes(this);
                }
            }
        }
    }
    public void onSystemBarAppearanceChanged(@WindowInsetsController.Appearance int appearance) {
    }
    public static class DragShadowBuilder {
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        private final WeakReference<View> mView;
        public DragShadowBuilder(View view) {
            mView = new WeakReference<View>(view);
        }
        public DragShadowBuilder() {
            mView = new WeakReference<View>(null);
        }
        @SuppressWarnings({"JavadocReference"})
        final public View getView() {
            return mView.get();
        }
        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
            final View view = mView.get();
            if (view != null) {
                outShadowSize.set(view.getWidth(), view.getHeight());
                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
            } else {
                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
            }
        }
        public void onDrawShadow(@NonNull Canvas canvas) {
            final View view = mView.get();
            if (view != null) {
                view.draw(canvas);
            } else {
                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
            }
        }
    }
    @Deprecated
    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
                                   Object myLocalState, int flags) {
        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
    }
    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
            Object myLocalState, int flags) {
        if (ViewDebug.DEBUG_DRAG) {
            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
        }
        if (mAttachInfo == null) {
            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
            return false;
        }
        if (!mAttachInfo.mViewRootImpl.mSurface.isValid()) {
            Log.w(VIEW_LOG_TAG, "startDragAndDrop called with an invalid surface.");
            return false;
        }
        if ((flags & DRAG_FLAG_GLOBAL) != 0 && ((flags & DRAG_FLAG_GLOBAL_SAME_APPLICATION) != 0)) {
            Log.w(VIEW_LOG_TAG, "startDragAndDrop called with both DRAG_FLAG_GLOBAL "
                    + "and DRAG_FLAG_GLOBAL_SAME_APPLICATION, the drag will default to "
                    + "DRAG_FLAG_GLOBAL_SAME_APPLICATION");
            flags &= ~DRAG_FLAG_GLOBAL;
        }
        if (data != null) {
            if (com.android.window.flags.Flags.delegateUnhandledDrags()) {
                data.prepareToLeaveProcess(
                        (flags & (DRAG_FLAG_GLOBAL_SAME_APPLICATION | DRAG_FLAG_GLOBAL)) != 0);
                if ((flags & DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG) != 0) {
                    if (!hasActivityPendingIntents(data)) {
                        flags &= ~DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG;
                        Log.w(VIEW_LOG_TAG, "startDragAndDrop called with "
                                + "DRAG_FLAG_START_INTENT_ON_UNHANDLED_DRAG but the clip data "
                                + "contains non-activity PendingIntents");
                    }
                }
            } else {
                data.prepareToLeaveProcess((flags & DRAG_FLAG_GLOBAL) != 0);
            }
        }
        Rect bounds = new Rect();
        getBoundsOnScreen(bounds, true);
        Point lastTouchPoint = new Point();
        mAttachInfo.mViewRootImpl.getLastTouchPoint(lastTouchPoint);
        final ViewRootImpl root = mAttachInfo.mViewRootImpl;
        final boolean a11yEnabled = AccessibilityManager.getInstance(mContext).isEnabled();
        if (a11yEnabled && (flags & View.DRAG_FLAG_ACCESSIBILITY_ACTION) != 0) {
            try {
                IBinder token = mAttachInfo.mSession.performDrag(
                        mAttachInfo.mWindow, flags, null,
                        mAttachInfo.mViewRootImpl.getLastTouchSource(),
                        mAttachInfo.mViewRootImpl.getLastTouchDeviceId(),
                        mAttachInfo.mViewRootImpl.getLastTouchPointerId(),
                        0f, 0f, 0f, 0f, data);
                if (ViewDebug.DEBUG_DRAG) {
                    Log.d(VIEW_LOG_TAG, "startDragAndDrop via a11y action returned " + token);
                }
                if (token != null) {
                    root.setLocalDragState(myLocalState);
                    mAttachInfo.mDragToken = token;
                    mAttachInfo.mDragData = data;
                    mAttachInfo.mViewRootImpl.setDragStartedViewForAccessibility(this);
                    setAccessibilityDragStarted(true);
                }
                return token != null;
            } catch (Exception e) {
                Log.e(VIEW_LOG_TAG, "Unable to initiate a11y drag", e);
                return false;
            }
        }
        Point shadowSize = new Point();
        Point shadowTouchPoint = new Point();
        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
        if ((shadowSize.x < 0) || (shadowSize.y < 0)
                || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
            throw new IllegalStateException("Drag shadow dimensions must not be negative");
        }
        final float overrideInvScale = CompatibilityInfo.getOverrideInvertedScale();
        if (overrideInvScale != 1f) {
            shadowTouchPoint.x = (int) (shadowTouchPoint.x / overrideInvScale);
            shadowTouchPoint.y = (int) (shadowTouchPoint.y / overrideInvScale);
        }
        if (shadowSize.x == 0  || shadowSize.y == 0) {
            if (!sAcceptZeroSizeDragShadow) {
                throw new IllegalStateException("Drag shadow dimensions must be positive");
            }
            shadowSize.x = 1;
            shadowSize.y = 1;
        }
        if (ViewDebug.DEBUG_DRAG) {
            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
        }
        final SurfaceSession session = new SurfaceSession();
        final SurfaceControl surfaceControl = new SurfaceControl.Builder(session)
                .setName("drag surface")
                .setParent(root.getSurfaceControl())
                .setBufferSize(shadowSize.x, shadowSize.y)
                .setFormat(PixelFormat.TRANSLUCENT)
                .setCallsite("View.startDragAndDrop")
                .build();
        if (overrideInvScale != 1f) {
            final SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
            transaction.setMatrix(surfaceControl, 1 / overrideInvScale, 0, 0, 1 / overrideInvScale)
                    .apply();
        }
        final Surface surface = new Surface();
        surface.copyFrom(surfaceControl);
        IBinder token = null;
        try {
            Trace.traceBegin(TRACE_TAG_VIEW, "startDragAndDrop#drawDragShadow");
            final Canvas canvas = isHardwareAccelerated()
                    ? surface.lockHardwareCanvas()
                    : surface.lockCanvas(null);
            try {
                canvas.drawColor(0, PorterDuff.Mode.CLEAR);
                shadowBuilder.onDrawShadow(canvas);
            } finally {
                surface.unlockCanvasAndPost(canvas);
                Trace.traceEnd(TRACE_TAG_VIEW);
            }
            Trace.traceBegin(TRACE_TAG_VIEW, "startDragAndDrop#performDrag");
            try {
                token = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, flags, surfaceControl,
                        root.getLastTouchSource(), root.getLastTouchDeviceId(),
                        root.getLastTouchPointerId(), lastTouchPoint.x, lastTouchPoint.y,
                        shadowTouchPoint.x, shadowTouchPoint.y, data);
                if (ViewDebug.DEBUG_DRAG) {
                    Log.d(VIEW_LOG_TAG, "performDrag returned " + token);
                }
                if (token != null) {
                    if (mAttachInfo.mDragSurface != null) {
                        mAttachInfo.mDragSurface.release();
                    }
                    if (mAttachInfo.mDragData != null) {
                        View.cleanUpPendingIntents(mAttachInfo.mDragData);
                    }
                    mAttachInfo.mDragSurface = surface;
                    mAttachInfo.mDragToken = token;
                    mAttachInfo.mDragData = data;
                    root.setLocalDragState(myLocalState);
                    if (a11yEnabled) {
                        mAttachInfo.mViewRootImpl.setDragStartedViewForAccessibility(this);
                    }
                }
                return token != null;
            } finally {
                Trace.traceEnd(TRACE_TAG_VIEW);
            }
        } catch (Exception e) {
            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
            return false;
        } finally {
            if (token == null) {
                surface.destroy();
            }
            session.kill();
            surfaceControl.release();
        }
    }
    static boolean hasActivityPendingIntents(ClipData data) {
        final int size = data.getItemCount();
        for (int i = 0; i < size; i++) {
            final ClipData.Item item = data.getItemAt(i);
            if (item.getIntentSender() != null) {
                final PendingIntent pi = new PendingIntent(item.getIntentSender().getTarget());
                if (pi.isActivity()) {
                    return true;
                }
            }
        }
        return false;
    }
    static void cleanUpPendingIntents(ClipData data) {
        final int size = data.getItemCount();
        for (int i = 0; i < size; i++) {
            final ClipData.Item item = data.getItemAt(i);
            if (item.getIntentSender() != null) {
                final PendingIntent pi = new PendingIntent(item.getIntentSender().getTarget());
                pi.cancel();
            }
        }
    }
    void setAccessibilityDragStarted(boolean started) {
        int pflags4 = mPrivateFlags4;
        if (started) {
            pflags4 |= PFLAG4_DRAG_A11Y_STARTED;
        } else {
            pflags4 &= ~PFLAG4_DRAG_A11Y_STARTED;
        }
        if (pflags4 != mPrivateFlags4) {
            mPrivateFlags4 = pflags4;
            sendWindowContentChangedAccessibilityEvent(CONTENT_CHANGE_TYPE_UNDEFINED);
        }
    }
    private boolean startedSystemDragForAccessibility() {
        return (mPrivateFlags4 & PFLAG4_DRAG_A11Y_STARTED) != 0;
    }
    public final void cancelDragAndDrop() {
        if (ViewDebug.DEBUG_DRAG) {
            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
        }
        if (mAttachInfo == null) {
            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
            return;
        }
        if (mAttachInfo.mDragToken != null) {
            try {
                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken, false);
            } catch (Exception e) {
                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
            }
            mAttachInfo.mDragToken = null;
        } else {
            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
        }
    }
    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
        if (ViewDebug.DEBUG_DRAG) {
            Log.d(VIEW_LOG_TAG, "updateDragShadow");
        }
        if (mAttachInfo == null) {
            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
            return;
        }
        if (mAttachInfo.mDragToken != null) {
            try {
                Canvas canvas = isHardwareAccelerated()
                        ? mAttachInfo.mDragSurface.lockHardwareCanvas()
                        : mAttachInfo.mDragSurface.lockCanvas(null);
                try {
                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
                    shadowBuilder.onDrawShadow(canvas);
                } finally {
                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
                }
            } catch (Exception e) {
                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
            }
        } else {
            Log.e(VIEW_LOG_TAG, "No active drag");
        }
    }
    public final boolean startMovingTask(float startX, float startY) {
        if (ViewDebug.DEBUG_POSITIONING) {
            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
        }
        try {
            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
        } catch (RemoteException e) {
            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
        }
        return false;
    }
    public void finishMovingTask() {
        if (ViewDebug.DEBUG_POSITIONING) {
            Log.d(VIEW_LOG_TAG, "finishMovingTask");
        }
        try {
            mAttachInfo.mSession.finishMovingTask(mAttachInfo.mWindow);
        } catch (RemoteException e) {
            Log.e(VIEW_LOG_TAG, "Unable to finish moving", e);
        }
    }
    public boolean onDragEvent(DragEvent event) {
        if (mListenerInfo == null || mListenerInfo.mOnReceiveContentListener == null) {
            return false;
        }
        if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
            return true;
        }
        if (event.getAction() == DragEvent.ACTION_DROP) {
            final DragAndDropPermissions permissions = DragAndDropPermissions.obtain(event);
            if (permissions != null) {
                permissions.takeTransient();
            }
            final ContentInfo payload =
                    new ContentInfo.Builder(event.getClipData(), SOURCE_DRAG_AND_DROP)
                            .setDragAndDropPermissions(permissions)
                            .build();
            ContentInfo remainingPayload = performReceiveContent(payload);
            return remainingPayload != payload;
        }
        return false;
    }
    boolean dispatchDragEnterExitInPreN(DragEvent event) {
        return callDragEventHandler(event);
    }
    public boolean dispatchDragEvent(DragEvent event) {
        event.mEventHandlerWasCalled = true;
        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
            event.mAction == DragEvent.ACTION_DROP) {
            getViewRootImpl().setDragFocus(this, event);
        }
        return callDragEventHandler(event);
    }
    final boolean callDragEventHandler(DragEvent event) {
        final boolean result;
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
                && li.mOnDragListener.onDrag(this, event)) {
            result = true;
        } else {
            result = onDragEvent(event);
        }
        switch (event.mAction) {
            case DragEvent.ACTION_DRAG_STARTED: {
                if (result && li != null && li.mOnDragListener != null) {
                    sendWindowContentChangedAccessibilityEvent(
                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
                }
            } break;
            case DragEvent.ACTION_DRAG_ENTERED: {
                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
                refreshDrawableState();
            } break;
            case DragEvent.ACTION_DRAG_EXITED: {
                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
                refreshDrawableState();
            } break;
            case DragEvent.ACTION_DROP: {
                if (result && li != null && (li.mOnDragListener != null
                        || li.mOnReceiveContentListener != null)) {
                    sendWindowContentChangedAccessibilityEvent(
                            AccessibilityEvent.CONTENT_CHANGE_TYPE_DRAG_DROPPED);
                }
            } break;
            case DragEvent.ACTION_DRAG_ENDED: {
                sendWindowContentChangedAccessibilityEvent(
                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
                mPrivateFlags2 &= ~View.DRAG_MASK;
                refreshDrawableState();
            } break;
        }
        return result;
    }
    boolean canAcceptDrag() {
        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
    }
    void sendWindowContentChangedAccessibilityEvent(int changeType) {
        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
            AccessibilityEvent event = AccessibilityEvent.obtain();
            event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
            event.setContentChangeTypes(changeType);
            sendAccessibilityEventUnchecked(event);
        }
    }
    @UnsupportedAppUsage
    public void onCloseSystemDialogs(String reason) {
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
        if (DBG) {
            Log.i("View", "Getting transparent region for: " + this);
        }
        final Region r = dr.getTransparentRegion();
        final Rect db = dr.getBounds();
        final AttachInfo attachInfo = mAttachInfo;
        if (r != null && attachInfo != null) {
            final int w = getRight()-getLeft();
            final int h = getBottom()-getTop();
            if (db.left > 0) {
                r.op(0, 0, db.left, h, Region.Op.UNION);
            }
            if (db.right < w) {
                r.op(db.right, 0, w, h, Region.Op.UNION);
            }
            if (db.top > 0) {
                r.op(0, 0, w, db.top, Region.Op.UNION);
            }
            if (db.bottom < h) {
                r.op(0, db.bottom, w, h, Region.Op.UNION);
            }
            final int[] location = attachInfo.mTransparentLocation;
            getLocationInWindow(location);
            r.translate(location[0], location[1]);
            region.op(r, Region.Op.INTERSECT);
        } else {
            region.op(db, Region.Op.DIFFERENCE);
        }
    }
    private void checkForLongClick(long delay, float x, float y, int classification) {
        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
            mHasPerformedLongPress = false;
            if (mPendingCheckForLongPress == null) {
                mPendingCheckForLongPress = new CheckForLongPress();
            }
            mPendingCheckForLongPress.setAnchor(x, y);
            mPendingCheckForLongPress.rememberWindowAttachCount();
            mPendingCheckForLongPress.rememberPressedState();
            mPendingCheckForLongPress.setClassification(classification);
            postDelayed(mPendingCheckForLongPress, delay);
        }
    }
    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
        LayoutInflater factory = LayoutInflater.from(context);
        return factory.inflate(resource, root);
    }
    @SuppressWarnings({"UnusedParameters"})
    protected boolean overScrollBy(int deltaX, int deltaY,
            int scrollX, int scrollY,
            int scrollRangeX, int scrollRangeY,
            int maxOverScrollX, int maxOverScrollY,
            boolean isTouchEvent) {
        final int overScrollMode = mOverScrollMode;
        final boolean canScrollHorizontal =
                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
        final boolean canScrollVertical =
                computeVerticalScrollRange() > computeVerticalScrollExtent();
        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
        int newScrollX = scrollX + deltaX;
        if (!overScrollHorizontal) {
            maxOverScrollX = 0;
        }
        int newScrollY = scrollY + deltaY;
        if (!overScrollVertical) {
            maxOverScrollY = 0;
        }
        final int left = -maxOverScrollX;
        final int right = maxOverScrollX + scrollRangeX;
        final int top = -maxOverScrollY;
        final int bottom = maxOverScrollY + scrollRangeY;
        boolean clampedX = false;
        if (newScrollX > right) {
            newScrollX = right;
            clampedX = true;
        } else if (newScrollX < left) {
            newScrollX = left;
            clampedX = true;
        }
        boolean clampedY = false;
        if (newScrollY > bottom) {
            newScrollY = bottom;
            clampedY = true;
        } else if (newScrollY < top) {
            newScrollY = top;
            clampedY = true;
        }
        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
        return clampedX || clampedY;
    }
    protected void onOverScrolled(int scrollX, int scrollY,
            boolean clampedX, boolean clampedY) {
    }
    @InspectableProperty(enumMapping = {
            @EnumEntry(value = OVER_SCROLL_ALWAYS, name = "always"),
            @EnumEntry(value = OVER_SCROLL_IF_CONTENT_SCROLLS, name = "ifContentScrolls"),
            @EnumEntry(value = OVER_SCROLL_NEVER, name = "never")
    })
    public int getOverScrollMode() {
        return mOverScrollMode;
    }
    public void setOverScrollMode(int overScrollMode) {
        if (overScrollMode != OVER_SCROLL_ALWAYS &&
                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
                overScrollMode != OVER_SCROLL_NEVER) {
            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
        }
        mOverScrollMode = overScrollMode;
    }
    public void setNestedScrollingEnabled(boolean enabled) {
        if (enabled) {
            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
        } else {
            stopNestedScroll();
            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
        }
    }
    @InspectableProperty
    public boolean isNestedScrollingEnabled() {
        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
                PFLAG3_NESTED_SCROLLING_ENABLED;
    }
    public boolean startNestedScroll(int axes) {
        if (hasNestedScrollingParent()) {
            return true;
        }
        if (isNestedScrollingEnabled()) {
            ViewParent p = getParent();
            View child = this;
            while (p != null) {
                try {
                    if (p.onStartNestedScroll(child, this, axes)) {
                        mNestedScrollingParent = p;
                        p.onNestedScrollAccepted(child, this, axes);
                        return true;
                    }
                } catch (AbstractMethodError e) {
                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
                            "method onStartNestedScroll", e);
                }
                if (p instanceof View) {
                    child = (View) p;
                }
                p = p.getParent();
            }
        }
        return false;
    }
    public void stopNestedScroll() {
        if (mNestedScrollingParent != null) {
            mNestedScrollingParent.onStopNestedScroll(this);
            mNestedScrollingParent = null;
        }
    }
    public boolean hasNestedScrollingParent() {
        return mNestedScrollingParent != null;
    }
    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
                int startX = 0;
                int startY = 0;
                if (offsetInWindow != null) {
                    getLocationInWindow(offsetInWindow);
                    startX = offsetInWindow[0];
                    startY = offsetInWindow[1];
                }
                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
                        dxUnconsumed, dyUnconsumed);
                if (offsetInWindow != null) {
                    getLocationInWindow(offsetInWindow);
                    offsetInWindow[0] -= startX;
                    offsetInWindow[1] -= startY;
                }
                return true;
            } else if (offsetInWindow != null) {
                offsetInWindow[0] = 0;
                offsetInWindow[1] = 0;
            }
        }
        return false;
    }
    public boolean dispatchNestedPreScroll(int dx, int dy,
            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
            if (dx != 0 || dy != 0) {
                int startX = 0;
                int startY = 0;
                if (offsetInWindow != null) {
                    getLocationInWindow(offsetInWindow);
                    startX = offsetInWindow[0];
                    startY = offsetInWindow[1];
                }
                if (consumed == null) {
                    if (mTempNestedScrollConsumed == null) {
                        mTempNestedScrollConsumed = new int[2];
                    }
                    consumed = mTempNestedScrollConsumed;
                }
                consumed[0] = 0;
                consumed[1] = 0;
                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
                if (offsetInWindow != null) {
                    getLocationInWindow(offsetInWindow);
                    offsetInWindow[0] -= startX;
                    offsetInWindow[1] -= startY;
                }
                return consumed[0] != 0 || consumed[1] != 0;
            } else if (offsetInWindow != null) {
                offsetInWindow[0] = 0;
                offsetInWindow[1] = 0;
            }
        }
        return false;
    }
    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
        }
        return false;
    }
    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
        }
        return false;
    }
    @UnsupportedAppUsage
    protected float getVerticalScrollFactor() {
        if (mVerticalScrollFactor == 0) {
            TypedValue outValue = new TypedValue();
            if (!mContext.getTheme().resolveAttribute(
                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
                throw new IllegalStateException(
                        "Expected theme to define listPreferredItemHeight.");
            }
            mVerticalScrollFactor = outValue.getDimension(
                    mContext.getResources().getDisplayMetrics());
        }
        return mVerticalScrollFactor;
    }
    @UnsupportedAppUsage
    protected float getHorizontalScrollFactor() {
        return getVerticalScrollFactor();
    }
    @ViewDebug.ExportedProperty(category = "text", mapping = {
            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
    })
    @InspectableProperty(hasAttributeId = false, enumMapping = {
            @EnumEntry(value = TEXT_DIRECTION_INHERIT, name = "inherit"),
            @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
            @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
            @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
            @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
            @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
            @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
            @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
    })
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public int getRawTextDirection() {
        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
    }
    public void setTextDirection(int textDirection) {
        if (getRawTextDirection() != textDirection) {
            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
            resetResolvedTextDirection();
            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
            resolveTextDirection();
            onRtlPropertiesChanged(getLayoutDirection());
            requestLayout();
            invalidate(true);
        }
    }
    @ViewDebug.ExportedProperty(category = "text", mapping = {
            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
    })
    @InspectableProperty(hasAttributeId = false, enumMapping = {
            @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
            @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
            @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
            @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
            @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
            @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
            @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
    })
    public int getTextDirection() {
        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
    }
    public boolean resolveTextDirection() {
        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
        if (hasRtlSupport()) {
            final int textDirection = getRawTextDirection();
            switch(textDirection) {
                case TEXT_DIRECTION_INHERIT:
                    if (!canResolveTextDirection()) {
                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
                        return false;
                    }
                    try {
                        if (!mParent.isTextDirectionResolved()) {
                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
                            return false;
                        }
                    } catch (AbstractMethodError e) {
                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                                " does not fully implement ViewParent", e);
                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
                        return true;
                    }
                    int parentResolvedDirection;
                    try {
                        parentResolvedDirection = mParent.getTextDirection();
                    } catch (AbstractMethodError e) {
                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                                " does not fully implement ViewParent", e);
                        parentResolvedDirection = TEXT_DIRECTION_LTR;
                    }
                    switch (parentResolvedDirection) {
                        case TEXT_DIRECTION_FIRST_STRONG:
                        case TEXT_DIRECTION_ANY_RTL:
                        case TEXT_DIRECTION_LTR:
                        case TEXT_DIRECTION_RTL:
                        case TEXT_DIRECTION_LOCALE:
                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
                            mPrivateFlags2 |=
                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
                            break;
                        default:
                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
                    }
                    break;
                case TEXT_DIRECTION_FIRST_STRONG:
                case TEXT_DIRECTION_ANY_RTL:
                case TEXT_DIRECTION_LTR:
                case TEXT_DIRECTION_RTL:
                case TEXT_DIRECTION_LOCALE:
                case TEXT_DIRECTION_FIRST_STRONG_LTR:
                case TEXT_DIRECTION_FIRST_STRONG_RTL:
                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
                    break;
                default:
                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
            }
        } else {
            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
        }
        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
        return true;
    }
    public boolean canResolveTextDirection() {
        switch (getRawTextDirection()) {
            case TEXT_DIRECTION_INHERIT:
                if (mParent != null) {
                    try {
                        return mParent.canResolveTextDirection();
                    } catch (AbstractMethodError e) {
                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                                " does not fully implement ViewParent", e);
                    }
                }
                return false;
            default:
                return true;
        }
    }
    @TestApi
    public void resetResolvedTextDirection() {
        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
    }
    public boolean isTextDirectionInherited() {
        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
    }
    public boolean isTextDirectionResolved() {
        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
    }
    @ViewDebug.ExportedProperty(category = "text", mapping = {
            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
    })
    @InspectableProperty(hasAttributeId = false, enumMapping = {
            @EnumEntry(value = TEXT_ALIGNMENT_INHERIT, name = "inherit"),
            @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
            @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
            @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
            @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
            @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
            @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
    })
    @TextAlignment
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public int getRawTextAlignment() {
        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
    }
    public void setTextAlignment(@TextAlignment int textAlignment) {
        if (textAlignment != getRawTextAlignment()) {
            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
            resetResolvedTextAlignment();
            mPrivateFlags2 |=
                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
            resolveTextAlignment();
            onRtlPropertiesChanged(getLayoutDirection());
            requestLayout();
            invalidate(true);
        }
    }
    @ViewDebug.ExportedProperty(category = "text", mapping = {
            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
    })
    @InspectableProperty(enumMapping = {
            @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
            @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
            @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
            @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
            @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
            @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
    })
    @TextAlignment
    public int getTextAlignment() {
        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
    }
    public boolean resolveTextAlignment() {
        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
        if (hasRtlSupport()) {
            final int textAlignment = getRawTextAlignment();
            switch (textAlignment) {
                case TEXT_ALIGNMENT_INHERIT:
                    if (!canResolveTextAlignment()) {
                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
                        return false;
                    }
                    try {
                        if (!mParent.isTextAlignmentResolved()) {
                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
                            return false;
                        }
                    } catch (AbstractMethodError e) {
                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                                " does not fully implement ViewParent", e);
                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
                        return true;
                    }
                    int parentResolvedTextAlignment;
                    try {
                        parentResolvedTextAlignment = mParent.getTextAlignment();
                    } catch (AbstractMethodError e) {
                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                                " does not fully implement ViewParent", e);
                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
                    }
                    switch (parentResolvedTextAlignment) {
                        case TEXT_ALIGNMENT_GRAVITY:
                        case TEXT_ALIGNMENT_TEXT_START:
                        case TEXT_ALIGNMENT_TEXT_END:
                        case TEXT_ALIGNMENT_CENTER:
                        case TEXT_ALIGNMENT_VIEW_START:
                        case TEXT_ALIGNMENT_VIEW_END:
                            mPrivateFlags2 |=
                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
                            break;
                        default:
                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
                    }
                    break;
                case TEXT_ALIGNMENT_GRAVITY:
                case TEXT_ALIGNMENT_TEXT_START:
                case TEXT_ALIGNMENT_TEXT_END:
                case TEXT_ALIGNMENT_CENTER:
                case TEXT_ALIGNMENT_VIEW_START:
                case TEXT_ALIGNMENT_VIEW_END:
                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
                    break;
                default:
                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
            }
        } else {
            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
        }
        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
        return true;
    }
    public boolean canResolveTextAlignment() {
        switch (getRawTextAlignment()) {
            case TEXT_DIRECTION_INHERIT:
                if (mParent != null) {
                    try {
                        return mParent.canResolveTextAlignment();
                    } catch (AbstractMethodError e) {
                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                                " does not fully implement ViewParent", e);
                    }
                }
                return false;
            default:
                return true;
        }
    }
    @TestApi
    public void resetResolvedTextAlignment() {
        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
    }
    public boolean isTextAlignmentInherited() {
        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
    }
    public boolean isTextAlignmentResolved() {
        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
    }
    public static int generateViewId() {
        for (;;) {
            final int result = sNextGeneratedId.get();
            int newValue = result + 1;
            if (newValue > 0x00FFFFFF) newValue = 1;            if (sNextGeneratedId.compareAndSet(result, newValue)) {
                return result;
            }
        }
    }
    private static boolean isViewIdGenerated(int id) {
        return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
    }
    public void captureTransitioningViews(List<View> transitioningViews) {
        if (getVisibility() == View.VISIBLE) {
            transitioningViews.add(this);
        }
    }
    public void findNamedViews(Map<String, View> namedElements) {
        if (getVisibility() == VISIBLE || mGhostView != null) {
            String transitionName = getTransitionName();
            if (transitionName != null) {
                namedElements.put(transitionName, this);
            }
        }
    }
    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
        final float x = event.getX(pointerIndex);
        final float y = event.getY(pointerIndex);
        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
            return null;
        }
        if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
            return mMousePointerIcon;
        }
        return null;
    }
    public void setPointerIcon(PointerIcon pointerIcon) {
        mMousePointerIcon = pointerIcon;
        final ViewRootImpl viewRootImpl = getViewRootImpl();
        if (viewRootImpl == null) {
            return;
        }
        viewRootImpl.refreshPointerIcon();
    }
    @InspectableProperty
    public PointerIcon getPointerIcon() {
        return mMousePointerIcon;
    }
    public boolean hasPointerCapture() {
        final ViewRootImpl viewRootImpl = getViewRootImpl();
        if (viewRootImpl == null) {
            return false;
        }
        return viewRootImpl.hasPointerCapture();
    }
    public void requestPointerCapture() {
        final ViewRootImpl viewRootImpl = getViewRootImpl();
        if (viewRootImpl != null) {
            viewRootImpl.requestPointerCapture(true);
        }
    }
    public void releasePointerCapture() {
        final ViewRootImpl viewRootImpl = getViewRootImpl();
        if (viewRootImpl != null) {
            viewRootImpl.requestPointerCapture(false);
        }
    }
    @CallSuper
    public void onPointerCaptureChange(boolean hasCapture) {
    }
    public void dispatchPointerCaptureChanged(boolean hasCapture) {
        onPointerCaptureChange(hasCapture);
    }
    public boolean onCapturedPointerEvent(MotionEvent event) {
        return false;
    }
    public interface OnCapturedPointerListener {
        boolean onCapturedPointer(View view, MotionEvent event);
    }
    public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
        getListenerInfo().mOnCapturedPointerListener = l;
    }
    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
        @Override
        public void setValue(View object, float value) {
            object.setAlpha(value);
        }
        @Override
        public Float get(View object) {
            return object.getAlpha();
        }
    };
    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
        @Override
        public void setValue(View object, float value) {
            object.setTranslationX(value);
        }
                @Override
        public Float get(View object) {
            return object.getTranslationX();
        }
    };
    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
        @Override
        public void setValue(View object, float value) {
            object.setTranslationY(value);
        }
        @Override
        public Float get(View object) {
            return object.getTranslationY();
        }
    };
    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
        @Override
        public void setValue(View object, float value) {
            object.setTranslationZ(value);
        }
        @Override
        public Float get(View object) {
            return object.getTranslationZ();
        }
    };
    public static final Property<View, Float> X = new FloatProperty<View>("x") {
        @Override
        public void setValue(View object, float value) {
            object.setX(value);
        }
        @Override
        public Float get(View object) {
            return object.getX();
        }
    };
    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
        @Override
        public void setValue(View object, float value) {
            object.setY(value);
        }
        @Override
        public Float get(View object) {
            return object.getY();
        }
    };
    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
        @Override
        public void setValue(View object, float value) {
            object.setZ(value);
        }
        @Override
        public Float get(View object) {
            return object.getZ();
        }
    };
    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
        @Override
        public void setValue(View object, float value) {
            object.setRotation(value);
        }
        @Override
        public Float get(View object) {
            return object.getRotation();
        }
    };
    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
        @Override
        public void setValue(View object, float value) {
            object.setRotationX(value);
        }
        @Override
        public Float get(View object) {
            return object.getRotationX();
        }
    };
    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
        @Override
        public void setValue(View object, float value) {
            object.setRotationY(value);
        }
        @Override
        public Float get(View object) {
            return object.getRotationY();
        }
    };
    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
        @Override
        public void setValue(View object, float value) {
            object.setScaleX(value);
        }
        @Override
        public Float get(View object) {
            return object.getScaleX();
        }
    };
    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
        @Override
        public void setValue(View object, float value) {
            object.setScaleY(value);
        }
        @Override
        public Float get(View object) {
            return object.getScaleY();
        }
    };
    public static class MeasureSpec {
        private static final int MODE_SHIFT = 30;
        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
        @Retention(RetentionPolicy.SOURCE)
        public @interface MeasureSpecMode {}
        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
        public static final int EXACTLY     = 1 << MODE_SHIFT;
        public static final int AT_MOST     = 2 << MODE_SHIFT;
        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
                                          @MeasureSpecMode int mode) {
            return (size & ~MODE_MASK) | (mode & MODE_MASK);
        }
        @UnsupportedAppUsage
        public static int makeSafeMeasureSpec(int size, int mode) {
            return makeMeasureSpec(size, mode);
        }
        @MeasureSpecMode
        public static int getMode(int measureSpec) {
            return (measureSpec & MODE_MASK);
        }
        public static int getSize(int measureSpec) {
            return (measureSpec & ~MODE_MASK);
        }
        static int adjust(int measureSpec, int delta) {
            final int mode = getMode(measureSpec);
            int size = getSize(measureSpec);
            if (mode == UNSPECIFIED) {
                return makeMeasureSpec(size, UNSPECIFIED);
            }
            size += delta;
            if (size < 0) {
                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
                        ") spec: " + toString(measureSpec) + " delta: " + delta);
                size = 0;
            }
            return makeMeasureSpec(size, mode);
        }
        public static String toString(int measureSpec) {
            int mode = getMode(measureSpec);
            int size = getSize(measureSpec);
            StringBuilder sb = new StringBuilder("MeasureSpec: ");
            if (mode == UNSPECIFIED)
                sb.append("UNSPECIFIED ");
            else if (mode == EXACTLY)
                sb.append("EXACTLY ");
            else if (mode == AT_MOST)
                sb.append("AT_MOST ");
            else
                sb.append(mode).append(" ");
            sb.append(size);
            return sb.toString();
        }
    }
    private final class CheckForLongPress implements Runnable {
        private int mOriginalWindowAttachCount;
        private float mX;
        private float mY;
        private boolean mOriginalPressedState;
        private int mClassification;
        @UnsupportedAppUsage
        private CheckForLongPress() {
        }
        @Override
        public void run() {
            if ((mOriginalPressedState == isPressed()) && (mParent != null)
                    && mOriginalWindowAttachCount == mWindowAttachCount) {
                recordGestureClassification(mClassification);
                if (performLongClick(mX, mY)) {
                    mHasPerformedLongPress = true;
                }
            }
        }
        public void setAnchor(float x, float y) {
            mX = x;
            mY = y;
        }
        public void rememberWindowAttachCount() {
            mOriginalWindowAttachCount = mWindowAttachCount;
        }
        public void rememberPressedState() {
            mOriginalPressedState = isPressed();
        }
        public void setClassification(int classification) {
            mClassification = classification;
        }
    }
    private final class CheckForTap implements Runnable {
        public float x;
        public float y;
        @Override
        public void run() {
            mPrivateFlags &= ~PFLAG_PREPRESSED;
            setPressed(true, x, y);
            final long delay =
                    ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout();
            checkForLongClick(delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
        }
    }
    private final class PerformClick implements Runnable {
        @Override
        public void run() {
            recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
            performClickInternal();
        }
    }
    private void recordGestureClassification(int classification) {
        if (classification == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
            return;
        }
        FrameworkStatsLog.write(FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED, getClass().getName(),
                classification);
    }
    public ViewPropertyAnimator animate() {
        if (mAnimator == null) {
            mAnimator = new ViewPropertyAnimator(this);
        }
        return mAnimator;
    }
    public final void setTransitionName(String transitionName) {
        mTransitionName = transitionName;
    }
    @ViewDebug.ExportedProperty
    @InspectableProperty
    public String getTransitionName() {
        return mTransitionName;
    }
    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
    }
    public interface OnKeyListener {
        boolean onKey(View v, int keyCode, KeyEvent event);
    }
    public interface OnUnhandledKeyEventListener {
        boolean onUnhandledKeyEvent(View v, KeyEvent event);
    }
    public interface OnTouchListener {
        boolean onTouch(View v, MotionEvent event);
    }
    public interface OnHoverListener {
        boolean onHover(View v, MotionEvent event);
    }
    public interface OnGenericMotionListener {
        boolean onGenericMotion(View v, MotionEvent event);
    }
    public interface OnLongClickListener {
        boolean onLongClick(View v);
        default boolean onLongClickUseDefaultHapticFeedback(@NonNull View v) {
            return true;
        }
    }
    public interface OnDragListener {
        boolean onDrag(View v, DragEvent event);
    }
    public interface OnFocusChangeListener {
        void onFocusChange(View v, boolean hasFocus);
    }
    public interface OnClickListener {
        void onClick(View v);
    }
    public interface OnContextClickListener {
        boolean onContextClick(View v);
    }
    public interface OnCreateContextMenuListener {
        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
    }
    @Deprecated
    public interface OnSystemUiVisibilityChangeListener {
        public void onSystemUiVisibilityChange(int visibility);
    }
    public interface OnAttachStateChangeListener {
        public void onViewAttachedToWindow(@NonNull View v);
        public void onViewDetachedFromWindow(@NonNull View v);
    }
    public interface OnApplyWindowInsetsListener {
        public @NonNull WindowInsets onApplyWindowInsets(@NonNull View v,
                @NonNull WindowInsets insets);
    }
    private final class UnsetPressedState implements Runnable {
        @Override
        public void run() {
            setPressed(false);
        }
    }
    private static class VisibilityChangeForAutofillHandler extends Handler {
        private final AutofillManager mAfm;
        private final View mView;
        private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
                @NonNull View view) {
            mAfm = afm;
            mView = view;
        }
        @Override
        public void handleMessage(Message msg) {
            mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
        }
    }
    public static class BaseSavedState extends AbsSavedState {
        static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
        static final int IS_AUTOFILLED = 0b10;
        static final int AUTOFILL_ID = 0b100;
        int mSavedData;
        String mStartActivityRequestWhoSaved;
        boolean mIsAutofilled;
        boolean mHideHighlight;
        int mAutofillViewId;
        public BaseSavedState(Parcel source) {
            this(source, null);
        }
        public BaseSavedState(Parcel source, ClassLoader loader) {
            super(source, loader);
            mSavedData = source.readInt();
            mStartActivityRequestWhoSaved = source.readString();
            mIsAutofilled = source.readBoolean();
            mHideHighlight = source.readBoolean();
            mAutofillViewId = source.readInt();
        }
        public BaseSavedState(Parcelable superState) {
            super(superState);
        }
        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeInt(mSavedData);
            out.writeString(mStartActivityRequestWhoSaved);
            out.writeBoolean(mIsAutofilled);
            out.writeBoolean(mHideHighlight);
            out.writeInt(mAutofillViewId);
        }
        public static final @android.annotation.NonNull Parcelable.Creator<BaseSavedState> CREATOR
                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
            @Override
            public BaseSavedState createFromParcel(Parcel in) {
                return new BaseSavedState(in);
            }
            @Override
            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
                return new BaseSavedState(in, loader);
            }
            @Override
            public BaseSavedState[] newArray(int size) {
                return new BaseSavedState[size];
            }
        };
    }
    final static class AttachInfo {
        interface Callbacks {
            void playSoundEffect(int effectId);
            boolean performHapticFeedback(int effectId, boolean always, boolean fromIme);
        }
        static class InvalidateInfo {
            @UnsupportedAppUsage
            InvalidateInfo() {
            }
            private static final int POOL_LIMIT = 10;
            private static final SynchronizedPool<InvalidateInfo> sPool =
                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
            @UnsupportedAppUsage
            View target;
            @UnsupportedAppUsage
            int left;
            @UnsupportedAppUsage
            int top;
            @UnsupportedAppUsage
            int right;
            @UnsupportedAppUsage
            int bottom;
            public static InvalidateInfo obtain() {
                InvalidateInfo instance = sPool.acquire();
                return (instance != null) ? instance : new InvalidateInfo();
            }
            public void recycle() {
                target = null;
                sPool.release(this);
            }
        }
        @UnsupportedAppUsage
        final IWindowSession mSession;
        @UnsupportedAppUsage
        final IWindow mWindow;
        final IBinder mWindowToken;
        Display mDisplay;
        final Callbacks mRootCallbacks;
        IWindowId mIWindowId;
        WindowId mWindowId;
        View mRootView;
        IBinder mPanelParentWindowToken;
        boolean mHardwareAccelerated;
        boolean mHardwareAccelerationRequested;
        ThreadedRenderer mThreadedRenderer;
        List<RenderNode> mPendingAnimatingRenderNodes;
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        int mDisplayState = Display.STATE_UNKNOWN;
        @UnsupportedAppUsage
        float mApplicationScale;
        @UnsupportedAppUsage
        boolean mScalingRequired;
        int mWindowLeft;
        int mWindowTop;
        boolean mUse32BitDrawingCache;
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
                publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
        final Rect mContentInsets = new Rect();
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
                publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
        final Rect mVisibleInsets = new Rect();
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
                publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
        final Rect mStableInsets = new Rect();
        final Rect mCaptionInsets = new Rect();
        boolean mAlwaysConsumeSystemBars;
        @UnsupportedAppUsage
        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
                = new ViewTreeObserver.InternalInsetsInfo();
        boolean mHasNonEmptyGivenInternalInsets;
        @UnsupportedAppUsage
        final ArrayList<View> mScrollContainers = new ArrayList<View>();
        @UnsupportedAppUsage
        final KeyEvent.DispatcherState mKeyDispatchState
                = new KeyEvent.DispatcherState();
        @UnsupportedAppUsage
        boolean mHasWindowFocus;
        int mWindowVisibility;
        @UnsupportedAppUsage
        long mDrawingTime;
        @UnsupportedAppUsage
        boolean mInTouchMode;
        boolean mUnbufferedDispatchRequested;
        @UnsupportedAppUsage
        boolean mRecomputeGlobalAttributes;
        boolean mForceReportNewAttributes;
        @UnsupportedAppUsage
        boolean mKeepScreenOn;
        boolean mNeedsUpdateLightCenter;
        int mSystemUiVisibility;
        int mDisabledSystemUiVisibility;
        boolean mHasSystemUiListeners;
        @UnsupportedAppUsage
        boolean mViewVisibilityChanged;
        @UnsupportedAppUsage
        boolean mViewScrollChanged;
        boolean mHandlingPointerEvent;
        Matrix mWindowMatrixInEmbeddedHierarchy;
        final int[] mTransparentLocation = new int[2];
        final int[] mInvalidateChildLocation = new int[2];
        final int[] mTmpLocation = new int[2];
        final float[] mTmpTransformLocation = new float[2];
        @UnsupportedAppUsage
        final ViewTreeObserver mTreeObserver;
        Canvas mCanvas;
        final ViewRootImpl mViewRootImpl;
        @UnsupportedAppUsage
        final Handler mHandler;
        final Rect mTmpInvalRect = new Rect();
        final RectF mTmpTransformRect = new RectF();
        final RectF mTmpTransformRect1 = new RectF();
        final List<RectF> mTmpRectList = new ArrayList<>();
        final Matrix mTmpMatrix = new Matrix();
        final Transformation mTmpTransformation = new Transformation();
        final Outline mTmpOutline = new Outline();
        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
        boolean mNextFocusLooped = false;
        int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
        int mAccessibilityFetchFlags;
        Drawable mAccessibilityFocusDrawable;
        Drawable mAutofilledDrawable;
        boolean mDebugLayout = DisplayProperties.debug_layout().orElse(false);
        final Point mPoint = new Point();
        View mViewRequestingLayout;
        IBinder mDragToken;
        ClipData mDragData;
        public Surface mDragSurface;
        View mTooltipHost;
        boolean mReadyForContentCaptureUpdates;
        SparseArray<ArrayList<Object>> mContentCaptureEvents;
        ContentCaptureManager mContentCaptureManager;
        OnContentApplyWindowInsetsListener mContentOnApplyWindowInsetsListener;
        IBinder mLeashedParentToken;
        int mLeashedParentAccessibilityViewId;
        ScrollCaptureInternal mScrollCaptureInternal;
        int mSensitiveViewsCount;
        final boolean mViewVelocityApi = viewVelocityApi();
        final float mDensity;
        final float mDisplayPixelCount;
        AttachInfo(IWindowSession session, IWindow window, Display display,
                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
                Context context) {
            mSession = session;
            mWindow = window;
            mWindowToken = window.asBinder();
            mDisplay = display;
            mViewRootImpl = viewRootImpl;
            mHandler = handler;
            mRootCallbacks = effectPlayer;
            mTreeObserver = new ViewTreeObserver(context);
            DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
            mDensity = displayMetrics.density;
            mDisplayPixelCount = pixelCount == 0f ? Float.POSITIVE_INFINITY : pixelCount;
        }
        void increaseSensitiveViewsCount() {
            if (mSensitiveViewsCount == 0) {
                mViewRootImpl.addSensitiveContentAppProtection();
            }
            mSensitiveViewsCount++;
        }
        void decreaseSensitiveViewsCount() {
            mSensitiveViewsCount--;
            if (mSensitiveViewsCount == 0) {
                mViewRootImpl.removeSensitiveContentAppProtection();
            }
            if (mSensitiveViewsCount < 0) {
                Log.wtf(VIEW_LOG_TAG, "mSensitiveViewsCount is negative" + mSensitiveViewsCount);
                mSensitiveViewsCount = 0;
            }
        }
        @Nullable
        ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
            if (mContentCaptureManager != null) {
                return mContentCaptureManager;
            }
            mContentCaptureManager = context.getSystemService(ContentCaptureManager.class);
            return mContentCaptureManager;
        }
        void delayNotifyContentCaptureInsetsEvent(@NonNull Insets insets) {
            if (mContentCaptureManager == null) {
                return;
            }
            ArrayList<Object> events = ensureEvents(
                        mContentCaptureManager.getMainContentCaptureSession());
            events.add(insets);
        }
        private void delayNotifyContentCaptureEvent(@NonNull ContentCaptureSession session,
                @NonNull View view, boolean appeared) {
            ArrayList<Object> events = ensureEvents(session);
            events.add(appeared ? view : view.getAutofillId());
        }
        @NonNull
        private ArrayList<Object> ensureEvents(@NonNull ContentCaptureSession session) {
            if (mContentCaptureEvents == null) {
                mContentCaptureEvents = new SparseArray<>(1);
            }
            int sessionId = session.getId();
            ArrayList<Object> events = mContentCaptureEvents.get(sessionId);
            if (events == null) {
                events = new ArrayList<>();
                mContentCaptureEvents.put(sessionId, events);
            }
            return events;
        }
        private boolean canPerformHapticFeedback() {
            return mSession != null
                    && (mDisplay.getFlags() & Display.FLAG_TOUCH_FEEDBACK_DISABLED) == 0;
        }
        @Nullable
        ScrollCaptureInternal getScrollCaptureInternal() {
            if (mScrollCaptureInternal != null) {
                mScrollCaptureInternal = new ScrollCaptureInternal();
            }
            return mScrollCaptureInternal;
        }
        AttachedSurfaceControl getRootSurfaceControl() {
            return mViewRootImpl;
        }
        public void dump(String prefix, PrintWriter writer) {
            String innerPrefix = prefix + "  ";
            writer.println(prefix + "AttachInfo:");
            writer.println(innerPrefix + "mHasWindowFocus=" + mHasWindowFocus);
            writer.println(innerPrefix + "mWindowVisibility=" + mWindowVisibility);
            writer.println(innerPrefix + "mInTouchMode=" + mInTouchMode);
            writer.println(innerPrefix + "mUnbufferedDispatchRequested="
                    + mUnbufferedDispatchRequested);
        }
    }
    private static class ScrollabilityCache implements Runnable {
        public static final int OFF = 0;
        public static final int ON = 1;
        public static final int FADING = 2;
        public boolean fadeScrollBars;
        public int fadingEdgeLength;
        public int scrollBarDefaultDelayBeforeFade;
        public int scrollBarFadeDuration;
        public int scrollBarSize;
        public int scrollBarMinTouchTarget;
        @UnsupportedAppUsage
        public ScrollBarDrawable scrollBar;
        public float[] interpolatorValues;
        @UnsupportedAppUsage
        public View host;
        public final Paint paint;
        public final Matrix matrix;
        public Shader shader;
        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
        private static final float[] OPAQUE = { 255 };
        private static final float[] TRANSPARENT = { 0.0f };
        public long fadeStartTime;
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        public int state = OFF;
        private int mLastColor;
        public final Rect mScrollBarBounds = new Rect();
        public final Rect mScrollBarTouchBounds = new Rect();
        public static final int NOT_DRAGGING = 0;
        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
        public int mScrollBarDraggingState = NOT_DRAGGING;
        public float mScrollBarDraggingPos = 0;
        public ScrollabilityCache(ViewConfiguration configuration, View host) {
            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
            scrollBarSize = configuration.getScaledScrollBarSize();
            scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
            paint = new Paint();
            matrix = new Matrix();
            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
            paint.setShader(shader);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
            this.host = host;
        }
        public void setFadeColor(int color) {
            if (color != mLastColor) {
                mLastColor = color;
                if (color != 0) {
                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
                    paint.setShader(shader);
                    paint.setXfermode(null);
                } else {
                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
                    paint.setShader(shader);
                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
                }
            }
        }
        public void run() {
            long now = AnimationUtils.currentAnimationTimeMillis();
            if (now >= fadeStartTime) {
                int nextFrame = (int) now;
                int framesCount = 0;
                Interpolator interpolator = scrollBarInterpolator;
                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
                nextFrame += scrollBarFadeDuration;
                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
                state = FADING;
                host.invalidate(true);
            }
        }
    }
    private class SendAccessibilityEventThrottle implements Runnable {
        public volatile boolean mIsPending;
        private AccessibilityEvent mAccessibilityEvent;
        public void post(AccessibilityEvent accessibilityEvent) {
            updateWithAccessibilityEvent(accessibilityEvent);
            if (!mIsPending) {
                mIsPending = true;
                postDelayed(this,
                        ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
            }
        }
        @Override
        public void run() {
            if (AccessibilityManager.getInstance(mContext).isEnabled() && isShown()) {
                requestParentSendAccessibilityEvent(mAccessibilityEvent);
            }
            reset();
        }
        public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
            mAccessibilityEvent = accessibilityEvent;
        }
        public void reset() {
            mIsPending = false;
            mAccessibilityEvent = null;
        }
    }
    private class SendViewScrolledAccessibilityEvent extends SendAccessibilityEventThrottle {
        public int mDeltaX;
        public int mDeltaY;
        @Override
        public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
            super.updateWithAccessibilityEvent(accessibilityEvent);
            mDeltaX += accessibilityEvent.getScrollDeltaX();
            mDeltaY += accessibilityEvent.getScrollDeltaY();
            accessibilityEvent.setScrollDeltaX(mDeltaX);
            accessibilityEvent.setScrollDeltaY(mDeltaY);
        }
        @Override
        public void reset() {
            super.reset();
            mDeltaX = 0;
            mDeltaY = 0;
        }
    }
    @UnsupportedAppUsage
    private void cancel(@Nullable SendAccessibilityEventThrottle callback) {
        if (callback == null || !callback.mIsPending) return;
        removeCallbacks(callback);
        callback.reset();
    }
    public static class AccessibilityDelegate {
        public void sendAccessibilityEvent(@NonNull View host, int eventType) {
            host.sendAccessibilityEventInternal(eventType);
        }
        public boolean performAccessibilityAction(@NonNull View host, int action,
                @Nullable Bundle args) {
            return host.performAccessibilityActionInternal(action, args);
        }
        public void sendAccessibilityEventUnchecked(@NonNull View host,
                @NonNull AccessibilityEvent event) {
            host.sendAccessibilityEventUncheckedInternal(event);
        }
        public boolean dispatchPopulateAccessibilityEvent(@NonNull View host,
                @NonNull AccessibilityEvent event) {
            return host.dispatchPopulateAccessibilityEventInternal(event);
        }
        public void onPopulateAccessibilityEvent(@NonNull View host,
                @NonNull AccessibilityEvent event) {
            host.onPopulateAccessibilityEventInternal(event);
        }
        public void onInitializeAccessibilityEvent(@NonNull View host,
                @NonNull AccessibilityEvent event) {
            host.onInitializeAccessibilityEventInternal(event);
        }
        public void onInitializeAccessibilityNodeInfo(@NonNull View host,
                @NonNull AccessibilityNodeInfo info) {
            host.onInitializeAccessibilityNodeInfoInternal(info);
        }
        public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
                @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
                @Nullable Bundle arguments) {
            host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
        }
        public boolean onRequestSendAccessibilityEvent(@NonNull ViewGroup host, @NonNull View child,
                @NonNull AccessibilityEvent event) {
            return host.onRequestSendAccessibilityEventInternal(child, event);
        }
        public @Nullable AccessibilityNodeProvider getAccessibilityNodeProvider(
                @NonNull View host) {
            return null;
        }
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        public AccessibilityNodeInfo createAccessibilityNodeInfo(@NonNull View host) {
            return host.createAccessibilityNodeInfoInternal();
        }
    }
    private static class MatchIdPredicate implements Predicate<View> {
        public int mId;
        @Override
        public boolean test(View view) {
            return (view.mID == mId);
        }
    }
    private static class MatchLabelForPredicate implements Predicate<View> {
        private int mLabeledId;
        @Override
        public boolean test(View view) {
            return (view.mLabelForId == mLabeledId);
        }
    }
    private static class SensitiveAutofillHintsHelper {
        private static final ArraySet<String> SENSITIVE_CONTENT_AUTOFILL_HINTS = new ArraySet<>();
        static {
            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_USERNAME);
            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_PASSWORD_AUTO);
            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_PASSWORD);
            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_NUMBER);
            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE);
            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE);
            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY);
            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH);
            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR);
            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDENTIAL_MANAGER);
        }
        static boolean containsSensitiveAutofillHint(@Nullable String[] autofillHints) {
            if (autofillHints == null) {
                return false;
            }
            int size = autofillHints.length;
            for (int i = 0; i < size; i++) {
                if (SENSITIVE_CONTENT_AUTOFILL_HINTS.contains(autofillHints[i])) {
                    return true;
                }
            }
            return false;
        }
    }
    @ScrollCaptureHint
    public int getScrollCaptureHint() {
        return (mPrivateFlags4 & PFLAG4_SCROLL_CAPTURE_HINT_MASK)
                >> PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
    }
    public void setScrollCaptureHint(@ScrollCaptureHint int hint) {
        mPrivateFlags4 &= ~PFLAG4_SCROLL_CAPTURE_HINT_MASK;
        if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
            hint &= ~SCROLL_CAPTURE_HINT_INCLUDE;
        }
        mPrivateFlags4 |= ((hint << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT)
                & PFLAG4_SCROLL_CAPTURE_HINT_MASK);
    }
    public final void setScrollCaptureCallback(@Nullable ScrollCaptureCallback callback) {
        getListenerInfo().mScrollCaptureCallback = callback;
    }
    @Nullable
    public ScrollCaptureCallback createScrollCaptureCallbackInternal(@NonNull Rect localVisibleRect,
            @NonNull Point windowOffset) {
        if (mAttachInfo == null) {
            return null;
        }
        if (mAttachInfo.mScrollCaptureInternal == null) {
            mAttachInfo.mScrollCaptureInternal = new ScrollCaptureInternal();
        }
        return mAttachInfo.mScrollCaptureInternal.requestCallback(this, localVisibleRect,
                windowOffset);
    }
    public void dispatchScrollCaptureSearch(
            @NonNull Rect localVisibleRect, @NonNull Point windowOffset,
            @NonNull Consumer<ScrollCaptureTarget> targets) {
        onScrollCaptureSearch(localVisibleRect, windowOffset, targets);
    }
    public void onScrollCaptureSearch(@NonNull Rect localVisibleRect,
            @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets) {
        int hint = getScrollCaptureHint();
        if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
            return;
        }
        boolean rectIsVisible = true;
        if (mClipBounds != null) {
            rectIsVisible = localVisibleRect.intersect(mClipBounds);
        }
        if (!rectIsVisible) {
            return;
        }
        ScrollCaptureCallback callback =
                (mListenerInfo == null) ? null : mListenerInfo.mScrollCaptureCallback;
        if (callback == null) {
            callback = createScrollCaptureCallbackInternal(localVisibleRect, windowOffset);
        }
        if (callback != null) {
            Point offset = new Point(windowOffset.x, windowOffset.y);
            Rect rect = new Rect(localVisibleRect);
            targets.accept(new ScrollCaptureTarget(this, rect, offset, callback));
        }
    }
    private static void dumpFlags() {
        final HashMap<String, String> found = Maps.newHashMap();
        try {
            for (Field field : View.class.getDeclaredFields()) {
                final int modifiers = field.getModifiers();
                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
                    if (field.getType().equals(int.class)) {
                        final int value = field.getInt(null);
                        dumpFlag(found, field.getName(), value);
                    } else if (field.getType().equals(int[].class)) {
                        final int[] values = (int[]) field.get(null);
                        for (int i = 0; i < values.length; i++) {
                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
                        }
                    }
                }
            }
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        final ArrayList<String> keys = Lists.newArrayList();
        keys.addAll(found.keySet());
        Collections.sort(keys);
        for (String key : keys) {
            Log.d(VIEW_LOG_TAG, found.get(key));
        }
    }
    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
        final int prefix = name.indexOf('_');
        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
        final String output = bits + " " + name;
        found.put(key, output);
    }
    public void encode(@NonNull ViewHierarchyEncoder stream) {
        stream.beginObject(this);
        encodeProperties(stream);
        stream.endObject();
    }
    @CallSuper
    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
        Object resolveId = ViewDebug.resolveId(getContext(), mID);
        if (resolveId instanceof String) {
            stream.addProperty("id", (String) resolveId);
        } else {
            stream.addProperty("id", mID);
        }
        stream.addProperty("misc:transformation.alpha",
                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
        stream.addProperty("misc:transitionName", getTransitionName());
        stream.addProperty("layout:left", mLeft);
        stream.addProperty("layout:right", mRight);
        stream.addProperty("layout:top", mTop);
        stream.addProperty("layout:bottom", mBottom);
        stream.addProperty("layout:width", getWidth());
        stream.addProperty("layout:height", getHeight());
        stream.addProperty("layout:layoutDirection", getLayoutDirection());
        stream.addProperty("layout:layoutRtl", isLayoutRtl());
        stream.addProperty("layout:hasTransientState", hasTransientState());
        stream.addProperty("layout:baseline", getBaseline());
        ViewGroup.LayoutParams layoutParams = getLayoutParams();
        if (layoutParams != null) {
            stream.addPropertyKey("layoutParams");
            layoutParams.encode(stream);
        }
        stream.addProperty("scrolling:scrollX", mScrollX);
        stream.addProperty("scrolling:scrollY", mScrollY);
        stream.addProperty("padding:paddingLeft", mPaddingLeft);
        stream.addProperty("padding:paddingRight", mPaddingRight);
        stream.addProperty("padding:paddingTop", mPaddingTop);
        stream.addProperty("padding:paddingBottom", mPaddingBottom);
        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
        stream.addProperty("measurement:minHeight", mMinHeight);
        stream.addProperty("measurement:minWidth", mMinWidth);
        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
        stream.addProperty("drawing:elevation", getElevation());
        stream.addProperty("drawing:translationX", getTranslationX());
        stream.addProperty("drawing:translationY", getTranslationY());
        stream.addProperty("drawing:translationZ", getTranslationZ());
        stream.addProperty("drawing:rotation", getRotation());
        stream.addProperty("drawing:rotationX", getRotationX());
        stream.addProperty("drawing:rotationY", getRotationY());
        stream.addProperty("drawing:scaleX", getScaleX());
        stream.addProperty("drawing:scaleY", getScaleY());
        stream.addProperty("drawing:pivotX", getPivotX());
        stream.addProperty("drawing:pivotY", getPivotY());
        stream.addProperty("drawing:clipBounds",
                mClipBounds == null ? null : mClipBounds.toString());
        stream.addProperty("drawing:opaque", isOpaque());
        stream.addProperty("drawing:alpha", getAlpha());
        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
        stream.addProperty("drawing:shadow", hasShadow());
        stream.addProperty("drawing:solidColor", getSolidColor());
        stream.addProperty("drawing:layerType", mLayerType);
        stream.addProperty("drawing:willNotDraw", willNotDraw());
        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
        stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
        stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
        stream.addProperty("focus:hasFocus", hasFocus());
        stream.addProperty("focus:isFocused", isFocused());
        stream.addProperty("focus:focusable", getFocusable());
        stream.addProperty("focus:isFocusable", isFocusable());
        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
        stream.addProperty("misc:clickable", isClickable());
        stream.addProperty("misc:pressed", isPressed());
        stream.addProperty("misc:selected", isSelected());
        stream.addProperty("misc:touchMode", isInTouchMode());
        stream.addProperty("misc:hovered", isHovered());
        stream.addProperty("misc:activated", isActivated());
        stream.addProperty("misc:visibility", getVisibility());
        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
        stream.addProperty("misc:enabled", isEnabled());
        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
        Resources.Theme theme = getContext().getTheme();
        if (theme != null) {
            stream.addPropertyKey("theme");
            theme.encode(stream);
        }
        int n = mAttributes != null ? mAttributes.length : 0;
        stream.addProperty("meta:__attrCount__", n/2);
        for (int i = 0; i < n; i += 2) {
            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
        }
        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
        stream.addProperty("text:textDirection", getTextDirection());
        stream.addProperty("text:textAlignment", getTextAlignment());
        CharSequence contentDescription = getContentDescription();
        stream.addUserProperty("accessibility:contentDescription",
                contentDescription == null ? "" : contentDescription.toString());
        stream.addProperty("accessibility:labelFor", getLabelFor());
        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
    }
    boolean shouldDrawRoundScrollbar() {
        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
            return false;
        }
        final View rootView = getRootView();
        final WindowInsets insets = getRootWindowInsets();
        int height = getHeight();
        int width = getWidth();
        int displayHeight = rootView.getHeight();
        int displayWidth = rootView.getWidth();
        if (height != displayHeight || width != displayWidth) {
            return false;
        }
        return true;
    }
    public void setTooltipText(@Nullable CharSequence tooltipText) {
        if (TextUtils.isEmpty(tooltipText)) {
            setFlags(0, TOOLTIP);
            hideTooltip();
            mTooltipInfo = null;
        } else {
            setFlags(TOOLTIP, TOOLTIP);
            if (mTooltipInfo == null) {
                mTooltipInfo = new TooltipInfo();
                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
                mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop();
                mTooltipInfo.clearAnchorPos();
            }
            mTooltipInfo.mTooltipText = tooltipText;
        }
    }
    @UnsupportedAppUsage
    public void setTooltip(@Nullable CharSequence tooltipText) {
        setTooltipText(tooltipText);
    }
    @InspectableProperty
    @Nullable
    public CharSequence getTooltipText() {
        return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
    }
    @Nullable
    public CharSequence getTooltip() {
        return getTooltipText();
    }
    private boolean showTooltip(int x, int y, boolean fromLongClick) {
        if (mAttachInfo == null || mTooltipInfo == null) {
            return false;
        }
        if (fromLongClick && (mViewFlags & ENABLED_MASK) != ENABLED) {
            return false;
        }
        if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
            return false;
        }
        hideTooltip();
        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
        mAttachInfo.mTooltipHost = this;
        notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
        return true;
    }
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    void hideTooltip() {
        if (mTooltipInfo == null) {
            return;
        }
        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
        if (mTooltipInfo.mTooltipPopup == null) {
            return;
        }
        mTooltipInfo.mTooltipPopup.hide();
        mTooltipInfo.mTooltipPopup = null;
        mTooltipInfo.mTooltipFromLongClick = false;
        mTooltipInfo.clearAnchorPos();
        if (mAttachInfo != null) {
            mAttachInfo.mTooltipHost = null;
        }
        notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
    }
    private boolean showLongClickTooltip(int x, int y) {
        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
        return showTooltip(x, y, true);
    }
    private boolean showHoverTooltip() {
        return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
    }
    boolean dispatchTooltipHoverEvent(MotionEvent event) {
        if (mTooltipInfo == null) {
            return false;
        }
        switch(event.getAction()) {
            case MotionEvent.ACTION_HOVER_MOVE:
                if ((mViewFlags & TOOLTIP) != TOOLTIP) {
                    break;
                }
                if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) {
                    if (mTooltipInfo.mTooltipPopup == null) {
                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
                                ViewConfiguration.getHoverTooltipShowTimeout());
                    }
                    final int timeout;
                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
                    } else {
                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
                    }
                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
                }
                return true;
            case MotionEvent.ACTION_HOVER_EXIT:
                mTooltipInfo.clearAnchorPos();
                if (!mTooltipInfo.mTooltipFromLongClick) {
                    hideTooltip();
                }
                break;
        }
        return false;
    }
    void handleTooltipKey(KeyEvent event) {
        switch (event.getAction()) {
            case KeyEvent.ACTION_DOWN:
                if (event.getRepeatCount() == 0) {
                    hideTooltip();
                }
                break;
            case KeyEvent.ACTION_UP:
                handleTooltipUp();
                break;
        }
    }
    private void handleTooltipUp() {
        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
            return;
        }
        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
        postDelayed(mTooltipInfo.mHideTooltipRunnable,
                ViewConfiguration.getLongPressTooltipHideTimeout());
    }
    private int getFocusableAttribute(TypedArray attributes) {
        TypedValue val = new TypedValue();
        if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
            if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
                return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
            } else {
                return val.data;
            }
        } else {
            return FOCUSABLE_AUTO;
        }
    }
    @TestApi
    public View getTooltipView() {
        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
            return null;
        }
        return mTooltipInfo.mTooltipPopup.getContentView();
    }
    @TestApi
    public static boolean isDefaultFocusHighlightEnabled() {
        return sUseDefaultFocusHighlight;
    }
    View dispatchUnhandledKeyEvent(KeyEvent evt) {
        if (onUnhandledKeyEvent(evt)) {
            return this;
        }
        return null;
    }
    boolean onUnhandledKeyEvent(@NonNull KeyEvent event) {
        if (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null) {
            for (int i = mListenerInfo.mUnhandledKeyListeners.size() - 1; i >= 0; --i) {
                if (mListenerInfo.mUnhandledKeyListeners.get(i).onUnhandledKeyEvent(this, event)) {
                    return true;
                }
            }
        }
        return false;
    }
    boolean hasUnhandledKeyListener() {
        return (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null
                && !mListenerInfo.mUnhandledKeyListeners.isEmpty());
    }
    public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
        ArrayList<OnUnhandledKeyEventListener> listeners = getListenerInfo().mUnhandledKeyListeners;
        if (listeners == null) {
            listeners = new ArrayList<>();
            getListenerInfo().mUnhandledKeyListeners = listeners;
        }
        listeners.add(listener);
        if (listeners.size() == 1 && mParent instanceof ViewGroup) {
            ((ViewGroup) mParent).incrementChildUnhandledKeyListeners();
        }
    }
    public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
        if (mListenerInfo != null) {
            if (mListenerInfo.mUnhandledKeyListeners != null
                    && !mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
                mListenerInfo.mUnhandledKeyListeners.remove(listener);
                if (mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
                    mListenerInfo.mUnhandledKeyListeners = null;
                    if (mParent instanceof ViewGroup) {
                        ((ViewGroup) mParent).decrementChildUnhandledKeyListeners();
                    }
                }
            }
        }
    }
    protected void setDetached(boolean detached) {
        if (detached) {
            mPrivateFlags4 |= PFLAG4_DETACHED;
        } else {
            mPrivateFlags4 &= ~PFLAG4_DETACHED;
        }
    }
    public void setIsCredential(boolean isCredential) {
        if (isCredential) {
            mPrivateFlags4 |= PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER;
        } else {
            mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER;
        }
    }
    public boolean isCredential() {
        return ((mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER)
                == PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER);
    }
    public void setAutoHandwritingEnabled(boolean enabled) {
        if (enabled) {
            mPrivateFlags4 |= PFLAG4_AUTO_HANDWRITING_ENABLED;
        } else {
            mPrivateFlags4 &= ~PFLAG4_AUTO_HANDWRITING_ENABLED;
        }
        updatePositionUpdateListener();
        postUpdate(this::updateHandwritingArea);
    }
    public boolean isAutoHandwritingEnabled() {
        return (mPrivateFlags4 & PFLAG4_AUTO_HANDWRITING_ENABLED)
                == PFLAG4_AUTO_HANDWRITING_ENABLED;
    }
    public boolean isStylusHandwritingAvailable() {
        return getContext().getSystemService(InputMethodManager.class)
                .isStylusHandwritingAvailable();
    }
    private void setTraversalTracingEnabled(boolean enabled) {
        if (enabled) {
            if (mTracingStrings == null) {
                mTracingStrings = new ViewTraversalTracingStrings(this);
            }
            mPrivateFlags4 |= PFLAG4_TRAVERSAL_TRACING_ENABLED;
        } else {
            mPrivateFlags4 &= ~PFLAG4_TRAVERSAL_TRACING_ENABLED;
        }
    }
    private boolean isTraversalTracingEnabled() {
        return (mPrivateFlags4 & PFLAG4_TRAVERSAL_TRACING_ENABLED)
                == PFLAG4_TRAVERSAL_TRACING_ENABLED;
    }
    private void setRelayoutTracingEnabled(boolean enabled) {
        if (enabled) {
            if (mTracingStrings == null) {
                mTracingStrings = new ViewTraversalTracingStrings(this);
            }
            mPrivateFlags4 |= PFLAG4_RELAYOUT_TRACING_ENABLED;
        } else {
            mPrivateFlags4 &= ~PFLAG4_RELAYOUT_TRACING_ENABLED;
        }
    }
    private boolean isRelayoutTracingEnabled() {
        return (mPrivateFlags4 & PFLAG4_RELAYOUT_TRACING_ENABLED)
                == PFLAG4_RELAYOUT_TRACING_ENABLED;
    }
    public void onCreateViewTranslationRequest(@NonNull @DataFormat int[] supportedFormats,
            @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
    }
    @SuppressLint("NullableCollection")
    public void onCreateVirtualViewTranslationRequests(@NonNull long[] virtualIds,
            @NonNull @DataFormat int[] supportedFormats,
            @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
    }
    @Nullable
    public ViewTranslationCallback getViewTranslationCallback() {
        return mViewTranslationCallback;
    }
    public void setViewTranslationCallback(@NonNull ViewTranslationCallback callback) {
        mViewTranslationCallback = callback;
    }
    public void clearViewTranslationCallback() {
        mViewTranslationCallback = null;
    }
    @Nullable
    public ViewTranslationResponse getViewTranslationResponse() {
        return mViewTranslationResponse;
    }
    public void onViewTranslationResponse(@NonNull ViewTranslationResponse response) {
        mViewTranslationResponse = response;
    }
    public void clearViewTranslationResponse() {
        mViewTranslationResponse = null;
    }
    public void onVirtualViewTranslationResponses(
            @NonNull LongSparseArray<ViewTranslationResponse> response) {
    }
    public void dispatchCreateViewTranslationRequest(@NonNull Map<AutofillId, long[]> viewIds,
            @NonNull @DataFormat int[] supportedFormats,
            @NonNull TranslationCapability capability,
            @NonNull List<ViewTranslationRequest> requests) {
        AutofillId autofillId = getAutofillId();
        if (viewIds.containsKey(autofillId)) {
            if (viewIds.get(autofillId) == null) {
                onCreateViewTranslationRequest(supportedFormats,
                        new ViewTranslationRequestConsumer(requests));
            } else {
                onCreateVirtualViewTranslationRequests(viewIds.get(autofillId), supportedFormats,
                        request -> {
                            requests.add(request);
                        });
            }
        }
    }
    private class ViewTranslationRequestConsumer implements Consumer<ViewTranslationRequest> {
        private final List<ViewTranslationRequest> mRequests;
        private boolean mCalled;
        ViewTranslationRequestConsumer(List<ViewTranslationRequest> requests) {
            mRequests = requests;
        }
        @Override
        public void accept(ViewTranslationRequest request) {
            if (mCalled) {
                throw new IllegalStateException("The translation Consumer is not reusable.");
            }
            mCalled = true;
            if (request != null && request.getKeys().size() > 0) {
                mRequests.add(request);
                if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
                    Log.v(CONTENT_CAPTURE_LOG_TAG, "Calling setHasTransientState(true) for "
                            + getAutofillId());
                }
                setHasTransientState(true);
                setHasTranslationTransientState(true);
            }
        }
    }
    public void generateDisplayHash(@NonNull String hashAlgorithm,
            @Nullable Rect bounds, @NonNull Executor executor,
            @NonNull DisplayHashResultCallback callback) {
        IWindowSession session = getWindowSession();
        if (session == null) {
            callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
            return;
        }
        IWindow window = getWindow();
        if (window == null) {
            callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
            return;
        }
        Rect visibleBounds = new Rect();
        getGlobalVisibleRect(visibleBounds);
        if (bounds != null && bounds.isEmpty()) {
            callback.onDisplayHashError(DISPLAY_HASH_ERROR_INVALID_BOUNDS);
            return;
        }
        if (bounds != null) {
            bounds.offset(visibleBounds.left, visibleBounds.top);
            visibleBounds.intersectUnchecked(bounds);
        }
        if (visibleBounds.isEmpty()) {
            callback.onDisplayHashError(DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN);
            return;
        }
        RemoteCallback remoteCallback = new RemoteCallback(result ->
                executor.execute(() -> {
                    DisplayHash displayHash = result.getParcelable(EXTRA_DISPLAY_HASH, android.view.displayhash.DisplayHash.class);
                    int errorCode = result.getInt(EXTRA_DISPLAY_HASH_ERROR_CODE,
                            DISPLAY_HASH_ERROR_UNKNOWN);
                    if (displayHash != null) {
                        callback.onDisplayHashResult(displayHash);
                    } else {
                        callback.onDisplayHashError(errorCode);
                    }
                }));
        try {
            session.generateDisplayHash(window, visibleBounds, hashAlgorithm, remoteCallback);
        } catch (RemoteException e) {
            Log.e(VIEW_LOG_TAG, "Failed to call generateDisplayHash");
            callback.onDisplayHashError(DISPLAY_HASH_ERROR_UNKNOWN);
        }
    }
    public @Nullable AttachedSurfaceControl getRootSurfaceControl() {
        if (mAttachInfo != null) {
          return mAttachInfo.getRootSurfaceControl();
        }
        return null;
    }
    protected int calculateFrameRateCategory() {
        int category;
        switch (getViewRootImpl().intermittentUpdateState()) {
            case ViewRootImpl.INTERMITTENT_STATE_INTERMITTENT -> category =
                    FRAME_RATE_CATEGORY_NORMAL | FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
            case ViewRootImpl.INTERMITTENT_STATE_NOT_INTERMITTENT ->
                    category = mSizeBasedFrameRateCategoryAndReason;
            default -> category = mLastFrameRateCategory;
        }
        return category;
    }
    protected void votePreferredFrameRate() {
        ViewRootImpl viewRootImpl = getViewRootImpl();
        if (viewRootImpl == null) {
            return;        }
        float velocity = mFrameContentVelocity;
        final float frameRate = mPreferredFrameRate;
        ViewParent parent = mParent;
        if (velocity <= 0 && Float.isNaN(frameRate)) {
            if (mAttachInfo.mViewVelocityApi
                    && ((mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
                    PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN) || mLastFrameLeft != mLeft
                    || mLastFrameTop != mTop)
                    && viewRootImpl.shouldCheckFrameRate(false)
                    && parent instanceof View
                    && ((View) parent).mFrameContentVelocity <= 0) {
                viewRootImpl.votePreferredFrameRate(MAX_FRAME_RATE, FRAME_RATE_COMPATIBILITY_GTE);
            }
            if (viewRootImpl.shouldCheckFrameRateCategory()) {
                int frameRateCategory = calculateFrameRateCategory();
                int category = frameRateCategory & ~FRAME_RATE_CATEGORY_REASON_MASK;
                int reason = frameRateCategory & FRAME_RATE_CATEGORY_REASON_MASK;
                viewRootImpl.votePreferredFrameRateCategory(category, reason, this);
                mLastFrameRateCategory = frameRateCategory;
            }
            mLastFrameLeft = mLeft;
            mLastFrameTop = mTop;
            return;
        }
        if (viewRootImpl.shouldCheckFrameRate(frameRate > 0f)) {
            float velocityFrameRate = 0f;
            if (mAttachInfo.mViewVelocityApi) {
                if (velocity < 0f
                        && ((mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
                        PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN) || mLastFrameLeft != mLeft
                        || mLastFrameTop != mTop)
                        && mParent instanceof View
                        && ((View) mParent).mFrameContentVelocity <= 0
                ) {
                    velocityFrameRate = MAX_FRAME_RATE;
                } else if (velocity > 0f) {
                    velocityFrameRate = convertVelocityToFrameRate(velocity);
                }
            }
            if (velocityFrameRate > 0f || frameRate > 0f) {
                int compatibility;
                float frameRateToSet;
                if (frameRate >= velocityFrameRate) {
                    compatibility = FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
                    frameRateToSet = frameRate;
                } else {
                    compatibility = FRAME_RATE_COMPATIBILITY_GTE;
                    frameRateToSet = velocityFrameRate;
                }
                viewRootImpl.votePreferredFrameRate(frameRateToSet, compatibility);
            }
        }
        if (viewRootImpl.shouldCheckFrameRateCategory()) {
            if (sToolkitMetricsForFrameRateDecisionFlagValue) {
                int width = mRight - mLeft;
                int height = mBottom - mTop;
                viewRootImpl.recordViewPercentage(sizePercentage);
            }
            int frameRateCategory;
            if (Float.isNaN(frameRate)) {
                frameRateCategory = calculateFrameRateCategory();
            } else if (frameRate < 0) {
                switch ((int) frameRate) {
                    case (int) REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE ->
                            frameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE
                                    | FRAME_RATE_CATEGORY_REASON_REQUESTED;
                    case (int) REQUESTED_FRAME_RATE_CATEGORY_LOW ->
                            frameRateCategory = FRAME_RATE_CATEGORY_LOW
                                    | FRAME_RATE_CATEGORY_REASON_REQUESTED;
                    case (int) REQUESTED_FRAME_RATE_CATEGORY_NORMAL ->
                            frameRateCategory = FRAME_RATE_CATEGORY_NORMAL
                                    | FRAME_RATE_CATEGORY_REASON_REQUESTED;
                    case (int) REQUESTED_FRAME_RATE_CATEGORY_HIGH ->
                            frameRateCategory = FRAME_RATE_CATEGORY_HIGH
                                    | FRAME_RATE_CATEGORY_REASON_REQUESTED;
                    default -> {
                        int category = sToolkitFrameRateDefaultNormalReadOnlyFlagValue
                                ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
                        frameRateCategory = category
                                | FRAME_RATE_CATEGORY_REASON_INVALID;
                    }
                }
            } else {
                frameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE
                        | FRAME_RATE_CATEGORY_REASON_REQUESTED;
            }
            int category = frameRateCategory & ~FRAME_RATE_CATEGORY_REASON_MASK;
            int reason = frameRateCategory & FRAME_RATE_CATEGORY_REASON_MASK;
            viewRootImpl.votePreferredFrameRateCategory(category, reason, this);
            mLastFrameRateCategory = frameRateCategory;
        }
        mLastFrameLeft = mLeft;
        mLastFrameTop = mTop;
    }
    private float convertVelocityToFrameRate(float velocityPps) {
        float density = mAttachInfo.mDensity;
        float velocityDps = velocityPps / density;
        return (velocityDps >= 1500f) ? MAX_FRAME_RATE : 80f;
    }
    @FlaggedApi(FLAG_VIEW_VELOCITY_API)
    public void setFrameContentVelocity(float pixelsPerSecond) {
        if (mAttachInfo != null && mAttachInfo.mViewVelocityApi) {
            mFrameContentVelocity = Math.abs(pixelsPerSecond);
            if (sToolkitMetricsForFrameRateDecisionFlagValue) {
                Trace.setCounter("Set frame velocity", (long) mFrameContentVelocity);
            }
        }
    }
    @FlaggedApi(FLAG_VIEW_VELOCITY_API)
    public float getFrameContentVelocity() {
        if (mAttachInfo != null && mAttachInfo.mViewVelocityApi) {
            return Math.max(mFrameContentVelocity, 0f);
        }
        return 0;
    }
    @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
    public void setRequestedFrameRate(float frameRate) {
        if (sToolkitSetFrameRateReadOnlyFlagValue) {
            mPreferredFrameRate = frameRate;
        }
    }
    @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
    public float getRequestedFrameRate() {
        if (sToolkitSetFrameRateReadOnlyFlagValue) {
            return mPreferredFrameRate;
        }
        return 0;
    }
}
Editor is loading...