() {
+ public Message createFromParcel(Parcel source) {
+ Message msg = Message.obtain();
+ msg.readFromParcel(source);
+ return msg;
+ }
+
+ public Message[] newArray(int size) {
+ return new Message[size];
+ }
+ };
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ if (callback != null) {
+ throw new RuntimeException(
+ "Can't marshal callbacks across processes.");
+ }
+ dest.writeInt(what);
+ dest.writeInt(arg1);
+ dest.writeInt(arg2);
+ if (obj != null) {
+ try {
+ Parcelable p = (Parcelable)obj;
+ dest.writeInt(1);
+ dest.writeParcelable(p, flags);
+ } catch (ClassCastException e) {
+ throw new RuntimeException(
+ "Can't marshal non-Parcelable objects across processes.");
+ }
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeLong(when);
+ dest.writeBundle(data);
+ Messenger.writeMessengerOrNullToParcel(replyTo, dest);
+ dest.writeInt(sendingUid);
+ dest.writeInt(workSourceUid);
+ }
+
+ private void readFromParcel(Parcel source) {
+ what = source.readInt();
+ arg1 = source.readInt();
+ arg2 = source.readInt();
+ if (source.readInt() != 0) {
+ obj = source.readParcelable(getClass().getClassLoader());
+ }
+ when = source.readLong();
+ data = source.readBundle();
+ replyTo = Messenger.readMessengerOrNullFromParcel(source);
+ sendingUid = source.readInt();
+ workSourceUid = source.readInt();
+ }
+}
diff --git a/AndroidCompat/src/main/java/android/os/MessageQueue.java b/AndroidCompat/src/main/java/android/os/MessageQueue.java
new file mode 100644
index 00000000..462ff31d
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/os/MessageQueue.java
@@ -0,0 +1,1700 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.TestApi;
+import android.app.Instrumentation;
+import android.os.shadows.ShadowPausedMessageQueue;
+import android.util.Log;
+import android.util.Printer;
+import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
+
+import java.io.FileDescriptor;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Low-level class holding the list of messages to be dispatched by a
+ * {@link Looper}. Messages are not added directly to a MessageQueue,
+ * but rather through {@link Handler} objects associated with the Looper.
+ *
+ * You can retrieve the MessageQueue for the current thread with
+ * {@link Looper#myQueue() Looper.myQueue()}.
+ */
+public final class MessageQueue {
+ private static final String TAG = "ConcurrentMessageQueue";
+ private static final boolean DEBUG = false;
+ private static final boolean TRACE = false;
+
+ // True if the message queue can be quit.
+ private final boolean mQuitAllowed;
+
+ @SuppressWarnings("unused")
+ private long mPtr; // used by native code
+
+ @IntDef(value = {
+ STACK_NODE_MESSAGE,
+ STACK_NODE_ACTIVE,
+ STACK_NODE_PARKED,
+ STACK_NODE_TIMEDPARK})
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface StackNodeType {}
+
+ /*
+ * Stack node types. STACK_NODE_MESSAGE indicates a node containing a message.
+ * The other types indicate what state our Looper thread is in. The bottom of
+ * the stack is always a single state node. Message nodes are added on top.
+ */
+ private static final int STACK_NODE_MESSAGE = 0;
+ /*
+ * Active state indicates that next() is processing messages
+ */
+ private static final int STACK_NODE_ACTIVE = 1;
+ /*
+ * Parked state indicates that the Looper thread is sleeping indefinitely (nothing to deliver)
+ */
+ private static final int STACK_NODE_PARKED = 2;
+ /*
+ * Timed Park state indicates that the Looper thread is sleeping, waiting for a message
+ * deadline
+ */
+ private static final int STACK_NODE_TIMEDPARK = 3;
+
+ /* Describes a node in the Treiber stack */
+ static class StackNode {
+ @StackNodeType
+ private final int mType;
+
+ StackNode(@StackNodeType int type) {
+ mType = type;
+ }
+
+ @StackNodeType
+ final int getNodeType() {
+ return mType;
+ }
+
+ final boolean isMessageNode() {
+ return mType == STACK_NODE_MESSAGE;
+ }
+ }
+
+ static final class MessageNode extends StackNode implements Comparable {
+ private final Message mMessage;
+ volatile StackNode mNext;
+ StateNode mBottomOfStack;
+ boolean mWokeUp;
+ final long mInsertSeq;
+ private static final VarHandle sRemovedFromStack;
+ private volatile boolean mRemovedFromStackValue;
+ static {
+ try {
+ MethodHandles.Lookup l = MethodHandles.lookup();
+ sRemovedFromStack = l.findVarHandle(MessageQueue.MessageNode.class,
+ "mRemovedFromStackValue", boolean.class);
+ } catch (Exception e) {
+ Log.wtf(TAG, "VarHandle lookup failed with exception: " + e);
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ MessageNode(@NonNull Message message, long insertSeq) {
+ super(STACK_NODE_MESSAGE);
+ mMessage = message;
+ mInsertSeq = insertSeq;
+ }
+
+ long getWhen() {
+ return mMessage.when;
+ }
+
+ boolean isRemovedFromStack() {
+ return mRemovedFromStackValue;
+ }
+
+ boolean removeFromStack() {
+ return sRemovedFromStack.compareAndSet(this, false, true);
+ }
+
+ boolean isAsync() {
+ return mMessage.isAsynchronous();
+ }
+
+ boolean isBarrier() {
+ return mMessage.target == null;
+ }
+
+ @Override
+ public int compareTo(@NonNull MessageNode messageNode) {
+ Message other = messageNode.mMessage;
+
+ int compared = Long.compare(mMessage.when, other.when);
+ if (compared == 0) {
+ compared = Long.compare(mInsertSeq, messageNode.mInsertSeq);
+ }
+ return compared;
+ }
+ }
+
+ static class StateNode extends StackNode {
+ StateNode(int type) {
+ super(type);
+ }
+ }
+
+ static final class TimedParkStateNode extends StateNode {
+ long mWhenToWake;
+
+ TimedParkStateNode() {
+ super(STACK_NODE_TIMEDPARK);
+ }
+ }
+
+ private static final StateNode sStackStateActive = new StateNode(STACK_NODE_ACTIVE);
+ private static final StateNode sStackStateParked = new StateNode(STACK_NODE_PARKED);
+ private final TimedParkStateNode mStackStateTimedPark = new TimedParkStateNode();
+
+ /* This is the top of our treiber stack. */
+ private static final VarHandle sState;
+ static {
+ try {
+ MethodHandles.Lookup l = MethodHandles.lookup();
+ sState = l.findVarHandle(MessageQueue.class, "mStateValue",
+ MessageQueue.StackNode.class);
+ } catch (Exception e) {
+ Log.wtf(TAG, "VarHandle lookup failed with exception: " + e);
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ private volatile StackNode mStateValue = sStackStateParked;
+ private final ConcurrentSkipListSet mPriorityQueue =
+ new ConcurrentSkipListSet();
+ private final ConcurrentSkipListSet mAsyncPriorityQueue =
+ new ConcurrentSkipListSet();
+
+ /*
+ * This helps us ensure that messages with the same timestamp are inserted in FIFO order.
+ * Increments on each insert, starting at 0. MessageNode.compareTo() will compare sequences
+ * when delivery timestamps are identical.
+ */
+ private static final VarHandle sNextInsertSeq;
+ private volatile long mNextInsertSeqValue = 0;
+ /*
+ * The exception to the FIFO order rule is sendMessageAtFrontOfQueue().
+ * Those messages must be in LIFO order.
+ * Decrements on each front of queue insert.
+ */
+ private static final VarHandle sNextFrontInsertSeq;
+ private volatile long mNextFrontInsertSeqValue = -1;
+ static {
+ try {
+ MethodHandles.Lookup l = MethodHandles.lookup();
+ sNextInsertSeq = l.findVarHandle(MessageQueue.class, "mNextInsertSeqValue",
+ long.class);
+ sNextFrontInsertSeq = l.findVarHandle(MessageQueue.class, "mNextFrontInsertSeqValue",
+ long.class);
+ } catch (Exception e) {
+ Log.wtf(TAG, "VarHandle lookup failed with exception: " + e);
+ throw new ExceptionInInitializerError(e);
+ }
+
+ }
+
+ /*
+ * Tracks the number of queued and cancelled messages in our stack.
+ *
+ * On item cancellation, determine whether to wake next() to flush tombstoned messages.
+ * We track queued and cancelled counts as two ints packed into a single long.
+ */
+ private static final class MessageCounts {
+ private static VarHandle sCounts;
+ private volatile long mCountsValue = 0;
+ static {
+ try {
+ MethodHandles.Lookup l = MethodHandles.lookup();
+ sCounts = l.findVarHandle(MessageQueue.MessageCounts.class, "mCountsValue",
+ long.class);
+ } catch (Exception e) {
+ Log.wtf(TAG, "VarHandle lookup failed with exception: " + e);
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ /* We use a special value to indicate when next() has been woken for flush. */
+ private static final long AWAKE = Long.MAX_VALUE;
+ /*
+ * Minimum number of messages in the stack which we need before we consider flushing
+ * tombstoned items.
+ */
+ private static final int MESSAGE_FLUSH_THRESHOLD = 10;
+
+ private static int numQueued(long val) {
+ return (int) (val >>> Integer.SIZE);
+ }
+
+ private static int numCancelled(long val) {
+ return (int) val;
+ }
+
+ private static long combineCounts(int queued, int cancelled) {
+ return ((long) queued << Integer.SIZE) | (long) cancelled;
+ }
+
+ public void incrementQueued() {
+ while (true) {
+ long oldVal = mCountsValue;
+ int queued = numQueued(oldVal);
+ int cancelled = numCancelled(oldVal);
+ /* Use Math.max() to avoid overflow of queued count */
+ long newVal = combineCounts(Math.max(queued + 1, queued), cancelled);
+
+ /* Don't overwrite 'AWAKE' state */
+ if (oldVal == AWAKE || sCounts.compareAndSet(this, oldVal, newVal)) {
+ break;
+ }
+ }
+ }
+
+ public boolean incrementCancelled() {
+ while (true) {
+ long oldVal = mCountsValue;
+ if (oldVal == AWAKE) {
+ return false;
+ }
+ int queued = numQueued(oldVal);
+ int cancelled = numCancelled(oldVal);
+ boolean needsPurge = queued > MESSAGE_FLUSH_THRESHOLD
+ && (queued >> 1) < cancelled;
+ long newVal;
+ if (needsPurge) {
+ newVal = AWAKE;
+ } else {
+ newVal = combineCounts(queued,
+ Math.max(cancelled + 1, cancelled));
+ }
+
+ if (sCounts.compareAndSet(this, oldVal, newVal)) {
+ return needsPurge;
+ }
+ }
+ }
+
+ public void clearCounts() {
+ mCountsValue = 0;
+ }
+ }
+
+ private final MessageCounts mMessageCounts = new MessageCounts();
+
+ private final Object mIdleHandlersLock = new Object();
+ private final ArrayList mIdleHandlers = new ArrayList();
+ private IdleHandler[] mPendingIdleHandlers;
+
+ private final Object mFileDescriptorRecordsLock = new Object();
+ private SparseArray mFileDescriptorRecords;
+
+ private static final VarHandle sQuitting;
+ private boolean mQuittingValue = false;
+ static {
+ try {
+ MethodHandles.Lookup l = MethodHandles.lookup();
+ sQuitting = l.findVarHandle(MessageQueue.class, "mQuittingValue", boolean.class);
+ } catch (Exception e) {
+ Log.wtf(TAG, "VarHandle lookup failed with exception: " + e);
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ // The next barrier token.
+ // Barriers are indicated by messages with a null target whose arg1 field carries the token.
+ private final AtomicInteger mNextBarrierToken = new AtomicInteger(1);
+
+ MessageQueue(boolean quitAllowed) {
+ mQuitAllowed = quitAllowed;
+ mPtr = ShadowPausedMessageQueue.nativeInit();
+ }
+
+ private static void throwIfNotTest() {
+ throw new IllegalStateException("Test-only API called not from a test!");
+ }
+
+ private static void throwIfNotTest$ravenwood() {
+ return;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ dispose();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ // Disposes of the underlying message queue.
+ // Must only be called on the looper thread or the finalizer.
+ private void dispose() {
+ if (mPtr != 0) {
+ ShadowPausedMessageQueue.nativeDestroy(mPtr);
+ mPtr = 0;
+ }
+ }
+
+ private static final class MatchDeliverableMessages extends MessageCompare {
+ @Override
+ public boolean compareMessage(MessageNode n, Handler h, int what, Object object,
+ Runnable r, long when) {
+ final Message m = n.mMessage;
+ if (m.when <= when) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private final MatchDeliverableMessages mMatchDeliverableMessages =
+ new MatchDeliverableMessages();
+ /**
+ * Returns true if the looper has no pending messages which are due to be processed.
+ *
+ * This method is safe to call from any thread.
+ *
+ * @return True if the looper is idle.
+ */
+ public boolean isIdle() {
+ final long now = SystemClock.uptimeMillis();
+
+ if (stackHasMessages(null, 0, null, null, now, mMatchDeliverableMessages, false)) {
+ return false;
+ }
+
+ MessageNode msgNode = null;
+ MessageNode asyncMsgNode = null;
+
+ if (!mPriorityQueue.isEmpty()) {
+ try {
+ msgNode = mPriorityQueue.first();
+ } catch (NoSuchElementException e) { }
+ }
+
+ if (!mAsyncPriorityQueue.isEmpty()) {
+ try {
+ asyncMsgNode = mAsyncPriorityQueue.first();
+ } catch (NoSuchElementException e) { }
+ }
+
+ if ((msgNode != null && msgNode.getWhen() <= now)
+ || (asyncMsgNode != null && asyncMsgNode.getWhen() <= now)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /* Protects mNextIsDrainingStack */
+ private final ReentrantLock mDrainingLock = new ReentrantLock();
+ private boolean mNextIsDrainingStack = false;
+ private final Condition mDrainCompleted = mDrainingLock.newCondition();
+
+ /**
+ * Add a new {@link IdleHandler} to this message queue. This may be
+ * removed automatically for you by returning false from
+ * {@link IdleHandler#queueIdle IdleHandler.queueIdle()} when it is
+ * invoked, or explicitly removing it with {@link #removeIdleHandler}.
+ *
+ *
This method is safe to call from any thread.
+ *
+ * @param handler The IdleHandler to be added.
+ */
+ public void addIdleHandler(@NonNull IdleHandler handler) {
+ if (handler == null) {
+ throw new NullPointerException("Can't add a null IdleHandler");
+ }
+ synchronized (mIdleHandlersLock) {
+ mIdleHandlers.add(handler);
+ }
+ }
+
+ /**
+ * Remove an {@link IdleHandler} from the queue that was previously added
+ * with {@link #addIdleHandler}. If the given object is not currently
+ * in the idle list, nothing is done.
+ *
+ *
This method is safe to call from any thread.
+ *
+ * @param handler The IdleHandler to be removed.
+ */
+ public void removeIdleHandler(@NonNull IdleHandler handler) {
+ synchronized (mIdleHandlersLock) {
+ mIdleHandlers.remove(handler);
+ }
+ }
+
+ /**
+ * Returns whether this looper's thread is currently polling for more work to do.
+ * This is a good signal that the loop is still alive rather than being stuck
+ * handling a callback. Note that this method is intrinsically racy, since the
+ * state of the loop can change before you get the result back.
+ *
+ *
This method is safe to call from any thread.
+ *
+ * @return True if the looper is currently polling for events.
+ * @hide
+ */
+ public boolean isPolling() {
+ // If the loop is quitting then it must not be idling.
+ // We can assume mPtr != 0 when sQuitting is false.
+ return !((boolean) sQuitting.getVolatile(this)) && ShadowPausedMessageQueue.nativeIsPolling(mPtr);
+ }
+
+ /* Helper to choose the correct queue to insert into. */
+ private void insertIntoPriorityQueue(MessageNode msgNode) {
+ if (msgNode.isAsync()) {
+ mAsyncPriorityQueue.add(msgNode);
+ } else {
+ mPriorityQueue.add(msgNode);
+ }
+ }
+
+ private boolean removeFromPriorityQueue(MessageNode msgNode) {
+ if (msgNode.isAsync()) {
+ return mAsyncPriorityQueue.remove(msgNode);
+ } else {
+ return mPriorityQueue.remove(msgNode);
+ }
+ }
+
+ private MessageNode pickEarliestNode(MessageNode nodeA, MessageNode nodeB) {
+ if (nodeA != null && nodeB != null) {
+ if (nodeA.compareTo(nodeB) < 0) {
+ return nodeA;
+ }
+ return nodeB;
+ }
+
+ return nodeA != null ? nodeA : nodeB;
+ }
+
+ private MessageNode iterateNext(Iterator iter) {
+ if (iter.hasNext()) {
+ try {
+ return iter.next();
+ } catch (NoSuchElementException e) {
+ /* The queue is empty - this can happen if we race with remove */
+ }
+ }
+ return null;
+ }
+
+ /* Move any non-cancelled messages into the priority queue */
+ private void drainStack(StackNode oldTop) {
+ while (oldTop.isMessageNode()) {
+ MessageNode oldTopMessageNode = (MessageNode) oldTop;
+ if (oldTopMessageNode.removeFromStack()) {
+ insertIntoPriorityQueue(oldTopMessageNode);
+ }
+ MessageNode inserted = oldTopMessageNode;
+ oldTop = oldTopMessageNode.mNext;
+ /*
+ * removeMessages can walk this list while we are consuming it.
+ * Set our next pointer to null *after* we add the message to our
+ * priority queue. This way removeMessages() will always find the
+ * message, either in our list or in the priority queue.
+ */
+ inserted.mNext = null;
+ }
+ }
+
+ /* Set the stack state to Active, return a list of nodes to walk. */
+ private StackNode swapAndSetStackStateActive() {
+ while (true) {
+ /* Set stack state to Active, get node list to walk later */
+ StackNode current = (StackNode) sState.getVolatile(this);
+ if (current == sStackStateActive
+ || sState.compareAndSet(this, current, sStackStateActive)) {
+ return current;
+ }
+ }
+ }
+
+ /* This is only read/written from the Looper thread */
+ private int mNextPollTimeoutMillis;
+ private static final AtomicLong mMessagesDelivered = new AtomicLong();
+ private boolean mMessageDirectlyQueued;
+
+ private Message nextMessage() {
+ return nextMessage(false); // TODO: Suwayomi this was not given, no idea how that works
+ }
+
+ private Message nextMessage(boolean peek) {
+ int i = 0;
+
+ while (true) {
+ if (DEBUG) {
+ Log.d(TAG, "nextMessage loop #" + i);
+ i++;
+ }
+
+ mDrainingLock.lock();
+ mNextIsDrainingStack = true;
+ mDrainingLock.unlock();
+
+ /*
+ * Set our state to active, drain any items from the stack into our priority queues
+ */
+ StackNode oldTop;
+ oldTop = swapAndSetStackStateActive();
+ drainStack(oldTop);
+
+ mDrainingLock.lock();
+ mNextIsDrainingStack = false;
+ mDrainCompleted.signalAll();
+ mDrainingLock.unlock();
+
+ /*
+ * The objective of this next block of code is to:
+ * - find a message to return (if any is ready)
+ * - find a next message we would like to return, after scheduling.
+ * - we make our scheduling decision based on this next message (if it exists).
+ *
+ * We have two queues to juggle and the presence of barriers throws an additional
+ * wrench into our plans.
+ *
+ * The last wrinkle is that remove() may delete items from underneath us. If we hit
+ * that case, we simply restart the loop.
+ */
+
+ /* Get the first node from each queue */
+ Iterator queueIter = mPriorityQueue.iterator();
+ MessageNode msgNode = iterateNext(queueIter);
+ Iterator asyncQueueIter = mAsyncPriorityQueue.iterator();
+ MessageNode asyncMsgNode = iterateNext(asyncQueueIter);
+
+ if (DEBUG) {
+ if (msgNode != null) {
+ Message msg = msgNode.mMessage;
+ Log.d(TAG, "Next found node what: " + msg.what + " when: " + msg.when
+ + " seq: " + msgNode.mInsertSeq + "barrier: "
+ + msgNode.isBarrier() + " now: " + SystemClock.uptimeMillis());
+ }
+ if (asyncMsgNode != null) {
+ Message msg = asyncMsgNode.mMessage;
+ Log.d(TAG, "Next found async node what: " + msg.what + " when: " + msg.when
+ + " seq: " + asyncMsgNode.mInsertSeq + "barrier: "
+ + asyncMsgNode.isBarrier() + " now: "
+ + SystemClock.uptimeMillis());
+ }
+ }
+
+ /*
+ * the node which we will return, null if none are ready
+ */
+ MessageNode found = null;
+ /*
+ * The node from which we will determine our next wakeup time.
+ * Null indicates there is no next message ready. If we found a node,
+ * we can leave this null as Looper will call us again after delivering
+ * the message.
+ */
+ MessageNode next = null;
+
+ long now = SystemClock.uptimeMillis();
+ /*
+ * If we have a barrier we should return the async node (if it exists and is ready)
+ */
+ if (msgNode != null && msgNode.isBarrier()) {
+ if (asyncMsgNode != null && now >= asyncMsgNode.getWhen()) {
+ found = asyncMsgNode;
+ } else {
+ next = asyncMsgNode;
+ }
+ } else { /* No barrier. */
+ MessageNode earliest;
+ /*
+ * If we have two messages, pick the earliest option from either queue.
+ * Otherwise grab whichever node is non-null. If both are null we'll fall through.
+ */
+ earliest = pickEarliestNode(msgNode, asyncMsgNode);
+
+ if (earliest != null) {
+ if (now >= earliest.getWhen()) {
+ found = earliest;
+ } else {
+ next = earliest;
+ }
+ }
+ }
+
+ if (DEBUG) {
+ if (found != null) {
+ Message msg = found.mMessage;
+ Log.d(TAG, "Will deliver node what: " + msg.what + " when: " + msg.when
+ + " seq: " + found.mInsertSeq + " barrier: " + found.isBarrier()
+ + " async: " + found.isAsync() + " now: "
+ + SystemClock.uptimeMillis());
+ } else {
+ Log.d(TAG, "No node to deliver");
+ }
+ if (next != null) {
+ Message msg = next.mMessage;
+ Log.d(TAG, "Next node what: " + msg.what + " when: " + msg.when + " seq: "
+ + next.mInsertSeq + " barrier: " + next.isBarrier() + " async: "
+ + next.isAsync()
+ + " now: " + SystemClock.uptimeMillis());
+ } else {
+ Log.d(TAG, "No next node");
+ }
+ }
+
+ /*
+ * If we have a found message, we will get called again so there's no need to set state.
+ * In that case we can leave our state as ACTIVE.
+ *
+ * Otherwise we should determine how to park the thread.
+ */
+ StateNode nextOp = sStackStateActive;
+ if (found == null) {
+ if (next == null) {
+ /* No message to deliver, sleep indefinitely */
+ mNextPollTimeoutMillis = -1;
+ nextOp = sStackStateParked;
+ if (DEBUG) {
+ Log.d(TAG, "nextMessage next state is StackStateParked");
+ }
+ } else {
+ /* Message not ready, or we found one to deliver already, set a timeout */
+ long nextMessageWhen = next.getWhen();
+ if (nextMessageWhen > now) {
+ mNextPollTimeoutMillis = (int) Math.min(nextMessageWhen - now,
+ Integer.MAX_VALUE);
+ } else {
+ mNextPollTimeoutMillis = 0;
+ }
+
+ mStackStateTimedPark.mWhenToWake = now + mNextPollTimeoutMillis;
+ nextOp = mStackStateTimedPark;
+ if (DEBUG) {
+ Log.d(TAG, "nextMessage next state is StackStateTimedParked timeout ms "
+ + mNextPollTimeoutMillis + " mWhenToWake: "
+ + mStackStateTimedPark.mWhenToWake + " now " + now);
+ }
+ }
+ }
+
+ /*
+ * Try to swap our state from Active back to Park or TimedPark. If we raced with
+ * enqueue, loop back around to pick up any new items.
+ */
+ if (sState.compareAndSet(this, sStackStateActive, nextOp)) {
+ mMessageCounts.clearCounts();
+ if (found != null) {
+ if (!peek && !removeFromPriorityQueue(found)) {
+ /*
+ * RemoveMessages() might be able to pull messages out from under us
+ * However we can detect that here and just loop around if it happens.
+ */
+ continue;
+ }
+
+ if (TRACE) {
+ Trace.setCounter("MQ.Delivered", mMessagesDelivered.incrementAndGet());
+ }
+ return found.mMessage;
+ }
+ return null;
+ }
+ }
+ }
+
+ Message next() {
+ final long ptr = mPtr;
+ if (ptr == 0) {
+ return null;
+ }
+
+ mNextPollTimeoutMillis = 0;
+ int pendingIdleHandlerCount = -1; // -1 only during first iteration
+ while (true) {
+ if (mNextPollTimeoutMillis != 0) {
+ // Binder.flushPendingCommands();
+ }
+
+ mMessageDirectlyQueued = false;
+ ShadowPausedMessageQueue.nativePollOnce(ptr, mNextPollTimeoutMillis);
+
+ Message msg = nextMessage();
+ if (msg != null) {
+ msg.markInUse();
+ return msg;
+ }
+
+ if ((boolean) sQuitting.getVolatile(this)) {
+ return null;
+ }
+
+ synchronized (mIdleHandlersLock) {
+ // If first time idle, then get the number of idlers to run.
+ // Idle handles only run if the queue is empty or if the first message
+ // in the queue (possibly a barrier) is due to be handled in the future.
+ if (pendingIdleHandlerCount < 0
+ && isIdle()) {
+ pendingIdleHandlerCount = mIdleHandlers.size();
+ }
+ if (pendingIdleHandlerCount <= 0) {
+ // No idle handlers to run. Loop and wait some more.
+ continue;
+ }
+
+ if (mPendingIdleHandlers == null) {
+ mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
+ }
+ mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
+ }
+
+ // Run the idle handlers.
+ // We only ever reach this code block during the first iteration.
+ for (int i = 0; i < pendingIdleHandlerCount; i++) {
+ final IdleHandler idler = mPendingIdleHandlers[i];
+ mPendingIdleHandlers[i] = null; // release the reference to the handler
+
+ boolean keep = false;
+ try {
+ keep = idler.queueIdle();
+ } catch (Throwable t) {
+ Log.wtf(TAG, "IdleHandler threw exception", t);
+ }
+
+ if (!keep) {
+ synchronized (mIdleHandlersLock) {
+ mIdleHandlers.remove(idler);
+ }
+ }
+ }
+
+ // Reset the idle handler count to 0 so we do not run them again.
+ pendingIdleHandlerCount = 0;
+
+ // While calling an idle handler, a new message could have been delivered
+ // so go back and look again for a pending message without waiting.
+ mNextPollTimeoutMillis = 0;
+ }
+ }
+
+ void quit(boolean safe) {
+ if (!mQuitAllowed) {
+ throw new IllegalStateException("Main thread not allowed to quit.");
+ }
+ synchronized (mIdleHandlersLock) {
+ if (sQuitting.compareAndSet(this, false, true)) {
+ if (safe) {
+ removeAllFutureMessages();
+ } else {
+ removeAllMessages();
+ }
+
+ // We can assume mPtr != 0 because sQuitting was previously false.
+ ShadowPausedMessageQueue.nativeWake(mPtr);
+ }
+ }
+ }
+
+ boolean enqueueMessage(@NonNull Message msg, long when) {
+ if (msg.target == null) {
+ throw new IllegalArgumentException("Message must have a target.");
+ }
+
+ if (msg.isInUse()) {
+ throw new IllegalStateException(msg + " This message is already in use.");
+ }
+
+ return enqueueMessageUnchecked(msg, when);
+ }
+
+ private boolean enqueueMessageUnchecked(@NonNull Message msg, long when) {
+ if ((boolean) sQuitting.getVolatile(this)) {
+ IllegalStateException e = new IllegalStateException(
+ msg.target + " sending message to a Handler on a dead thread");
+ Log.w(TAG, e.getMessage(), e);
+ msg.recycleUnchecked();
+ return false;
+ }
+
+ long seq = when != 0 ? ((long)sNextInsertSeq.getAndAdd(this, 1L) + 1L)
+ : ((long)sNextFrontInsertSeq.getAndAdd(this, -1L) - 1L);
+ /* TODO: Add a MessageNode member to Message so we can avoid this allocation */
+ MessageNode node = new MessageNode(msg, seq);
+ msg.when = when;
+ msg.markInUse();
+
+ if (DEBUG) {
+ Log.d(TAG, "Insert message what: " + msg.what + " when: " + msg.when + " seq: "
+ + node.mInsertSeq + " barrier: " + node.isBarrier() + " async: "
+ + node.isAsync() + " now: " + SystemClock.uptimeMillis());
+ }
+
+ final Looper myLooper = Looper.myLooper();
+ /* If we are running on the looper thread we can add directly to the priority queue */
+ if (myLooper != null && myLooper.getQueue() == this) {
+ node.removeFromStack();
+ insertIntoPriorityQueue(node);
+ /*
+ * We still need to do this even though we are the current thread,
+ * otherwise next() may sleep indefinitely.
+ */
+ if (!mMessageDirectlyQueued) {
+ mMessageDirectlyQueued = true;
+ ShadowPausedMessageQueue.nativeWake(mPtr);
+ }
+ return true;
+ }
+
+ while (true) {
+ StackNode old = (StackNode) sState.getVolatile(this);
+ boolean wakeNeeded;
+ boolean inactive;
+
+ node.mNext = old;
+ switch (old.getNodeType()) {
+ case STACK_NODE_ACTIVE:
+ /*
+ * The worker thread is currently active and will process any elements added to
+ * the stack before parking again.
+ */
+ node.mBottomOfStack = (StateNode) old;
+ inactive = false;
+ node.mWokeUp = true;
+ wakeNeeded = false;
+ break;
+
+ case STACK_NODE_PARKED:
+ node.mBottomOfStack = (StateNode) old;
+ inactive = true;
+ node.mWokeUp = true;
+ wakeNeeded = true;
+ break;
+
+ case STACK_NODE_TIMEDPARK:
+ node.mBottomOfStack = (StateNode) old;
+ inactive = true;
+ wakeNeeded = mStackStateTimedPark.mWhenToWake >= node.getWhen();
+ node.mWokeUp = wakeNeeded;
+ break;
+
+ default:
+ MessageNode oldMessage = (MessageNode) old;
+
+ node.mBottomOfStack = oldMessage.mBottomOfStack;
+ int bottomType = node.mBottomOfStack.getNodeType();
+ inactive = bottomType >= STACK_NODE_PARKED;
+ wakeNeeded = (bottomType == STACK_NODE_TIMEDPARK
+ && mStackStateTimedPark.mWhenToWake >= node.getWhen()
+ && !oldMessage.mWokeUp);
+ node.mWokeUp = oldMessage.mWokeUp || wakeNeeded;
+ break;
+ }
+ if (sState.compareAndSet(this, old, node)) {
+ if (inactive) {
+ if (wakeNeeded) {
+ ShadowPausedMessageQueue.nativeWake(mPtr);
+ } else {
+ mMessageCounts.incrementQueued();
+ }
+ }
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Posts a synchronization barrier to the Looper's message queue.
+ *
+ * Message processing occurs as usual until the message queue encounters the
+ * synchronization barrier that has been posted. When the barrier is encountered,
+ * later synchronous messages in the queue are stalled (prevented from being executed)
+ * until the barrier is released by calling {@link #removeSyncBarrier} and specifying
+ * the token that identifies the synchronization barrier.
+ *
+ * This method is used to immediately postpone execution of all subsequently posted
+ * synchronous messages until a condition is met that releases the barrier.
+ * Asynchronous messages (see {@link Message#isAsynchronous} are exempt from the barrier
+ * and continue to be processed as usual.
+ *
+ * This call must be always matched by a call to {@link #removeSyncBarrier} with
+ * the same token to ensure that the message queue resumes normal operation.
+ * Otherwise the application will probably hang!
+ *
+ * @return A token that uniquely identifies the barrier. This token must be
+ * passed to {@link #removeSyncBarrier} to release the barrier.
+ *
+ * @hide
+ */
+ @TestApi
+ public int postSyncBarrier() {
+ return postSyncBarrier(SystemClock.uptimeMillis());
+ }
+
+ private int postSyncBarrier(long when) {
+ final int token = mNextBarrierToken.getAndIncrement();
+ final Message msg = Message.obtain();
+
+ msg.markInUse();
+ msg.arg1 = token;
+
+ if (!enqueueMessageUnchecked(msg, when)) {
+ Log.wtf(TAG, "Unexpected error while adding sync barrier!");
+ return -1;
+ }
+
+ return token;
+ }
+
+ private static final class MatchBarrierToken extends MessageCompare {
+ int mBarrierToken;
+
+ MatchBarrierToken(int token) {
+ super();
+ mBarrierToken = token;
+ }
+
+ @Override
+ public boolean compareMessage(MessageNode n, Handler h, int what, Object object,
+ Runnable r, long when) {
+ final Message m = n.mMessage;
+ if (m.target == null && m.arg1 == mBarrierToken) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Removes a synchronization barrier.
+ *
+ * @param token The synchronization barrier token that was returned by
+ * {@link #postSyncBarrier}.
+ *
+ * @throws IllegalStateException if the barrier was not found.
+ *
+ * @hide
+ */
+ @TestApi
+ public void removeSyncBarrier(int token) {
+ boolean removed;
+ MessageNode first;
+ final MatchBarrierToken matchBarrierToken = new MatchBarrierToken(token);
+
+ try {
+ /* Retain the first element to see if we are currently stuck on a barrier. */
+ first = mPriorityQueue.first();
+ } catch (NoSuchElementException e) {
+ /* The queue is empty */
+ first = null;
+ }
+
+ removed = findOrRemoveMessages(null, 0, null, null, 0, matchBarrierToken, true);
+ if (removed && first != null) {
+ Message m = first.mMessage;
+ if (m.target == null && m.arg1 == token) {
+ /* Wake up next() in case it was sleeping on this barrier. */
+ ShadowPausedMessageQueue.nativeWake(mPtr);
+ }
+ } else if (!removed) {
+ throw new IllegalStateException("The specified message queue synchronization "
+ + " barrier token has not been posted or has already been removed.");
+ }
+ }
+
+ private static final class MatchEarliestMessage extends MessageCompare {
+ MessageNode mEarliest = null;
+
+ @Override
+ public boolean compareMessage(MessageNode n, Handler h, int what, Object object,
+ Runnable r, long when) {
+ final Message m = n.mMessage;
+ if (mEarliest == null || mEarliest.mMessage.when > m.when) {
+ mEarliest = n;
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Get the timestamp of the next executable message in our priority queue.
+ * Returns null if there are no messages ready for delivery.
+ *
+ * Caller must ensure that this doesn't race 'next' from the Looper thread.
+ */
+ Long peekWhenForTest() {
+ throwIfNotTest();
+ Message ret = nextMessage(true);
+ return ret != null ? ret.when : null;
+ }
+
+ /**
+ * Return the next executable message in our priority queue.
+ * Returns null if there are no messages ready for delivery
+ *
+ * Caller must ensure that this doesn't race 'next' from the Looper thread.
+ */
+ Message pollForTest() {
+ throwIfNotTest();
+ return nextMessage(false);
+ }
+
+ /**
+ * @return true if we are blocked on a sync barrier
+ */
+ boolean isBlockedOnSyncBarrier() {
+ throwIfNotTest();
+ Iterator queueIter = mPriorityQueue.iterator();
+ MessageNode queueNode = iterateNext(queueIter);
+
+ if (queueNode.isBarrier()) {
+ long now = SystemClock.uptimeMillis();
+
+ /* Look for a deliverable async node. If one exists we are not blocked. */
+ Iterator asyncQueueIter = mAsyncPriorityQueue.iterator();
+ MessageNode asyncNode = iterateNext(asyncQueueIter);
+ if (asyncNode != null && now >= asyncNode.getWhen()) {
+ return false;
+ }
+ /*
+ * Look for a deliverable sync node. In this case, if one exists we are blocked
+ * since the barrier prevents delivery of the Message.
+ */
+ while (queueNode.isBarrier()) {
+ queueNode = iterateNext(queueIter);
+ }
+ if (queueNode != null && now >= queueNode.getWhen()) {
+ return true;
+ }
+ }
+
+ // TODO: Suwayomi moved this outside if, there was no return?
+ return false;
+ }
+
+ private StateNode getStateNode(StackNode node) {
+ if (node.isMessageNode()) {
+ return ((MessageNode) node).mBottomOfStack;
+ }
+ return (StateNode) node;
+ }
+
+ private void waitForDrainCompleted() {
+ mDrainingLock.lock();
+ while (mNextIsDrainingStack) {
+ mDrainCompleted.awaitUninterruptibly();
+ }
+ mDrainingLock.unlock();
+ }
+
+ /*
+ * This class is used to find matches for hasMessages() and removeMessages()
+ */
+ private abstract static class MessageCompare {
+ public abstract boolean compareMessage(MessageNode n, Handler h, int what, Object object,
+ Runnable r, long when);
+ }
+
+ private boolean stackHasMessages(Handler h, int what, Object object, Runnable r, long when,
+ MessageCompare compare, boolean removeMatches) {
+ boolean found = false;
+ StackNode top = (StackNode) sState.getVolatile(this);
+ StateNode bottom = getStateNode(top);
+
+ /*
+ * If the top node is a state node, there are no reachable messages.
+ * If it's anything other than Active, we can quit as we know that next() is not
+ * consuming items.
+ * If the top node is Active then we know that next() is currently consuming items.
+ * In that case we should wait next() has drained the stack.
+ */
+ if (top == bottom) {
+ if (bottom != sStackStateActive) {
+ return false;
+ }
+ waitForDrainCompleted();
+ return false;
+ }
+
+ /*
+ * We have messages that we may tombstone. Walk the stack until we hit the bottom or we
+ * hit a null pointer.
+ * If we hit the bottom, we are done.
+ * If we hit a null pointer, then the stack is being consumed by next() and we must cycle
+ * until the stack has been drained.
+ */
+ MessageNode p = (MessageNode) top;
+
+ while (true) {
+ if (compare.compareMessage(p, h, what, object, r, when)) {
+ found = true;
+ if (DEBUG) {
+ Log.w(TAG, "stackHasMessages node matches");
+ }
+ if (removeMatches) {
+ if (p.removeFromStack()) {
+ p.mMessage.recycleUnchecked();
+ if (mMessageCounts.incrementCancelled()) {
+ ShadowPausedMessageQueue.nativeWake(mPtr);
+ }
+ }
+ } else {
+ return true;
+ }
+ }
+
+ StackNode n = p.mNext;
+ if (n == null) {
+ /* Next() is walking the stack, we must re-sample */
+ if (DEBUG) {
+ Log.d(TAG, "stackHasMessages next() is walking the stack, we must re-sample");
+ }
+ waitForDrainCompleted();
+ break;
+ }
+ if (!n.isMessageNode()) {
+ /* We reached the end of the stack */
+ return found;
+ }
+ p = (MessageNode) n;
+ }
+
+ return found;
+ }
+
+ private boolean priorityQueueHasMessage(ConcurrentSkipListSet queue, Handler h,
+ int what, Object object, Runnable r, long when, MessageCompare compare,
+ boolean removeMatches) {
+ Iterator iterator = queue.iterator();
+ boolean found = false;
+
+ while (iterator.hasNext()) {
+ MessageNode msg = iterator.next();
+
+ if (compare.compareMessage(msg, h, what, object, r, when)) {
+ if (removeMatches) {
+ found = true;
+ if (queue.remove(msg)) {
+ msg.mMessage.recycleUnchecked();
+ }
+ } else {
+ return true;
+ }
+ }
+ }
+ return found;
+ }
+
+ private boolean findOrRemoveMessages(Handler h, int what, Object object, Runnable r, long when,
+ MessageCompare compare, boolean removeMatches) {
+ boolean foundInStack, foundInQueue;
+
+ foundInStack = stackHasMessages(h, what, object, r, when, compare, removeMatches);
+ foundInQueue = priorityQueueHasMessage(mPriorityQueue, h, what, object, r, when, compare,
+ removeMatches);
+ foundInQueue |= priorityQueueHasMessage(mAsyncPriorityQueue, h, what, object, r, when,
+ compare, removeMatches);
+
+ return foundInStack || foundInQueue;
+ }
+
+ private static final class MatchHandlerWhatAndObject extends MessageCompare {
+ @Override
+ public boolean compareMessage(MessageNode n, Handler h, int what, Object object,
+ Runnable r, long when) {
+ final Message m = n.mMessage;
+ if (m.target == h && m.what == what && (object == null || m.obj == object)) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private final MatchHandlerWhatAndObject mMatchHandlerWhatAndObject =
+ new MatchHandlerWhatAndObject();
+ boolean hasMessages(Handler h, int what, Object object) {
+ if (h == null) {
+ return false;
+ }
+
+ return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject, false);
+ }
+
+ private static final class MatchHandlerWhatAndObjectEquals extends MessageCompare {
+ @Override
+ public boolean compareMessage(MessageNode n, Handler h, int what, Object object, Runnable r,
+ long when) {
+ final Message m = n.mMessage;
+ if (m.target == h && m.what == what && (object == null || object.equals(m.obj))) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private final MatchHandlerWhatAndObjectEquals mMatchHandlerWhatAndObjectEquals =
+ new MatchHandlerWhatAndObjectEquals();
+ boolean hasEqualMessages(Handler h, int what, Object object) {
+ if (h == null) {
+ return false;
+ }
+
+ return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals,
+ false);
+ }
+
+ private static final class MatchHandlerRunnableAndObject extends MessageCompare {
+ @Override
+ public boolean compareMessage(MessageNode n, Handler h, int what, Object object,
+ Runnable r, long when) {
+ final Message m = n.mMessage;
+ if (m.target == h && m.callback == r && (object == null || m.obj == object)) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private final MatchHandlerRunnableAndObject mMatchHandlerRunnableAndObject =
+ new MatchHandlerRunnableAndObject();
+
+ boolean hasMessages(Handler h, Runnable r, Object object) {
+ if (h == null) {
+ return false;
+ }
+
+ return findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, false);
+ }
+
+ private static final class MatchHandler extends MessageCompare {
+ @Override
+ public boolean compareMessage(MessageNode n, Handler h, int what, Object object,
+ Runnable r, long when) {
+ final Message m = n.mMessage;
+ if (m.target == h) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private final MatchHandler mMatchHandler = new MatchHandler();
+ boolean hasMessages(Handler h) {
+ if (h == null) {
+ return false;
+ }
+ return findOrRemoveMessages(h, -1, null, null, 0, mMatchHandler, false);
+ }
+
+ void removeMessages(Handler h, int what, Object object) {
+ if (h == null) {
+ return;
+ }
+ findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject, true);
+ }
+
+ void removeEqualMessages(Handler h, int what, Object object) {
+ if (h == null) {
+ return;
+ }
+ findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals, true);
+ }
+
+ void removeMessages(Handler h, Runnable r, Object object) {
+ if (h == null || r == null) {
+ return;
+ }
+ findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, true);
+ }
+
+ private static final class MatchHandlerRunnableAndObjectEquals extends MessageCompare {
+ @Override
+ public boolean compareMessage(MessageNode n, Handler h, int what, Object object,
+ Runnable r, long when) {
+ final Message m = n.mMessage;
+ if (m.target == h && m.callback == r && (object == null || object.equals(m.obj))) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private final MatchHandlerRunnableAndObjectEquals mMatchHandlerRunnableAndObjectEquals =
+ new MatchHandlerRunnableAndObjectEquals();
+ void removeEqualMessages(Handler h, Runnable r, Object object) {
+ if (h == null || r == null) {
+ return;
+ }
+ findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObjectEquals, true);
+ }
+
+ private static final class MatchHandlerAndObject extends MessageCompare {
+ @Override
+ public boolean compareMessage(MessageNode n, Handler h, int what, Object object,
+ Runnable r, long when) {
+ final Message m = n.mMessage;
+ if (m.target == h && (object == null || m.obj == object)) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private final MatchHandlerAndObject mMatchHandlerAndObject = new MatchHandlerAndObject();
+ void removeCallbacksAndMessages(Handler h, Object object) {
+ if (h == null) {
+ return;
+ }
+ findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObject, true);
+ }
+
+ private static final class MatchHandlerAndObjectEquals extends MessageCompare {
+ @Override
+ public boolean compareMessage(MessageNode n, Handler h, int what, Object object,
+ Runnable r, long when) {
+ final Message m = n.mMessage;
+ if (m.target == h && (object == null || object.equals(m.obj))) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private final MatchHandlerAndObjectEquals mMatchHandlerAndObjectEquals =
+ new MatchHandlerAndObjectEquals();
+ void removeCallbacksAndEqualMessages(Handler h, Object object) {
+ if (h == null) {
+ return;
+ }
+ findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObjectEquals, true);
+ }
+
+ private static final class MatchAllMessages extends MessageCompare {
+ @Override
+ public boolean compareMessage(MessageNode n, Handler h, int what, Object object,
+ Runnable r, long when) {
+ return true;
+ }
+ }
+ private final MatchAllMessages mMatchAllMessages = new MatchAllMessages();
+ private void removeAllMessages() {
+ findOrRemoveMessages(null, -1, null, null, 0, mMatchAllMessages, true);
+ }
+
+ private static final class MatchAllFutureMessages extends MessageCompare {
+ @Override
+ public boolean compareMessage(MessageNode n, Handler h, int what, Object object,
+ Runnable r, long when) {
+ final Message m = n.mMessage;
+ if (m.when > when) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private final MatchAllFutureMessages mMatchAllFutureMessages = new MatchAllFutureMessages();
+ private void removeAllFutureMessages() {
+ findOrRemoveMessages(null, -1, null, null, SystemClock.uptimeMillis(),
+ mMatchAllFutureMessages, true);
+ }
+
+ private void printPriorityQueueNodes() {
+ Iterator iterator = mPriorityQueue.iterator();
+
+ Log.d(TAG, "* Dump priority queue");
+ while (iterator.hasNext()) {
+ MessageNode msgNode = iterator.next();
+ Log.d(TAG, "** MessageNode what: " + msgNode.mMessage.what + " when "
+ + msgNode.mMessage.when + " seq: " + msgNode.mInsertSeq);
+ }
+ }
+
+ private int dumpPriorityQueue(ConcurrentSkipListSet queue, Printer pw,
+ String prefix, Handler h, int n) {
+ int count = 0;
+ long now = SystemClock.uptimeMillis();
+
+ for (MessageNode msgNode : queue) {
+ Message msg = msgNode.mMessage;
+ if (h == null || h == msg.target) {
+ pw.println(prefix + "Message " + (n + count) + ": " + msg.toString(now));
+ }
+ count++;
+ }
+ return count;
+ }
+
+ /**
+ * Adds a file descriptor listener to receive notification when file descriptor
+ * related events occur.
+ *
+ * If the file descriptor has already been registered, the specified events
+ * and listener will replace any that were previously associated with it.
+ * It is not possible to set more than one listener per file descriptor.
+ *
+ * It is important to always unregister the listener when the file descriptor
+ * is no longer of use.
+ *
+ *
+ * @param fd The file descriptor for which a listener will be registered.
+ * @param events The set of events to receive: a combination of the
+ * {@link OnFileDescriptorEventListener#EVENT_INPUT},
+ * {@link OnFileDescriptorEventListener#EVENT_OUTPUT}, and
+ * {@link OnFileDescriptorEventListener#EVENT_ERROR} event masks. If the requested
+ * set of events is zero, then the listener is unregistered.
+ * @param listener The listener to invoke when file descriptor events occur.
+ *
+ * @see OnFileDescriptorEventListener
+ * @see #removeOnFileDescriptorEventListener
+ */
+ public void addOnFileDescriptorEventListener(@NonNull FileDescriptor fd,
+ @OnFileDescriptorEventListener.Events int events,
+ @NonNull OnFileDescriptorEventListener listener) {
+ if (fd == null) {
+ throw new IllegalArgumentException("fd must not be null");
+ }
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+
+ synchronized (mFileDescriptorRecordsLock) {
+ updateOnFileDescriptorEventListenerLocked(fd, events, listener);
+ }
+ }
+
+ /**
+ * Removes a file descriptor listener.
+ *
+ * This method does nothing if no listener has been registered for the
+ * specified file descriptor.
+ *
+ *
+ * @param fd The file descriptor whose listener will be unregistered.
+ *
+ * @see OnFileDescriptorEventListener
+ * @see #addOnFileDescriptorEventListener
+ */
+ public void removeOnFileDescriptorEventListener(@NonNull FileDescriptor fd) {
+ if (fd == null) {
+ throw new IllegalArgumentException("fd must not be null");
+ }
+
+ synchronized (mFileDescriptorRecordsLock) {
+ updateOnFileDescriptorEventListenerLocked(fd, 0, null);
+ }
+ }
+
+ private void updateOnFileDescriptorEventListenerLocked(FileDescriptor fd, int events,
+ OnFileDescriptorEventListener listener) {
+ throw new RuntimeException("Stub!");
+ // final int fdNum = fd.getInt$();
+
+ // int index = -1;
+ // FileDescriptorRecord record = null;
+ // if (mFileDescriptorRecords != null) {
+ // index = mFileDescriptorRecords.indexOfKey(fdNum);
+ // if (index >= 0) {
+ // record = mFileDescriptorRecords.valueAt(index);
+ // if (record != null && record.mEvents == events) {
+ // return;
+ // }
+ // }
+ // }
+
+ // if (events != 0) {
+ // events |= OnFileDescriptorEventListener.EVENT_ERROR;
+ // if (record == null) {
+ // if (mFileDescriptorRecords == null) {
+ // mFileDescriptorRecords = new SparseArray();
+ // }
+ // record = new FileDescriptorRecord(fd, events, listener);
+ // mFileDescriptorRecords.put(fdNum, record);
+ // } else {
+ // record.mListener = listener;
+ // record.mEvents = events;
+ // record.mSeq += 1;
+ // }
+ // nativeSetFileDescriptorEvents(mPtr, fdNum, events);
+ // } else if (record != null) {
+ // record.mEvents = 0;
+ // mFileDescriptorRecords.removeAt(index);
+ // nativeSetFileDescriptorEvents(mPtr, fdNum, 0);
+ // }
+ }
+
+ // Called from native code.
+ private int dispatchEvents(int fd, int events) {
+ // Get the file descriptor record and any state that might change.
+ final FileDescriptorRecord record;
+ final int oldWatchedEvents;
+ final OnFileDescriptorEventListener listener;
+ final int seq;
+ synchronized (mFileDescriptorRecordsLock) {
+ record = mFileDescriptorRecords.get(fd);
+ if (record == null) {
+ return 0; // spurious, no listener registered
+ }
+
+ oldWatchedEvents = record.mEvents;
+ events &= oldWatchedEvents; // filter events based on current watched set
+ if (events == 0) {
+ return oldWatchedEvents; // spurious, watched events changed
+ }
+
+ listener = record.mListener;
+ seq = record.mSeq;
+ }
+
+ // Invoke the listener outside of the lock.
+ int newWatchedEvents = listener.onFileDescriptorEvents(
+ record.mDescriptor, events);
+ if (newWatchedEvents != 0) {
+ newWatchedEvents |= OnFileDescriptorEventListener.EVENT_ERROR;
+ }
+
+ // Update the file descriptor record if the listener changed the set of
+ // events to watch and the listener itself hasn't been updated since.
+ if (newWatchedEvents != oldWatchedEvents) {
+ synchronized (mFileDescriptorRecordsLock) {
+ int index = mFileDescriptorRecords.indexOfKey(fd);
+ if (index >= 0 && mFileDescriptorRecords.valueAt(index) == record
+ && record.mSeq == seq) {
+ record.mEvents = newWatchedEvents;
+ if (newWatchedEvents == 0) {
+ mFileDescriptorRecords.removeAt(index);
+ }
+ }
+ }
+ }
+
+ // Return the new set of events to watch for native code to take care of.
+ return newWatchedEvents;
+ }
+
+ /**
+ * Callback interface for discovering when a thread is going to block
+ * waiting for more messages.
+ */
+ public static interface IdleHandler {
+ /**
+ * Called when the message queue has run out of messages and will now
+ * wait for more. Return true to keep your idle handler active, false
+ * to have it removed. This may be called if there are still messages
+ * pending in the queue, but they are all scheduled to be dispatched
+ * after the current time.
+ */
+ boolean queueIdle();
+ }
+
+ /**
+ * A listener which is invoked when file descriptor related events occur.
+ */
+ public interface OnFileDescriptorEventListener {
+ /**
+ * File descriptor event: Indicates that the file descriptor is ready for input
+ * operations, such as reading.
+ *
+ * The listener should read all available data from the file descriptor
+ * then return true to keep the listener active or false
+ * to remove the listener.
+ *
+ * In the case of a socket, this event may be generated to indicate
+ * that there is at least one incoming connection that the listener
+ * should accept.
+ *
+ * This event will only be generated if the {@link #EVENT_INPUT} event mask was
+ * specified when the listener was added.
+ *
+ */
+ public static final int EVENT_INPUT = 1 << 0;
+
+ /**
+ * File descriptor event: Indicates that the file descriptor is ready for output
+ * operations, such as writing.
+ *
+ * The listener should write as much data as it needs. If it could not
+ * write everything at once, then it should return true to
+ * keep the listener active. Otherwise, it should return false
+ * to remove the listener then re-register it later when it needs to write
+ * something else.
+ *
+ * This event will only be generated if the {@link #EVENT_OUTPUT} event mask was
+ * specified when the listener was added.
+ *
+ */
+ public static final int EVENT_OUTPUT = 1 << 1;
+
+ /**
+ * File descriptor event: Indicates that the file descriptor encountered a
+ * fatal error.
+ *
+ * File descriptor errors can occur for various reasons. One common error
+ * is when the remote peer of a socket or pipe closes its end of the connection.
+ *
+ * This event may be generated at any time regardless of whether the
+ * {@link #EVENT_ERROR} event mask was specified when the listener was added.
+ *
+ */
+ public static final int EVENT_ERROR = 1 << 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "EVENT_" }, value = {
+ EVENT_INPUT,
+ EVENT_OUTPUT,
+ EVENT_ERROR
+ })
+ public @interface Events {}
+
+ /**
+ * Called when a file descriptor receives events.
+ *
+ * @param fd The file descriptor.
+ * @param events The set of events that occurred: a combination of the
+ * {@link #EVENT_INPUT}, {@link #EVENT_OUTPUT}, and {@link #EVENT_ERROR} event masks.
+ * @return The new set of events to watch, or 0 to unregister the listener.
+ *
+ * @see #EVENT_INPUT
+ * @see #EVENT_OUTPUT
+ * @see #EVENT_ERROR
+ */
+ @Events int onFileDescriptorEvents(@NonNull FileDescriptor fd, @Events int events);
+ }
+
+ static final class FileDescriptorRecord {
+ public final FileDescriptor mDescriptor;
+ public int mEvents;
+ public OnFileDescriptorEventListener mListener;
+ public int mSeq;
+
+ public FileDescriptorRecord(FileDescriptor descriptor,
+ int events, OnFileDescriptorEventListener listener) {
+ mDescriptor = descriptor;
+ mEvents = events;
+ mListener = listener;
+ }
+ }
+}
diff --git a/AndroidCompat/src/main/java/android/os/ThreadLocalWorkSource.java b/AndroidCompat/src/main/java/android/os/ThreadLocalWorkSource.java
new file mode 100644
index 00000000..e9adb209
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/os/ThreadLocalWorkSource.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * Tracks who triggered the work currently executed on this thread.
+ *
+ * ThreadLocalWorkSource is automatically updated inside system server for incoming/outgoing
+ * binder calls and messages posted to handler threads.
+ *
+ *
ThreadLocalWorkSource can also be set manually if needed to refine the WorkSource.
+ *
+ *
Example:
+ *
+ * - Bluetooth process calls {@link PowerManager#isInteractive()} API on behalf of app foo.
+ *
- ThreadLocalWorkSource will be automatically set to the UID of foo.
+ *
- Any code on the thread handling {@link PowerManagerService#isInteractive()} can call
+ * {@link ThreadLocalWorkSource#getUid()} to blame any resource used to handle this call.
+ *
- If a message is posted from the binder thread, the code handling the message can also call
+ * {@link ThreadLocalWorkSource#getUid()} and it will return the UID of foo since the work source is
+ * automatically propagated.
+ *
+ *
+ * @hide Only for use within system server.
+ */
+public final class ThreadLocalWorkSource {
+ public static final int UID_NONE = Message.UID_NONE;
+ private static final ThreadLocal sWorkSourceUid =
+ ThreadLocal.withInitial(() -> new int[] {UID_NONE});
+
+ /**
+ * Returns the UID to blame for the code currently executed on this thread.
+ *
+ * This UID is set automatically by common frameworks (e.g. Binder and Handler frameworks)
+ * and automatically propagated inside system server.
+ *
It can also be set manually using {@link #setUid(int)}.
+ */
+ public static int getUid() {
+ return sWorkSourceUid.get()[0];
+ }
+
+ /**
+ * Sets the UID to blame for the code currently executed on this thread.
+ *
+ *
Inside system server, this UID will be automatically propagated.
+ *
It will be used to attribute future resources used on this thread (e.g. binder
+ * transactions or processing handler messages) and on any other threads the UID is propagated
+ * to.
+ *
+ * @return a token that can be used to restore the state.
+ */
+ public static long setUid(int uid) {
+ final long token = getToken();
+ sWorkSourceUid.get()[0] = uid;
+ return token;
+ }
+
+ /**
+ * Restores the state using the provided token.
+ */
+ public static void restore(long token) {
+ sWorkSourceUid.get()[0] = parseUidFromToken(token);
+ }
+
+ /**
+ * Clears the stored work source uid.
+ *
+ *
This method should be used when we do not know who to blame. If the UID to blame is the
+ * UID of the current process, it is better to attribute the work to the current process
+ * explicitly instead of clearing the work source:
+ *
+ *
+ * ThreadLocalWorkSource.setUid(Process.myUid());
+ *
+ *
+ * @return a token that can be used to restore the state.
+ */
+ public static long clear() {
+ return setUid(UID_NONE);
+ }
+
+ private static int parseUidFromToken(long token) {
+ return (int) token;
+ }
+
+ private static long getToken() {
+ return sWorkSourceUid.get()[0];
+ }
+
+ private ThreadLocalWorkSource() {
+ }
+}
diff --git a/AndroidCompat/src/main/java/android/os/shadows/NativeObjRegistry.java b/AndroidCompat/src/main/java/android/os/shadows/NativeObjRegistry.java
new file mode 100644
index 00000000..343805dc
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/os/shadows/NativeObjRegistry.java
@@ -0,0 +1,168 @@
+package android.os.shadows;
+// package org.robolectric.res.android;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A unique id per object registry. Used to emulate android platform behavior of storing a long
+ * which represents a pointer to an object.
+ */
+public class NativeObjRegistry {
+
+ private static final int INITIAL_ID = 1;
+
+ private final String name;
+ private final boolean debug;
+ private final HashMap nativeObjToIdMap = new HashMap();
+ private final Map idToDebugInfoMap;
+
+ private long nextId = INITIAL_ID;
+
+ public NativeObjRegistry(Class theClass) {
+ this(theClass, false);
+ }
+
+ public NativeObjRegistry(Class theClass, boolean debug) {
+ this(theClass.getSimpleName(), debug);
+ }
+
+ public NativeObjRegistry(String name) {
+ this(name, false);
+ }
+
+ public NativeObjRegistry(String name, boolean debug) {
+ this.name = name;
+ this.debug = debug;
+ this.idToDebugInfoMap = debug ? new HashMap<>() : null;
+ }
+
+ private Long getNativeObjectId(T o) {
+ for(Map.Entry entry : nativeObjToIdMap.entrySet()) {
+ if (o == entry.getValue())
+ return entry.getKey();
+ }
+ return null;
+ }
+
+ /**
+ * Register and assign a new unique native id for given object (representing a C memory pointer).
+ *
+ * @throws IllegalStateException if the object was previously registered
+ */
+ public synchronized long register(T o) {
+ if (o == null)
+ throw new IllegalStateException("Object must not be null");
+ Long nativeId = getNativeObjectId(o);
+ if (nativeId != null) {
+ if (debug) {
+ DebugInfo debugInfo = idToDebugInfoMap.get(nativeId);
+ if (debugInfo != null) {
+ System.out.printf(
+ "NativeObjRegistry %s: register %d -> %s already registered:%n", name, nativeId, o);
+ debugInfo.registrationTrace.printStackTrace(System.out);
+ }
+ }
+ throw new IllegalStateException("Object was previously registered with id " + nativeId);
+ }
+
+ nativeId = nextId;
+ if (debug) {
+ System.out.printf("NativeObjRegistry %s: register %d -> %s%n", name, nativeId, o);
+ idToDebugInfoMap.put(nativeId, new DebugInfo(new Trace()));
+ }
+ nativeObjToIdMap.put(nativeId, o);
+ nextId++;
+ return nativeId;
+ }
+
+ /**
+ * Unregister an object previously registered with {@link #register(Object)}.
+ *
+ * @param nativeId the unique id (representing a C memory pointer) of the object to unregister.
+ * @throws IllegalStateException if the object was never registered, or was previously
+ * unregistered.
+ */
+ public synchronized T unregister(long nativeId) {
+ T o = nativeObjToIdMap.remove(nativeId);
+ if (debug) {
+ System.out.printf("NativeObjRegistry %s: unregister %d -> %s%n", name, nativeId, o);
+ new RuntimeException("unregister debug").printStackTrace(System.out);
+ }
+ if (o == null) {
+ if (debug) {
+ DebugInfo debugInfo = idToDebugInfoMap.get(nativeId);
+ debugInfo.unregistrationTraces.add(new Trace());
+ if (debugInfo.unregistrationTraces.size() > 1) {
+ System.out.format("NativeObjRegistry %s: Too many unregistrations:%n", name);
+ for (Trace unregistration : debugInfo.unregistrationTraces) {
+ unregistration.printStackTrace(System.out);
+ }
+ }
+ }
+ throw new IllegalStateException(
+ nativeId + " has already been removed (or was never registered)");
+ }
+ return o;
+ }
+
+ /** Retrieve the native object for given id. Throws if object with that id cannot be found */
+ public synchronized T getNativeObject(long nativeId) {
+ T object = nativeObjToIdMap.get(nativeId);
+ if (object != null) {
+ return object;
+ } else {
+ throw new NullPointerException(
+ String.format(
+ "Could not find object with nativeId: %d. Currently registered ids: %s",
+ nativeId, nativeObjToIdMap.keySet()));
+ }
+ }
+
+ /**
+ * Updates the native object for the given id.
+ *
+ * @throws IllegalStateException if no object was registered with the given id before
+ */
+ public synchronized void update(long nativeId, T o) {
+ T previous = nativeObjToIdMap.get(nativeId);
+ if (previous == null) {
+ throw new IllegalStateException("Native id " + nativeId + " was never registered");
+ }
+ if (debug) {
+ System.out.printf("NativeObjRegistry %s: update %d -> %s%n", name, nativeId, o);
+ idToDebugInfoMap.put(nativeId, new DebugInfo(new Trace()));
+ }
+ nativeObjToIdMap.put(nativeId, o);
+ }
+
+ /**
+ * Similar to {@link #getNativeObject(long)} but returns null if object with given id cannot be
+ * found.
+ */
+ public synchronized T peekNativeObject(long nativeId) {
+ return nativeObjToIdMap.get(nativeId);
+ }
+
+ /** WARNING -- dangerous! Call {@link #unregister(long)} instead! */
+ public synchronized void clear() {
+ nextId = INITIAL_ID;
+ nativeObjToIdMap.clear();
+ }
+
+ private static class DebugInfo {
+ final Trace registrationTrace;
+ final List unregistrationTraces = new ArrayList<>();
+
+ public DebugInfo(Trace trace) {
+ registrationTrace = trace;
+ }
+ }
+
+ private static class Trace extends Throwable {
+
+ private Trace() {}
+ }
+}
diff --git a/AndroidCompat/src/main/java/android/os/shadows/ShadowPausedMessageQueue.java b/AndroidCompat/src/main/java/android/os/shadows/ShadowPausedMessageQueue.java
new file mode 100644
index 00000000..39f1acc5
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/os/shadows/ShadowPausedMessageQueue.java
@@ -0,0 +1,73 @@
+package android.os.shadows;
+// package org.robolectric.shadows;
+// and badly gutted
+
+import android.os.Looper;
+import android.os.Message;
+import android.os.MessageQueue;
+import android.os.MessageQueue.IdleHandler;
+import android.os.SystemClock;
+import android.util.Log;
+import java.time.Duration;
+import java.util.ArrayList;
+
+/**
+ * The shadow {@link} MessageQueue} for {@link LooperMode.Mode.PAUSED}
+ *
+ * This class should not be referenced directly. Use {@link ShadowMessageQueue} instead.
+ */
+@SuppressWarnings("SynchronizeOnNonFinalField")
+public class ShadowPausedMessageQueue {
+
+ // just use this class as the native object
+ private static NativeObjRegistry nativeQueueRegistry =
+ new NativeObjRegistry(ShadowPausedMessageQueue.class);
+ private boolean isPolling = false;
+ private Exception uncaughtException = null;
+
+ // shadow constructor instead of nativeInit because nativeInit signature has changed across SDK
+ // versions
+ public static long nativeInit() {
+ return nativeQueueRegistry.register(new ShadowPausedMessageQueue());
+ }
+
+ public static void nativeDestroy(long ptr) {
+ nativeQueueRegistry.unregister(ptr);
+ }
+
+ public static void nativePollOnce(long ptr, int timeoutMillis) {
+ ShadowPausedMessageQueue obj = nativeQueueRegistry.getNativeObject(ptr);
+ obj.nativePollOnce(timeoutMillis);
+ }
+
+ public void nativePollOnce(int timeoutMillis) {
+ if (timeoutMillis == 0) {
+ return;
+ }
+ synchronized (this) {
+ isPolling = true;
+ try {
+ if (timeoutMillis < 0) {
+ this.wait();
+ } else {
+ this.wait(timeoutMillis);
+ }
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ isPolling = false;
+ }
+ }
+
+ public static void nativeWake(long ptr) {
+ ShadowPausedMessageQueue obj = nativeQueueRegistry.getNativeObject(ptr);
+ synchronized (obj) {
+ obj.notifyAll();
+ }
+ }
+
+ public static boolean nativeIsPolling(long ptr) {
+ return nativeQueueRegistry.getNativeObject(ptr).isPolling;
+ }
+}
+
diff --git a/AndroidCompat/src/main/java/android/util/Log.java b/AndroidCompat/src/main/java/android/util/Log.java
index 03314a9c..1cbc90a7 100644
--- a/AndroidCompat/src/main/java/android/util/Log.java
+++ b/AndroidCompat/src/main/java/android/util/Log.java
@@ -136,4 +136,4 @@ public final class Log {
first.append(msg);
return first.toString();
}
-}
\ No newline at end of file
+}
diff --git a/AndroidCompat/src/main/java/android/util/Slog.java b/AndroidCompat/src/main/java/android/util/Slog.java
new file mode 100644
index 00000000..78e6cae9
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/util/Slog.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Build;
+
+/**
+ * API for sending log output to the {@link Log#LOG_ID_SYSTEM} buffer.
+ *
+ * Should be used by system components. Use {@code adb logcat --buffer=system} to fetch the logs.
+ *
+ * @see Log
+ * @hide
+ */
+public final class Slog {
+
+ private Slog() {
+ }
+
+ /**
+ * Logs {@code msg} at {@link Log#VERBOSE} level.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param msg the message to log.
+ *
+ * @see Log#v(String, String)
+ */
+ public static int v(@Nullable String tag, @NonNull String msg) {
+ return Log.println(Log.VERBOSE, tag, msg);
+ }
+
+ /**
+ * Logs {@code msg} at {@link Log#VERBOSE} level, attaching stack trace of the {@code tr} to
+ * the end of the log statement.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param msg the message to log.
+ * @param tr an exception to log.
+ *
+ * @see Log#v(String, String, Throwable)
+ */
+ public static int v(@Nullable String tag, @NonNull String msg, @Nullable Throwable tr) {
+ return Log.println(Log.VERBOSE, tag,
+ msg + '\n' + Log.getStackTraceString(tr));
+ }
+
+ /**
+ * Logs {@code msg} at {@link Log#DEBUG} level.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param msg the message to log.
+ *
+ * @see Log#d(String, String)
+ */
+ public static int d(@Nullable String tag, @NonNull String msg) {
+ return Log.println(Log.DEBUG, tag, msg);
+ }
+
+ /**
+ * Logs {@code msg} at {@link Log#DEBUG} level, attaching stack trace of the {@code tr} to
+ * the end of the log statement.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param msg the message to log.
+ * @param tr an exception to log.
+ *
+ * @see Log#d(String, String, Throwable)
+ */
+ public static int d(@Nullable String tag, @NonNull String msg, @Nullable Throwable tr) {
+ return Log.println(Log.DEBUG, tag,
+ msg + '\n' + Log.getStackTraceString(tr));
+ }
+
+ /**
+ * Logs {@code msg} at {@link Log#INFO} level.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param msg the message to log.
+ *
+ * @see Log#i(String, String)
+ */
+ public static int i(@Nullable String tag, @NonNull String msg) {
+ return Log.println(Log.INFO, tag, msg);
+ }
+
+ /**
+ * Logs {@code msg} at {@link Log#INFO} level, attaching stack trace of the {@code tr} to
+ * the end of the log statement.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param msg the message to log.
+ * @param tr an exception to log.
+ *
+ * @see Log#i(String, String, Throwable)
+ */
+ public static int i(@Nullable String tag, @NonNull String msg, @Nullable Throwable tr) {
+ return Log.println(Log.INFO, tag,
+ msg + '\n' + Log.getStackTraceString(tr));
+ }
+
+ /**
+ * Logs {@code msg} at {@link Log#WARN} level.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param msg the message to log.
+ *
+ * @see Log#w(String, String)
+ */
+ public static int w(@Nullable String tag, @NonNull String msg) {
+ return Log.println(Log.WARN, tag, msg);
+ }
+
+ /**
+ * Logs {@code msg} at {@link Log#WARN} level, attaching stack trace of the {@code tr} to
+ * the end of the log statement.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param msg the message to log.
+ * @param tr an exception to log.
+ *
+ * @see Log#w(String, String, Throwable)
+ */
+ public static int w(@Nullable String tag, @NonNull String msg, @Nullable Throwable tr) {
+ return Log.println(Log.WARN, tag,
+ msg + '\n' + Log.getStackTraceString(tr));
+ }
+
+ /**
+ * Logs stack trace of {@code tr} at {@link Log#WARN} level.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param tr an exception to log.
+ *
+ * @see Log#w(String, Throwable)
+ */
+ public static int w(@Nullable String tag, @Nullable Throwable tr) {
+ return Log.println(Log.WARN, tag, Log.getStackTraceString(tr));
+ }
+
+ /**
+ * Logs {@code msg} at {@link Log#ERROR} level.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param msg the message to log.
+ *
+ * @see Log#e(String, String)
+ */
+ public static int e(@Nullable String tag, @NonNull String msg) {
+ return Log.println(Log.ERROR, tag, msg);
+ }
+
+ /**
+ * Logs {@code msg} at {@link Log#ERROR} level, attaching stack trace of the {@code tr} to
+ * the end of the log statement.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param msg the message to log.
+ * @param tr an exception to log.
+ *
+ * @see Log#e(String, String, Throwable)
+ */
+ public static int e(@Nullable String tag, @NonNull String msg, @Nullable Throwable tr) {
+ return Log.println(Log.ERROR, tag,
+ msg + '\n' + Log.getStackTraceString(tr));
+ }
+
+ /**
+ * Logs a condition that should never happen.
+ *
+ *
+ * Similar to {@link Log#wtf(String, String)}, but will never cause the caller to crash, and
+ * will always be handled asynchronously. Primarily to be used by the system server.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param msg the message to log.
+ *
+ * @see Log#wtf(String, String)
+ */
+ public static int wtf(@Nullable String tag, @NonNull String msg) {
+ return Log.wtf(tag, msg, null);
+ }
+
+ /**
+ * Logs a condition that should never happen, attaching the full call stack to the log.
+ *
+ *
+ * Similar to {@link Log#wtfStack(String, String)}, but will never cause the caller to crash,
+ * and will always be handled asynchronously. Primarily to be used by the system server.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param msg the message to log.
+ *
+ * @see Log#wtfStack(String, String)
+ */
+ public static int wtfStack(@Nullable String tag, @NonNull String msg) {
+ return Log.wtf(tag, msg, null);
+ }
+
+ /**
+ * Logs a condition that should never happen, attaching stack trace of the {@code tr} to the
+ * end of the log statement.
+ *
+ *
+ * Similar to {@link Log#wtf(String, Throwable)}, but will never cause the caller to crash,
+ * and will always be handled asynchronously. Primarily to be used by the system server.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param tr an exception to log.
+ *
+ * @see Log#wtf(String, Throwable)
+ */
+ public static int wtf(@Nullable String tag, @Nullable Throwable tr) {
+ return Log.wtf(tag, tr.getMessage(), tr);
+ }
+
+ /**
+ * Logs a condition that should never happen, attaching stack trace of the {@code tr} to the
+ * end of the log statement.
+ *
+ *
+ * Similar to {@link Log#wtf(String, String, Throwable)}, but will never cause the caller to
+ * crash, and will always be handled asynchronously. Primarily to be used by the system server.
+ *
+ * @param tag identifies the source of a log message. It usually represents system service,
+ * e.g. {@code PackageManager}.
+ * @param msg the message to log.
+ * @param tr an exception to log.
+ *
+ * @see Log#wtf(String, String, Throwable)
+ */
+ public static int wtf(@Nullable String tag, @NonNull String msg, @Nullable Throwable tr) {
+ return Log.wtf(tag, msg, tr);
+ }
+
+ /** @hide */
+ public static int println(int priority, @Nullable String tag, @NonNull String msg) {
+ return Log.println(priority, tag, msg);
+ }
+}
diff --git a/AndroidCompat/src/main/java/android/util/TimeUtils.java b/AndroidCompat/src/main/java/android/util/TimeUtils.java
new file mode 100644
index 00000000..42521606
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/util/TimeUtils.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.os.Build;
+import android.os.SystemClock;
+
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalTime;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * A class containing utility methods related to time zones.
+ */
+public class TimeUtils {
+ /** @hide */ public TimeUtils() {}
+ /** {@hide} */
+ private static final SimpleDateFormat sLoggingFormat =
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+ /** @hide */
+ public static final SimpleDateFormat sDumpDateFormat =
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+
+ /**
+ * This timestamp is used in TimeUtils methods and by the SettingsUI to filter time zones
+ * to only "effective" ones in a country. It is compared against the notUsedAfter metadata that
+ * Android records for some time zones.
+ *
+ *
What is notUsedAfter?
+ * Android chooses to avoid making users choose between functionally identical time zones at the
+ * expense of not being able to represent local times in the past.
+ *
+ * notUsedAfter exists because some time zones can "merge" with other time zones after a given
+ * point in time (i.e. they change to have identical transitions, offsets, display names, etc.).
+ * From the notUsedAfter time, the zone will express the same local time as the one it merged
+ * with.
+ *
+ * Why hardcoded?
+ * Rather than using System.currentTimeMillis(), a timestamp known to be in the recent past is
+ * used to ensure consistent behavior across devices and time, and avoid assumptions that the
+ * system clock on a device is currently set correctly. The fixed value should be updated
+ * occasionally, but it doesn't have to be very often as effective time zones for a country
+ * don't change very often.
+ *
+ * @hide
+ */
+ public static final Instant MIN_USE_DATE_OF_TIMEZONE =
+ Instant.ofEpochMilli(1546300800000L); // 1/1/2019 00:00 UTC
+
+ /** @hide Field length that can hold 999 days of time */
+ public static final int HUNDRED_DAY_FIELD_LEN = 19;
+
+ private static final int SECONDS_PER_MINUTE = 60;
+ private static final int SECONDS_PER_HOUR = 60 * 60;
+ private static final int SECONDS_PER_DAY = 24 * 60 * 60;
+
+ /** @hide */
+ public static final long NANOS_PER_MS = 1000000;
+
+ private static final Object sFormatSync = new Object();
+ private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+10];
+ private static char[] sTmpFormatStr = new char[HUNDRED_DAY_FIELD_LEN+10];
+
+ static private int accumField(int amt, int suffix, boolean always, int zeropad) {
+ if (amt > 999) {
+ int num = 0;
+ while (amt != 0) {
+ num++;
+ amt /= 10;
+ }
+ return num + suffix;
+ } else {
+ if (amt > 99 || (always && zeropad >= 3)) {
+ return 3+suffix;
+ }
+ if (amt > 9 || (always && zeropad >= 2)) {
+ return 2+suffix;
+ }
+ if (always || amt > 0) {
+ return 1+suffix;
+ }
+ }
+ return 0;
+ }
+
+ static private int printFieldLocked(char[] formatStr, int amt, char suffix, int pos,
+ boolean always, int zeropad) {
+ if (always || amt > 0) {
+ final int startPos = pos;
+ if (amt > 999) {
+ int tmp = 0;
+ while (amt != 0 && tmp < sTmpFormatStr.length) {
+ int dig = amt % 10;
+ sTmpFormatStr[tmp] = (char)(dig + '0');
+ tmp++;
+ amt /= 10;
+ }
+ tmp--;
+ while (tmp >= 0) {
+ formatStr[pos] = sTmpFormatStr[tmp];
+ pos++;
+ tmp--;
+ }
+ } else {
+ if ((always && zeropad >= 3) || amt > 99) {
+ int dig = amt/100;
+ formatStr[pos] = (char)(dig + '0');
+ pos++;
+ amt -= (dig*100);
+ }
+ if ((always && zeropad >= 2) || amt > 9 || startPos != pos) {
+ int dig = amt/10;
+ formatStr[pos] = (char)(dig + '0');
+ pos++;
+ amt -= (dig*10);
+ }
+ formatStr[pos] = (char)(amt + '0');
+ pos++;
+ }
+ formatStr[pos] = suffix;
+ pos++;
+ }
+ return pos;
+ }
+
+ private static int formatDurationLocked(long duration, int fieldLen) {
+ if (sFormatStr.length < fieldLen) {
+ sFormatStr = new char[fieldLen];
+ }
+
+ char[] formatStr = sFormatStr;
+
+ if (duration == 0) {
+ int pos = 0;
+ fieldLen -= 1;
+ while (pos < fieldLen) {
+ formatStr[pos++] = ' ';
+ }
+ formatStr[pos] = '0';
+ return pos+1;
+ }
+
+ char prefix;
+ if (duration > 0) {
+ prefix = '+';
+ } else {
+ prefix = '-';
+ duration = -duration;
+ }
+
+ int millis = (int)(duration%1000);
+ int seconds = (int) Math.floor(duration / 1000);
+ int days = 0, hours = 0, minutes = 0;
+
+ if (seconds >= SECONDS_PER_DAY) {
+ days = seconds / SECONDS_PER_DAY;
+ seconds -= days * SECONDS_PER_DAY;
+ }
+ if (seconds >= SECONDS_PER_HOUR) {
+ hours = seconds / SECONDS_PER_HOUR;
+ seconds -= hours * SECONDS_PER_HOUR;
+ }
+ if (seconds >= SECONDS_PER_MINUTE) {
+ minutes = seconds / SECONDS_PER_MINUTE;
+ seconds -= minutes * SECONDS_PER_MINUTE;
+ }
+
+ int pos = 0;
+
+ if (fieldLen != 0) {
+ int myLen = accumField(days, 1, false, 0);
+ myLen += accumField(hours, 1, myLen > 0, 2);
+ myLen += accumField(minutes, 1, myLen > 0, 2);
+ myLen += accumField(seconds, 1, myLen > 0, 2);
+ myLen += accumField(millis, 2, true, myLen > 0 ? 3 : 0) + 1;
+ while (myLen < fieldLen) {
+ formatStr[pos] = ' ';
+ pos++;
+ myLen++;
+ }
+ }
+
+ formatStr[pos] = prefix;
+ pos++;
+
+ int start = pos;
+ boolean zeropad = fieldLen != 0;
+ pos = printFieldLocked(formatStr, days, 'd', pos, false, 0);
+ pos = printFieldLocked(formatStr, hours, 'h', pos, pos != start, zeropad ? 2 : 0);
+ pos = printFieldLocked(formatStr, minutes, 'm', pos, pos != start, zeropad ? 2 : 0);
+ pos = printFieldLocked(formatStr, seconds, 's', pos, pos != start, zeropad ? 2 : 0);
+ pos = printFieldLocked(formatStr, millis, 'm', pos, true, (zeropad && pos != start) ? 3 : 0);
+ formatStr[pos] = 's';
+ return pos + 1;
+ }
+
+ /** @hide Just for debugging; not internationalized. */
+ public static void formatDuration(long duration, StringBuilder builder) {
+ synchronized (sFormatSync) {
+ int len = formatDurationLocked(duration, 0);
+ builder.append(sFormatStr, 0, len);
+ }
+ }
+
+ /** @hide Just for debugging; not internationalized. */
+ public static void formatDuration(long duration, StringBuilder builder, int fieldLen) {
+ synchronized (sFormatSync) {
+ int len = formatDurationLocked(duration, fieldLen);
+ builder.append(sFormatStr, 0, len);
+ }
+ }
+
+ /** @hide Just for debugging; not internationalized. */
+ public static void formatDuration(long duration, PrintWriter pw, int fieldLen) {
+ synchronized (sFormatSync) {
+ int len = formatDurationLocked(duration, fieldLen);
+ pw.print(new String(sFormatStr, 0, len));
+ }
+ }
+
+ /** @hide Just for debugging; not internationalized. */
+ @TestApi
+ public static String formatDuration(long duration) {
+ synchronized (sFormatSync) {
+ int len = formatDurationLocked(duration, 0);
+ return new String(sFormatStr, 0, len);
+ }
+ }
+
+ /** @hide Just for debugging; not internationalized. */
+ public static void formatDuration(long duration, PrintWriter pw) {
+ formatDuration(duration, pw, 0);
+ }
+
+ /** @hide Just for debugging; not internationalized. */
+ public static void formatDuration(long time, long now, StringBuilder sb) {
+ if (time == 0) {
+ sb.append("--");
+ return;
+ }
+ formatDuration(time-now, sb, 0);
+ }
+
+ /** @hide Just for debugging; not internationalized. */
+ public static void formatDuration(long time, long now, PrintWriter pw) {
+ if (time == 0) {
+ pw.print("--");
+ return;
+ }
+ formatDuration(time-now, pw, 0);
+ }
+
+ /** @hide Just for debugging; not internationalized. */
+ public static String formatUptime(long time) {
+ return formatTime(time, SystemClock.uptimeMillis());
+ }
+
+ /** @hide Just for debugging; not internationalized. */
+ public static String formatRealtime(long time) {
+ return formatTime(time, SystemClock.elapsedRealtime());
+ }
+
+ /** @hide Just for debugging; not internationalized. */
+ public static String formatTime(long time, long referenceTime) {
+ long diff = time - referenceTime;
+ if (diff > 0) {
+ return time + " (in " + diff + " ms)";
+ }
+ if (diff < 0) {
+ return time + " (" + -diff + " ms ago)";
+ }
+ return time + " (now)";
+ }
+
+ /**
+ * Convert a System.currentTimeMillis() value to a time of day value like
+ * that printed in logs. MM-DD HH:MM:SS.MMM
+ *
+ * @param millis since the epoch (1/1/1970)
+ * @return String representation of the time.
+ * @hide
+ */
+ public static String logTimeOfDay(long millis) {
+ Calendar c = Calendar.getInstance();
+ if (millis >= 0) {
+ c.setTimeInMillis(millis);
+ return String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c);
+ } else {
+ return Long.toString(millis);
+ }
+ }
+
+ /** {@hide} */
+ public static String formatForLogging(long millis) {
+ if (millis <= 0) {
+ return "unknown";
+ } else {
+ return sLoggingFormat.format(new Date(millis));
+ }
+ }
+
+ /**
+ * Dump a currentTimeMillis style timestamp for dumpsys.
+ *
+ * @hide
+ */
+ public static void dumpTime(PrintWriter pw, long time) {
+ pw.print(sDumpDateFormat.format(new Date(time)));
+ }
+
+ /**
+ * This method is used to find if a clock time is inclusively between two other clock times
+ * @param reference The time of the day we want check if it is between start and end
+ * @param start The start time reference
+ * @param end The end time
+ * @return true if the reference time is between the two clock times, and false otherwise.
+ */
+ public static boolean isTimeBetween(@NonNull LocalTime reference,
+ @NonNull LocalTime start,
+ @NonNull LocalTime end) {
+ // ////////E----+-----S////////
+ if ((reference.isBefore(start) && reference.isAfter(end)
+ // -----+----S//////////E------
+ || (reference.isBefore(end) && reference.isBefore(start) && start.isBefore(end))
+ // ---------S//////////E---+---
+ || (reference.isAfter(end) && reference.isAfter(start)) && start.isBefore(end))) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Dump a currentTimeMillis style timestamp for dumpsys, with the delta time from now.
+ *
+ * @hide
+ */
+ public static void dumpTimeWithDelta(PrintWriter pw, long time, long now) {
+ pw.print(sDumpDateFormat.format(new Date(time)));
+ if (time == now) {
+ pw.print(" (now)");
+ } else {
+ pw.print(" (");
+ TimeUtils.formatDuration(time, now, pw);
+ pw.print(")");
+ }
+ }}
diff --git a/AndroidCompat/src/main/java/android/util/TraceNameSupplier.java b/AndroidCompat/src/main/java/android/util/TraceNameSupplier.java
new file mode 100644
index 00000000..e4b3a4ed
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/util/TraceNameSupplier.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os;
+
+import android.annotation.NonNull;
+
+/**
+ * Supplier for custom trace messages.
+ *
+ * @hide
+ */
+public interface TraceNameSupplier {
+
+ /**
+ * Gets the name used for trace messages.
+ */
+ @NonNull String getTraceName();
+}
diff --git a/AndroidCompat/src/main/java/android/view/View.java b/AndroidCompat/src/main/java/android/view/View.java
new file mode 100644
index 00000000..06a19f6c
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/view/View.java
@@ -0,0 +1,5748 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+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.FloatRange;
+import android.annotation.IdRes;
+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.UiThread;
+import android.app.PendingIntent;
+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.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.RenderNode;
+import android.graphics.Shader;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+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.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.Trace;
+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.Pair;
+import android.util.Property;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.util.StateSet;
+import android.util.TimeUtils;
+import android.util.TypedValue;
+import android.view.ContextMenu.ContextMenuInfo;
+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.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.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Checkable;
+
+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 {
+ /** @hide */
+ public static boolean DEBUG_DRAW = false;
+
+ protected static final String VIEW_LOG_TAG = "View";
+
+ 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;
+
+ /** @hide */
+ // public HapticScrollFeedbackProvider mScrollFeedbackProvider = null;
+
+ static boolean sTextureViewIgnoresDrawableSetters = false;
+
+ protected static boolean sPreserveMarginParamsInLayoutParamConversion;
+
+ static boolean sCascadedDragDrop;
+
+ static boolean sHasFocusableExcludeAutoFocusable;
+
+ static boolean sBrokenInsetsDispatch;
+
+ protected static boolean sBrokenWindowBackground;
+
+ static boolean sForceLayoutWhenInsetsChanged;
+
+ /** @hide */
+ @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;
+
+ /** @hide */
+ @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;
+
+ 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";
+
+ // TODO(229765029): unhide this for UI toolkit
+ public static final String AUTOFILL_HINT_PASSWORD_AUTO = "passwordAuto";
+
+ public static final String AUTOFILL_HINT_CREDENTIAL_MANAGER = "credential";
+
+ /** @hide */
+ @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;
+
+
+ /** @hide */
+ @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;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AutofillFlags {}
+
+ public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
+
+ /** @hide */
+ @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;
+
+ /** {@hide} */
+ @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;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ 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;
+
+ 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;
+
+ /** @hide */
+ @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;
+
+ static final int TOOLTIP = 0x40000000;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ContentSensitivity {}
+
+ public static final int CONTENT_SENSITIVITY_AUTO = 0x0;
+
+ public static final int CONTENT_SENSITIVITY_SENSITIVE = 0x1;
+
+ public static final int CONTENT_SENSITIVITY_NOT_SENSITIVE = 0x2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FocusableMode {}
+
+ public static final int FOCUSABLES_ALL = 0x00000000;
+
+ public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FocusDirection {}
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
+
+ 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;
+
+ // Singles
+ protected static final int[] EMPTY_STATE_SET = new int[0];
+ protected static final int[] ENABLED_STATE_SET = new int[0];
+ protected static final int[] FOCUSED_STATE_SET = new int[0];
+ protected static final int[] SELECTED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_STATE_SET = new int[0];
+ protected static final int[] WINDOW_FOCUSED_STATE_SET = new int[0];
+ // Doubles
+ protected static final int[] ENABLED_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] ENABLED_SELECTED_STATE_SET = new int[0];
+ protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] FOCUSED_SELECTED_STATE_SET = new int[0];
+ protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET = new int[0];
+ // Triples
+ protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET = new int[0];
+ protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_SELECTED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_ENABLED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = new int[0];
+ protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = new int[0];
+
+ 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;
+
+ protected static boolean sToolkitSetFrameRateReadOnlyFlagValue;
+
+ // Used to set frame rate compatibility.
+ int mFrameRateCompatibility;
+
+ static final int DEBUG_CORNERS_COLOR = 0;
+
+ static final int DEBUG_CORNERS_SIZE_DIP = 8;
+
+ static final ThreadLocal sThreadLocal = ThreadLocal.withInitial(Rect::new);
+
+ protected Animation mCurrentAnimation = null;
+
+ @ViewDebug.ExportedProperty(category = "measurement")
+ int mMeasuredWidth;
+
+ @ViewDebug.ExportedProperty(category = "measurement")
+ int mMeasuredHeight;
+
+ boolean mRecreateDisplayList = false;
+
+ @IdRes
+ @ViewDebug.ExportedProperty(resolveId = true)
+ int mID = NO_ID;
+ protected Object mTag = null;
+
+ /*
+ * Masks for mPrivateFlags, as generated by dumpFlags():
+ *
+ * |-------|-------|-------|-------|
+ * 1 PFLAG_WANTS_FOCUS
+ * 1 PFLAG_FOCUSED
+ * 1 PFLAG_SELECTED
+ * 1 PFLAG_IS_ROOT_NAMESPACE
+ * 1 PFLAG_HAS_BOUNDS
+ * 1 PFLAG_DRAWN
+ * 1 PFLAG_DRAW_ANIMATION
+ * 1 PFLAG_SKIP_DRAW
+ * 1 PFLAG_REQUEST_TRANSPARENT_REGIONS
+ * 1 PFLAG_DRAWABLE_STATE_DIRTY
+ * 1 PFLAG_MEASURED_DIMENSION_SET
+ * 1 PFLAG_FORCE_LAYOUT
+ * 1 PFLAG_LAYOUT_REQUIRED
+ * 1 PFLAG_PRESSED
+ * 1 PFLAG_DRAWING_CACHE_VALID
+ * 1 PFLAG_ANIMATION_STARTED
+ * 1 PFLAG_SAVE_STATE_CALLED
+ * 1 PFLAG_ALPHA_SET
+ * 1 PFLAG_SCROLL_CONTAINER
+ * 1 PFLAG_SCROLL_CONTAINER_ADDED
+ * 1 PFLAG_DIRTY
+ * 1 PFLAG_DIRTY_MASK
+ * 1 PFLAG_OPAQUE_BACKGROUND
+ * 1 PFLAG_OPAQUE_SCROLLBARS
+ * 11 PFLAG_OPAQUE_MASK
+ * 1 PFLAG_PREPRESSED
+ * 1 PFLAG_CANCEL_NEXT_UP_EVENT
+ * 1 PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH
+ * 1 PFLAG_HOVERED
+ * 1 PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK
+ * 1 PFLAG_ACTIVATED
+ * 1 PFLAG_INVALIDATED
+ * |-------|-------|-------|-------|
+ */
+ /** {@hide} */
+ static final int PFLAG_WANTS_FOCUS = 0x00000001;
+ /** {@hide} */
+ static final int PFLAG_FOCUSED = 0x00000002;
+ /** {@hide} */
+ static final int PFLAG_SELECTED = 0x00000004;
+ /** {@hide} */
+ static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008;
+ /** {@hide} */
+ static final int PFLAG_HAS_BOUNDS = 0x00000010;
+ /** {@hide} */
+ static final int PFLAG_DRAWN = 0x00000020;
+ static final int PFLAG_DRAW_ANIMATION = 0x00000040;
+ /** {@hide} */
+ static final int PFLAG_SKIP_DRAW = 0x00000080;
+ /** {@hide} */
+ static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
+ /** {@hide} */
+ static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400;
+ /** {@hide} */
+ static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800;
+ /** {@hide} */
+ static final int PFLAG_FORCE_LAYOUT = 0x00001000;
+ /** {@hide} */
+ static final int PFLAG_LAYOUT_REQUIRED = 0x00002000;
+
+ /** {@hide} */
+ static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000;
+ static final int PFLAG_ANIMATION_STARTED = 0x00010000;
+
+ 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;
+
+ static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000;
+
+ /** {@hide} */
+ static final int PFLAG_ACTIVATED = 0x40000000;
+
+ static final int PFLAG_INVALIDATED = 0x80000000;
+
+ /* End of masks for mPrivateFlags */
+
+ /*
+ * Masks for mPrivateFlags2, as generated by dumpFlags():
+ *
+ * |-------|-------|-------|-------|
+ * 1 PFLAG2_DRAG_CAN_ACCEPT
+ * 1 PFLAG2_DRAG_HOVERED
+ * 11 PFLAG2_LAYOUT_DIRECTION_MASK
+ * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
+ * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED
+ * 11 PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
+ * 1 PFLAG2_TEXT_DIRECTION_FLAGS[1]
+ * 1 PFLAG2_TEXT_DIRECTION_FLAGS[2]
+ * 11 PFLAG2_TEXT_DIRECTION_FLAGS[3]
+ * 1 PFLAG2_TEXT_DIRECTION_FLAGS[4]
+ * 1 1 PFLAG2_TEXT_DIRECTION_FLAGS[5]
+ * 11 PFLAG2_TEXT_DIRECTION_FLAGS[6]
+ * 111 PFLAG2_TEXT_DIRECTION_FLAGS[7]
+ * 111 PFLAG2_TEXT_DIRECTION_MASK
+ * 1 PFLAG2_TEXT_DIRECTION_RESOLVED
+ * 1 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
+ * 111 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
+ * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
+ * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
+ * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
+ * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
+ * 1 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
+ * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
+ * 111 PFLAG2_TEXT_ALIGNMENT_MASK
+ * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED
+ * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
+ * 111 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
+ * 111 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
+ * 11 PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
+ * 1 PFLAG2_ACCESSIBILITY_FOCUSED
+ * 1 PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
+ * 1 PFLAG2_VIEW_QUICK_REJECTED
+ * 1 PFLAG2_PADDING_RESOLVED
+ * 1 PFLAG2_DRAWABLE_RESOLVED
+ * 1 PFLAG2_HAS_TRANSIENT_STATE
+ * |-------|-------|-------|-------|
+ */
+
+ static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001;
+
+ static final int PFLAG2_DRAG_HOVERED = 0x00000002;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
+ public @interface LayoutDir {}
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ResolvedLayoutDir {}
+
+ public static final int LAYOUT_DIRECTION_UNDEFINED = 0;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ /** @hide */
+ @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;
+
+ 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;
+
+ 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;
+
+ // Accessiblity constants for mPrivateFlags2
+
+ 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;
+
+ /** @hide */
+ @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;
+
+ // There are a couple of flags left in mPrivateFlags2
+
+ /* End of masks for mPrivateFlags2 */
+
+ /*
+ * Masks for mPrivateFlags3, as generated by dumpFlags():
+ *
+ * |-------|-------|-------|-------|
+ * 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
+ * 1 PFLAG3_VIEW_IS_ANIMATING_ALPHA
+ * 1 PFLAG3_IS_LAID_OUT
+ * 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
+ * 1 PFLAG3_CALLED_SUPER
+ * 1 PFLAG3_APPLYING_INSETS
+ * 1 PFLAG3_FITTING_SYSTEM_WINDOWS
+ * 1 PFLAG3_NESTED_SCROLLING_ENABLED
+ * 1 PFLAG3_SCROLL_INDICATOR_TOP
+ * 1 PFLAG3_SCROLL_INDICATOR_BOTTOM
+ * 1 PFLAG3_SCROLL_INDICATOR_LEFT
+ * 1 PFLAG3_SCROLL_INDICATOR_RIGHT
+ * 1 PFLAG3_SCROLL_INDICATOR_START
+ * 1 PFLAG3_SCROLL_INDICATOR_END
+ * 1 PFLAG3_ASSIST_BLOCKED
+ * 1 PFLAG3_CLUSTER
+ * 1 PFLAG3_IS_AUTOFILLED
+ * 1 PFLAG3_FINGER_DOWN
+ * 1 PFLAG3_FOCUSED_BY_DEFAULT
+ * 1111 PFLAG3_IMPORTANT_FOR_AUTOFILL
+ * 1 PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
+ * 1 PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
+ * 1 PFLAG3_TEMPORARY_DETACH
+ * 1 PFLAG3_NO_REVEAL_ON_FOCUS
+ * 1 PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
+ * 1 PFLAG3_SCREEN_READER_FOCUSABLE
+ * 1 PFLAG3_AGGREGATED_VISIBLE
+ * 1 PFLAG3_AUTOFILLID_EXPLICITLY_SET
+ * 1 PFLAG3_ACCESSIBILITY_HEADING
+ * |-------|-------|-------|-------|
+ */
+
+ 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;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ 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;
+
+ 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;
+
+ static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
+
+ static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
+
+ /* End of masks for mPrivateFlags3 */
+
+ /*
+ * Masks for mPrivateFlags4, as generated by dumpFlags():
+ *
+ * |-------|-------|-------|-------|
+ * 1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
+ * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED
+ * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED
+ * 1 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
+ * 1 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE
+ * 11 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK
+ * 1 PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
+ * 1 PFLAG4_AUTOFILL_HIDE_HIGHLIGHT
+ * 11 PFLAG4_SCROLL_CAPTURE_HINT_MASK
+ * 1 PFLAG4_ALLOW_CLICK_WHEN_DISABLED
+ * 1 PFLAG4_DETACHED
+ * 1 PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE
+ * 1 PFLAG4_DRAG_A11Y_STARTED
+ * 1 PFLAG4_AUTO_HANDWRITING_INITIATION_ENABLED
+ * 1 PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER
+ * 1 PFLAG4_TRAVERSAL_TRACING_ENABLED
+ * 1 PFLAG4_RELAYOUT_TRACING_ENABLED
+ * 1 PFLAG4_ROTARY_HAPTICS_DETERMINED
+ * 1 PFLAG4_ROTARY_HAPTICS_ENABLED
+ * 1 PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT
+ * 1 PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT
+ * 11 PFLAG4_CONTENT_SENSITIVITY_MASK
+ * 1 PFLAG4_IS_COUNTED_AS_SENSITIVE
+ * 1 PFLAG4_HAS_DRAWN
+ * 1 PFLAG4_HAS_MOVED
+ * 1 PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION
+ * 1 PFLAG4_FORCED_OVERRIDE_FRAME_RATE
+ * 1 PFLAG4_SELF_REQUESTED_FRAME_RATE
+ * |-------|-------|-------|-------|
+ */
+
+ static final int PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS = 0x000000100;
+
+ 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;
+
+ /* End of masks for mPrivateFlags4 */
+
+ /** @hide */
+ protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
+ /** @hide */
+ protected static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
+ /** @hide */
+ protected static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
+
+ /** @hide */
+ @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;
+
+ @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;
+
+ 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;
+
+ public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
+
+ public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
+
+ public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
+
+ 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;
+
+ /** @hide */
+ @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;
+
+ protected ViewParent mParent;
+
+ // AttachInfo mAttachInfo;
+
+ /* @hide */
+ public int mPrivateFlags;
+ int mPrivateFlags2;
+ int mPrivateFlags3;
+
+ @SystemUiVisibility
+ int mSystemUiVisibility;
+
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SystemUiVisibility {}
+
+ int mTransientStateCount = 0;
+
+ int mWindowAttachCount;
+
+ protected ViewGroup.LayoutParams mLayoutParams;
+
+ @ViewDebug.ExportedProperty(formatToHexString = true)
+ int mViewFlags;
+
+ static class TransformationInfo {
+ float mTransitionAlpha = 1f;
+ }
+
+ /** @hide */
+ public TransformationInfo mTransformationInfo;
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ Rect mClipBounds = null;
+
+ @ViewDebug.ExportedProperty(category = "layout")
+ protected int mLeft;
+ @ViewDebug.ExportedProperty(category = "layout")
+ protected int mRight;
+ @ViewDebug.ExportedProperty(category = "layout")
+ protected int mTop;
+ @ViewDebug.ExportedProperty(category = "layout")
+ protected int mBottom;
+
+ @ViewDebug.ExportedProperty(category = "scrolling")
+ protected int mScrollX;
+ @ViewDebug.ExportedProperty(category = "scrolling")
+ protected int mScrollY;
+
+ @ViewDebug.ExportedProperty(category = "padding")
+ protected int mPaddingLeft = 0;
+ @ViewDebug.ExportedProperty(category = "padding")
+ protected int mPaddingRight = 0;
+ @ViewDebug.ExportedProperty(category = "padding")
+ protected int mPaddingTop;
+ @ViewDebug.ExportedProperty(category = "padding")
+ protected int mPaddingBottom;
+
+ @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;
+
+ int mOldWidthMeasureSpec = Integer.MIN_VALUE;
+ int mOldHeightMeasureSpec = Integer.MIN_VALUE;
+
+ RenderNode mBackgroundRenderNode;
+
+ static class TintInfo {
+ ColorStateList mTintList;
+ BlendMode mBlendMode;
+ boolean mHasTintMode;
+ boolean mHasTintList;
+ }
+
+ // ListenerInfo mListenerInfo;
+
+ // TooltipInfo mTooltipInfo;
+
+ @ViewDebug.ExportedProperty(deepExport = true)
+ protected Context mContext;
+
+ ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
+
+ int mNextFocusForwardId = View.NO_ID;
+
+ int mNextClusterForwardId = View.NO_ID;
+
+ boolean mDefaultFocusHighlightEnabled = true;
+
+ public static final int DRAG_FLAG_GLOBAL = 1 << 8; // 256
+
+ 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;
+
+ public static final int DRAG_FLAG_GLOBAL_SAME_APPLICATION = 1 << 12;
+
+ public static final int DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG = 1 << 13;
+
+ public static final int DRAG_FLAG_HIDE_CALLING_TASK_ON_DRAG_START = 1 << 14;
+
+ 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;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LayerType {}
+
+ int mLayerType = LAYER_TYPE_NONE;
+ Paint mLayerPaint;
+
+ public boolean mCachingFailed;
+
+ final RenderNode mRenderNode;
+
+ AccessibilityDelegate mAccessibilityDelegate;
+
+ ViewOverlay mOverlay;
+
+ // protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
+ // InputEventConsistencyVerifier.isInstrumentationEnabled() ?
+ // new InputEventConsistencyVerifier(this, 0) : null;
+
+ // GhostView mGhostView;
+
+ @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
+ public String[] mAttributes;
+
+ String mStartActivityRequestWho;
+
+ int mUnbufferedInputSource = InputDevice.SOURCE_CLASS_NONE;
+
+ static final float MAX_FRAME_RATE = 120;
+
+ public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = Float.NaN;
+ public static final float REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE = -1;
+ public static final float REQUESTED_FRAME_RATE_CATEGORY_LOW = -2;
+ public static final float REQUESTED_FRAME_RATE_CATEGORY_NORMAL = -3;
+ public static final float REQUESTED_FRAME_RATE_CATEGORY_HIGH = -4;
+
+ public View(Context context) {
+ mContext = context;
+ mRenderNode = null;
+ }
+
+ 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);
+ }
+
+ @NonNull
+ public int[] getAttributeResolutionStack(@AttrRes int attribute) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @NonNull
+ @SuppressWarnings("AndroidFrameworkEfficientCollections")
+ public Map getAttributeSourceResourceMap() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @StyleRes
+ public int getExplicitStyle() {
+ throw new RuntimeException("Stub!");
+ }
+
+ View() {
+ mRenderNode = null;
+ }
+
+ public final boolean isShowingLayoutBounds() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public final void setShowingLayoutBounds(boolean debugLayout) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void saveAttributeDataForStyleable(@NonNull Context context,
+ @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t,
+ int defStyleAttr, int defStyleRes) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void initializeFadingEdge(TypedArray a) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void initializeFadingEdgeInternal(TypedArray a) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getVerticalFadingEdgeLength() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setFadingEdgeLength(int length) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void clearPendingCredentialRequest() {
+ throw new RuntimeException("Stub!");
+ }
+
+ // public void setPendingCredentialRequest(@NonNull GetCredentialRequest request,
+ // @NonNull OutcomeReceiver callback) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // @Nullable
+ // public ViewCredentialHandler getViewCredentialHandler() {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ public int getHorizontalFadingEdgeLength() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getVerticalScrollbarWidth() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected int getHorizontalScrollbarHeight() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void initializeScrollbars(TypedArray a) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void initializeScrollbarsInternal(TypedArray a) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setVerticalScrollbarThumbDrawable(@Nullable Drawable drawable) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setVerticalScrollbarTrackDrawable(@Nullable Drawable drawable) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setHorizontalScrollbarThumbDrawable(@Nullable Drawable drawable) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setHorizontalScrollbarTrackDrawable(@Nullable Drawable drawable) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @Nullable Drawable getVerticalScrollbarThumbDrawable() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @Nullable Drawable getVerticalScrollbarTrackDrawable() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @Nullable Drawable getHorizontalScrollbarThumbDrawable() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @Nullable Drawable getHorizontalScrollbarTrackDrawable() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setVerticalScrollbarPosition(int position) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getVerticalScrollbarPosition() {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean isOnScrollbar(float x, float y) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean isOnScrollbarThumb(float x, float y) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean isDraggingScrollBar() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setScrollIndicators(@ScrollIndicators int indicators) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ScrollIndicators
+ public int getScrollIndicators() {
+ throw new RuntimeException("Stub!");
+ }
+
+ // ListenerInfo getListenerInfo() {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ public void setOnScrollChangeListener(OnScrollChangeListener l) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setOnFocusChangeListener(OnFocusChangeListener l) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public OnFocusChangeListener getOnFocusChangeListener() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setOnClickListener(@Nullable OnClickListener l) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean hasOnClickListeners() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setOnLongClickListener(@Nullable OnLongClickListener l) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean hasOnLongClickListeners() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public OnLongClickListener getOnLongClickListener() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setOnContextClickListener(@Nullable OnContextClickListener l) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addFrameMetricsListener(Window window,
+ Window.OnFrameMetricsAvailableListener listener,
+ Handler handler) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void removeFrameMetricsListener(
+ Window.OnFrameMetricsAvailableListener listener) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ public void setNotifyAutofillManagerOnClick(boolean notify) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // NOTE: other methods on View should not call this method directly, but performClickInternal()
+ // instead, to guarantee that the autofill manager is notified when necessary (as subclasses
+ // could extend this method without calling super.performClick()).
+ public boolean performClick() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean callOnClick() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean performLongClick() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean performLongClick(float x, float y) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean performContextClick(float x, float y) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean performContextClick() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean performButtonActionOnTouchDown(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean showContextMenu() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean showContextMenu(float x, float y) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public ActionMode startActionMode(ActionMode.Callback callback) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public ActionMode startActionMode(ActionMode.Callback callback, int type) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void startActivityForResult(Intent intent, int requestCode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchActivityResult(
+ String who, int requestCode, int resultCode, Intent data) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ // Do nothing.
+ }
+
+ public void setOnKeyListener(OnKeyListener l) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setOnTouchListener(OnTouchListener l) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setOnGenericMotionListener(OnGenericMotionListener l) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setOnHoverListener(OnHoverListener l) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setOnDragListener(OnDragListener l) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void setRevealOnFocusHint(boolean revealOnFocus) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean getRevealOnFocusHint() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void getHotspotBounds(Rect outRect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean requestRectangleOnScreen(Rect rectangle) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void clearFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void notifyGlobalFocusCleared(View oldFocus) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean rootViewRequestFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void unFocus(View focused) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "focus")
+ public boolean hasFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean hasFocusable() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean hasExplicitFocusable() {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
+ @Nullable Rect previouslyFocusedRect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public CharSequence getAccessibilityPaneTitle() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void sendAccessibilityEvent(int eventType) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void announceForAccessibility(CharSequence text) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void sendAccessibilityEventInternal(int eventType) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public AccessibilityNodeInfo createAccessibilityNodeInfo() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @Nullable AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void getBoundsOnScreen(Rect outRect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public void getBoundsOnScreen(@NonNull Rect outRect, boolean clipToParent) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void getBoundsOnScreen(RectF outRect, boolean clipToParent) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void getBoundsInWindow(Rect outRect, boolean clipToParent) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void mapRectFromViewToWindowCoords(RectF rect, boolean clipToParent) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public CharSequence getAccessibilityClassName() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onProvideStructure(ViewStructure structure) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ protected void onProvideStructure(@NonNull ViewStructure structure,
+ @ViewStructureType int viewFor, int flags) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onProvideVirtualStructure(ViewStructure structure) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // public void setOnReceiveContentListener(
+ // @SuppressLint("NullableCollection") @Nullable String[] mimeTypes,
+ // @Nullable OnReceiveContentListener listener) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // @Nullable
+ // public ContentInfo performReceiveContent(@NonNull ContentInfo payload) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // @Nullable
+ // public ContentInfo onReceiveContent(@NonNull ContentInfo payload) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ @SuppressLint("NullableCollection")
+ @Nullable
+ public String[] getReceiveContentMimeTypes() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void autofill(@SuppressWarnings("unused") AutofillValue value) {
+ }
+
+ public void autofill(@NonNull @SuppressWarnings("unused") SparseArray values) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // public void onGetCredentialResponse(GetCredentialResponse response) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ public void onGetCredentialException(String errorType, String errorMsg) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final AutofillId getAutofillId() {
+ throw new RuntimeException("Stub!");
+ }
+
+ // @Nullable
+ // public final GetCredentialRequest getPendingCredentialRequest() {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // @Nullable
+ // public final OutcomeReceiver getPendingCredentialCallback() {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ public void setAutofillId(@Nullable AutofillId id) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void resetSubtreeAutofillIds() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @AutofillType int getAutofillType() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty()
+ @Nullable public String[] getAutofillHints() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public boolean isAutofilled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean hideAutofillHighlight() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public AutofillValue getAutofillValue() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @AutofillImportance int getImportantForAutofill() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setImportantForAutofill(@AutofillImportance int mode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean isImportantForAutofill() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void setContentSensitivity(@ContentSensitivity int mode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @ContentSensitivity final int getContentSensitivity() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean isContentSensitive() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @ContentCaptureImportance int getImportantForContentCapture() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean isImportantForContentCapture() {
+ throw new RuntimeException("Stub!");
+ }
+ /** @hide */
+ protected boolean getNotifiedContentCaptureAppeared() {
+ throw new RuntimeException("Stub!");
+ }
+
+
+ public void setContentCaptureSession(@Nullable ContentCaptureSession contentCaptureSession) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public final ContentCaptureSession getContentCaptureSession() {
+ throw new RuntimeException("Stub!");
+ }
+
+ final boolean isActivityDeniedForAutofillForUnimportantView() {
+ throw new RuntimeException("Stub!");
+ }
+
+ final boolean isMatchingAutofillableHeuristics() {
+ throw new RuntimeException("Stub!");
+ }
+ /** @hide */
+ public boolean canNotifyAutofillEnterExitEvent() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void dispatchProvideStructure(ViewStructure structure) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
+ @AutofillFlags int flags) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void dispatchInitialProvideContentCaptureStructure() {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ void dispatchProvideContentCaptureStructure() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
+ throw new RuntimeException("Stub!");
+ }
+
+
+ public void addExtraDataToAccessibilityNodeInfo(
+ @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
+ @Nullable Bundle arguments) {
+ }
+
+ public boolean isVisibleToUserForAutofill(int virtualId) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isVisibleToUser() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean isVisibleToUser(Rect boundInView) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public AccessibilityDelegate getAccessibilityDelegate() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public AccessibilityNodeProvider getAccessibilityNodeProvider() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getAccessibilityViewId() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getAutofillViewId() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getAccessibilityWindowId() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "accessibility")
+ public final @Nullable CharSequence getStateDescription() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "accessibility")
+ public CharSequence getContentDescription() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "accessibility")
+ @Nullable
+ public CharSequence getSupplementalDescription() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setStateDescription(@Nullable CharSequence stateDescription) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setContentDescription(CharSequence contentDescription) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setSupplementalDescription(@Nullable CharSequence supplementalDescription) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAccessibilityTraversalBefore(@IdRes int beforeId) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @IdRes
+ public int getAccessibilityTraversalBefore() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAccessibilityTraversalAfter(@IdRes int afterId) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @IdRes
+ public int getAccessibilityTraversalAfter() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @IdRes
+ @ViewDebug.ExportedProperty(category = "accessibility")
+ public int getLabelFor() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setLabelFor(@IdRes int id) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ protected void onFocusLost() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "focus")
+ public boolean isFocused() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public View findFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isScrollContainer() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setScrollContainer(boolean isScrollContainer) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ @DrawingCacheQuality
+ public int getDrawingCacheQuality() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean getKeepScreenOn() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setKeepScreenOn(boolean keepScreenOn) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @IdRes
+ public int getNextFocusLeftId() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setNextFocusLeftId(@IdRes int nextFocusLeftId) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @IdRes
+ public int getNextFocusRightId() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setNextFocusRightId(@IdRes int nextFocusRightId) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @IdRes
+ public int getNextFocusUpId() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setNextFocusUpId(@IdRes int nextFocusUpId) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @IdRes
+ public int getNextFocusDownId() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setNextFocusDownId(@IdRes int nextFocusDownId) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @IdRes
+ public int getNextFocusForwardId() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setNextFocusForwardId(@IdRes int nextFocusForwardId) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @IdRes
+ public int getNextClusterForwardId() {
+ return mNextClusterForwardId;
+ }
+
+ public void setNextClusterForwardId(@IdRes int nextClusterForwardId) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isShown() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ protected boolean fitSystemWindows(Rect insets) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setWindowInsetsAnimationCallback(
+ @Nullable WindowInsetsAnimation.Callback callback) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean hasWindowInsetsAnimationCallback() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void dispatchWindowInsetsAnimationPrepare(
+ @NonNull WindowInsetsAnimation animation) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @NonNull
+ public Bounds dispatchWindowInsetsAnimationStart(
+ @NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @NonNull
+ public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
+ @NonNull List runningAnimations) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setSystemGestureExclusionRects(@NonNull List rects) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void updateSystemGestureExclusionRects() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @NonNull
+ public List getSystemGestureExclusionRects() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void setPreferKeepClear(boolean preferKeepClear) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean isPreferKeepClear() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void setPreferKeepClearRects(@NonNull List rects) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @NonNull
+ public final List getPreferKeepClearRects() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @SystemApi
+ public final void setUnrestrictedPreferKeepClearRects(@NonNull List rects) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @SystemApi
+ @NonNull
+ public final List getUnrestrictedPreferKeepClearRects() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void updateKeepClearRects() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @NonNull
+ List collectPreferKeepClearRects() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @NonNull
+ List collectUnrestrictedPreferKeepClearRects() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setHandwritingBoundsOffsets(float offsetLeft, float offsetTop,
+ float offsetRight, float offsetBottom) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public float getHandwritingBoundsOffsetLeft() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public float getHandwritingBoundsOffsetTop() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public float getHandwritingBoundsOffsetRight() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public float getHandwritingBoundsOffsetBottom() {
+ throw new RuntimeException("Stub!");
+ }
+
+
+ public void setHandwritingArea(@Nullable Rect rect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public Rect getHandwritingArea() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void updateHandwritingArea() {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean shouldInitiateHandwriting() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean shouldTrackHandwritingArea() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setHandwritingDelegatorCallback(@Nullable Runnable callback) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public Runnable getHandwritingDelegatorCallback() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAllowedHandwritingDelegatePackage(@Nullable String allowedPackageName) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public String getAllowedHandwritingDelegatePackageName() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setIsHandwritingDelegate(boolean isHandwritingDelegate) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isHandwritingDelegate() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAllowedHandwritingDelegatorPackage(@Nullable String allowedPackageName) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public String getAllowedHandwritingDelegatorPackageName() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setHandwritingDelegateFlags(
+ int flags) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getHandwritingDelegateFlags() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void getLocationInSurface(@NonNull @Size(2) int[] location) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public WindowInsets getRootWindowInsets() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @Nullable WindowInsetsController getWindowInsetsController() {
+ throw new RuntimeException("Stub!");
+ }
+
+ // @Nullable
+ // public final OnBackInvokedDispatcher findOnBackInvokedDispatcher() {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ @Deprecated
+ protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean hasContentOnApplyWindowInsetsListener() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setFitsSystemWindows(boolean fitSystemWindows) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty
+ public boolean getFitsSystemWindows() {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ public boolean fitsSystemWindows() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void requestFitSystemWindows() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void requestApplyInsets() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void makeOptionalFitsSystemWindows() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void makeFrameworkOptionalFitsSystemWindows() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isFrameworkOptionalFitsSystemWindows() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(mapping = {
+ @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"),
+ @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
+ @ViewDebug.IntToString(from = GONE, to = "GONE")
+ })
+ @Visibility
+ public int getVisibility() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setVisibility(@Visibility int visibility) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty
+ public boolean isEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setEnabled(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setFocusable(boolean focusable) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setFocusable(@Focusable int focusable) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setFocusableInTouchMode(boolean focusableInTouchMode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAutofillHints(@Nullable String... autofillHints) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public void setAutofilled(boolean isAutofilled, boolean hideHighlight) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty
+ public boolean isSoundEffectsEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty
+ public boolean isHapticFeedbackEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @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")
+ })
+ @LayoutDir
+ public int getRawLayoutDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setLayoutDirection(@LayoutDir int layoutDirection) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @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")
+ })
+ @ResolvedLayoutDir
+ public int getLayoutDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "layout")
+ public boolean isLayoutRtl() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "layout")
+ public boolean hasTransientState() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setHasTransientState(boolean hasTransientState) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setHasTranslationTransientState(boolean hasTranslationTransientState) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean hasTranslationTransientState() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void clearTranslationState() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isAttachedToWindow() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isLaidOut() {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean isLayoutValid() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setWillNotDraw(boolean willNotDraw) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public boolean willNotDraw() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ @Deprecated
+ public boolean willNotCacheDrawing() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty
+ public boolean isClickable() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setClickable(boolean clickable) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAllowClickWhenDisabled(boolean clickableWhenDisabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isLongClickable() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setLongClickable(boolean longClickable) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isContextClickable() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setContextClickable(boolean contextClickable) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setPressed(boolean pressed) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void dispatchSetPressed(boolean pressed) {
+ }
+
+ @ViewDebug.ExportedProperty
+ public boolean isPressed() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isAssistBlocked() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAssistBlocked(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isSaveEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setSaveEnabled(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty
+ public boolean getFilterTouchesWhenObscured() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setFilterTouchesWhenObscured(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isSaveFromParentEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setSaveFromParentEnabled(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+
+ @ViewDebug.ExportedProperty(category = "focus")
+ public final boolean isFocusable() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @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")
+ @Focusable
+ public int getFocusable() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "focus")
+ public final boolean isFocusableInTouchMode() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isScreenReaderFocusable() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setScreenReaderFocusable(boolean screenReaderFocusable) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isAccessibilityHeading() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAccessibilityHeading(boolean isHeading) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public View focusSearch(@FocusRealDirection int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "focus")
+ public final boolean isKeyboardNavigationCluster() {
+ throw new RuntimeException("Stub!");
+ }
+
+ View findKeyboardNavigationCluster() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setKeyboardNavigationCluster(boolean isCluster) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public final void setFocusedInCluster() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "focus")
+ public final boolean isFocusedByDefault() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setFocusedByDefault(boolean isFocusedByDefault) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean hasDefaultFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public View keyboardNavigationClusterSearch(View currentCluster,
+ @FocusDirection int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "focus")
+ public final boolean getDefaultFocusHighlightEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ View findUserSetNextFocus(View root, @FocusDirection int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public ArrayList getFocusables(@FocusDirection int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addFocusables(ArrayList views, @FocusDirection int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addFocusables(ArrayList views, @FocusDirection int direction,
+ @FocusableMode int focusableMode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addKeyboardNavigationClusters(
+ @NonNull Collection views,
+ int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void findViewsWithText(ArrayList outViews, CharSequence searched,
+ @FindViewFlags int flags) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public ArrayList getTouchables() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addTouchables(ArrayList views) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isAccessibilityFocused() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean requestAccessibilityFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void clearAccessibilityFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void clearAccessibilityFocusNoCallbacks(int action) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean requestFocus() {
+ return requestFocus(View.FOCUS_DOWN);
+ }
+
+ @TestApi
+ public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public boolean restoreFocusNotInCluster() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean restoreDefaultFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean requestFocus(int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void clearParentsWantFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean requestFocusFromTouch() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getImportantForAccessibility() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAccessibilityLiveRegion(int mode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getAccessibilityLiveRegion() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setImportantForAccessibility(int mode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isImportantForAccessibility() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public ViewParent getParentForAccessibility() {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ @Nullable
+ View getSelfOrParentImportantForA11y() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addChildrenForAccessibility(ArrayList outChildren) {
+
+ }
+
+ public boolean includeForAccessibility() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean includeForAccessibility(boolean forNodeTree) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "accessibility")
+ public boolean isAccessibilityDataSensitive() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void calculateAccessibilityDataSensitive() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAccessibilityDataSensitive(
+ @AccessibilityDataSensitive int accessibilityDataSensitive) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isActionableForAccessibility() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void notifySubtreeAccessibilityStateChangedIfNeeded() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTransitionVisibility(@Visibility int visibility) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void resetSubtreeAccessibilityStateChanged() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchNestedPrePerformAccessibilityAction(int action,
+ @Nullable Bundle arguments) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean performAccessibilityAction(int action, @Nullable Bundle arguments) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean performAccessibilityActionInternal(int action, @Nullable Bundle arguments) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public CharSequence getIterableTextForAccessibility() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isAccessibilitySelectionExtendable() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void prepareForExtendedAccessibilitySelection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getAccessibilitySelectionStart() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getAccessibilitySelectionEnd() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAccessibilitySelection(int start, int end) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // public TextSegmentIterator getIteratorForGranularity(int granularity) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ public final boolean isTemporarilyDetached() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ public void dispatchStartTemporaryDetach() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onStartTemporaryDetach() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ public void dispatchFinishTemporaryDetach() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onFinishTemporaryDetach() {
+ }
+
+ public KeyEvent.DispatcherState getKeyDispatcherState() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchKeyEventPreIme(KeyEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean isAccessibilityFocusedViewOrHost() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean canReceivePointerEvents() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean onFilterTouchEventForSecurity(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchTrackballEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchCapturedPointerEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchGenericMotionEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean dispatchHoverEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ 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;
+ }
+
+ public final boolean dispatchPointerEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void dispatchWindowFocusChanged(boolean hasFocus) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean hasWindowFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean hasImeFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void dispatchVisibilityChanged(@NonNull View changedView,
+ @Visibility int visibility) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
+ }
+
+ public void dispatchDisplayHint(@Visibility int hint) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void onDisplayHint(@Visibility int hint) {
+ }
+
+ public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void onWindowVisibilityChanged(@Visibility int visibility) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isAggregatedVisible() {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean dispatchVisibilityAggregated(boolean isVisible) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ public void onVisibilityAggregated(boolean isVisible) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Visibility
+ public int getWindowVisibility() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void getWindowVisibleDisplayFrame(Rect outRect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public void getWindowDisplayFrame(@NonNull Rect outRect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void dispatchConfigurationChanged(Configuration newConfig) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void onConfigurationChanged(Configuration newConfig) {
+ }
+
+ // void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ void needGlobalAttributesUpdate(boolean force) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty
+ public boolean isInTouchMode() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.CapturedViewProperty
+ public final Context getContext() {
+ return mContext;
+ }
+
+ public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ 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) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected ContextMenuInfo getContextMenuInfo() {
+ return null;
+ }
+
+ protected void onCreateContextMenu(ContextMenu menu) {
+ }
+
+ public boolean onTrackballEvent(MotionEvent event) {
+ return false;
+ }
+
+ public boolean onGenericMotionEvent(MotionEvent event) {
+ return false;
+ }
+
+ public boolean onHoverEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty
+ public boolean isHovered() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setHovered(boolean hovered) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onHoverChanged(boolean hovered) {
+ }
+
+ protected boolean handleScrollBarDragging(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean onTouchEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isInScrollingContainer() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void cancelLongPress() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTouchDelegate(TouchDelegate delegate) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public TouchDelegate getTouchDelegate() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void requestUnbufferedDispatch(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void requestUnbufferedDispatch(int source) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void setFlags(int flags, int mask) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void bringToFront() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void disableRotaryScrollFeedback() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+ throw new RuntimeException("Stub!");
+ }
+
+ 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() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setScrollX(int value) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setScrollY(int value) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final int getScrollX() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final int getScrollY() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "layout")
+ public final int getWidth() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "layout")
+ public final int getHeight() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void getDrawingRect(Rect outRect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final int getMeasuredWidth() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final int getMeasuredWidthAndState() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final int getMeasuredHeight() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final int getMeasuredHeightAndState() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final int getMeasuredState() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public Matrix getMatrix() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean hasIdentityMatrix() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void ensureTransformationInfo() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final Matrix getInverseMatrix() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public float getCameraDistance() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setCameraDistance(float distance) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getRotation() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setRotation(float rotation) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getRotationY() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setRotationY(float rotationY) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getRotationX() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setRotationX(float rotationX) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getScaleX() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setScaleX(float scaleX) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getScaleY() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setScaleY(float scaleY) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getPivotX() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setPivotX(float pivotX) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getPivotY() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setPivotY(float pivotY) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isPivotSet() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void resetPivot() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getAlpha() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean getHasOverlappingRendering() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public boolean hasOverlappingRendering() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean setAlphaNoInvalidation(float alpha) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void setAlphaInternal(float alpha) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTransitionAlpha(float alpha) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getTransitionAlpha() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setForceDarkAllowed(boolean allow) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public boolean isForceDarkAllowed() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.CapturedViewProperty
+ public final int getTop() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void setTop(int top) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.CapturedViewProperty
+ public final int getBottom() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isDirty() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void setBottom(int bottom) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.CapturedViewProperty
+ public final int getLeft() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void setLeft(int left) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.CapturedViewProperty
+ public final int getRight() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void setRight(int right) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getX() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setX(float x) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getY() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setY(float y) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getZ() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setZ(float z) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getElevation() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setElevation(float elevation) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getTranslationX() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTranslationX(float translationX) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getTranslationY() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTranslationY(float translationY) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public float getTranslationZ() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTranslationZ(float translationZ) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAnimationMatrix(@Nullable Matrix matrix) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public Matrix getAnimationMatrix() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public StateListAnimator getStateListAnimator() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setStateListAnimator(StateListAnimator stateListAnimator) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean getClipToOutline() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setClipToOutline(boolean clipToOutline) {
+ throw new RuntimeException("Stub!");
+ }
+
+
+ public void setOutlineProvider(ViewOutlineProvider provider) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public ViewOutlineProvider getOutlineProvider() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void invalidateOutline() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public boolean hasShadow() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setOutlineSpotShadowColor(@ColorInt int color) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @ColorInt int getOutlineSpotShadowColor() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setOutlineAmbientShadowColor(@ColorInt int color) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @ColorInt int getOutlineAmbientShadowColor() {
+ throw new RuntimeException("Stub!");
+ }
+
+
+ /** @hide */
+ public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void getHitRect(Rect outRect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /*package*/ final boolean pointInView(float localX, float localY) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean pointInView(float localX, float localY, float slop) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void getFocusedRect(Rect r) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean getGlobalVisibleRect(Rect r) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean getLocalVisibleRect(Rect r) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void offsetTopAndBottom(int offset) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void offsetLeftAndRight(int offset) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
+ public ViewGroup.LayoutParams getLayoutParams() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setLayoutParams(ViewGroup.LayoutParams params) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void resolveLayoutParams() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void scrollTo(int x, int y) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void scrollBy(int x, int y) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean awakenScrollBars() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean awakenScrollBars(int startDelay) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void invalidate(Rect dirty) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void invalidate(int l, int t, int r, int b) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void invalidate() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void invalidate(boolean invalidateCache) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
+ boolean fullInvalidate) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void damageInParent() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void invalidateParentCaches() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void invalidateParentIfNeeded() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void invalidateParentIfNeededAndWasQuickRejected() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public boolean isOpaque() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void computeOpaqueFlags() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean hasOpaqueScrollbars() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public Handler getHandler() {
+ throw new RuntimeException("Stub!");
+ }
+
+ // public ViewRootImpl getViewRootImpl() {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // public ThreadedRenderer getThreadedRenderer() {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ public boolean post(Runnable action) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean postDelayed(Runnable action, long delayMillis) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void postOnAnimation(Runnable action) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void postOnAnimationDelayed(Runnable action, long delayMillis) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean removeCallbacks(Runnable action) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void postInvalidate() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void postInvalidate(int left, int top, int right, int bottom) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void postInvalidateDelayed(long delayMilliseconds) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
+ int right, int bottom) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void postInvalidateOnAnimation() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void computeScroll() {
+ }
+
+ public boolean isHorizontalFadingEdgeEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isVerticalFadingEdgeEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getFadingEdge() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getFadingEdgeLength() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected float getTopFadingEdgeStrength() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected float getBottomFadingEdgeStrength() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected float getLeftFadingEdgeStrength() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected float getRightFadingEdgeStrength() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isHorizontalScrollBarEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isVerticalScrollBarEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void recomputePadding() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isScrollbarFadingEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getScrollBarDefaultDelayBeforeFade() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getScrollBarFadeDuration() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getScrollBarSize() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setScrollBarSize(int scrollBarSize) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setScrollBarStyle(@ScrollBarStyle int style) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ScrollBarStyle
+ public int getScrollBarStyle() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected int computeHorizontalScrollRange() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected int computeHorizontalScrollOffset() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected int computeHorizontalScrollExtent() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected int computeVerticalScrollRange() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected int computeVerticalScrollOffset() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected int computeVerticalScrollExtent() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean canScrollHorizontally(int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean canScrollVertically(int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void getScrollIndicatorBounds(@NonNull Rect out) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected final void onDrawScrollBars(@NonNull Canvas canvas) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean isVerticalScrollBarHidden() {
+ return false;
+ }
+
+ protected void onDrawHorizontalScrollBar(@NonNull Canvas canvas, Drawable scrollBar,
+ int l, int t, int r, int b) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void onDrawVerticalScrollBar(@NonNull Canvas canvas, Drawable scrollBar,
+ int l, int t, int r, int b) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void onDraw(@NonNull Canvas canvas) {
+ }
+
+ /*
+ * Caller is responsible for calling requestLayout if necessary.
+ * (This allows addViewInLayout to not request a new layout.)
+ */
+ void assignParent(ViewParent parent) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ protected void onAttachedToWindow() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean resolveRtlPropertiesIfNeeded() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public void resetRtlProperties() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void dispatchScreenStateChanged(int screenState) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onScreenStateChanged(int screenState) {
+ }
+
+ void dispatchMovedToDisplay(Display display, Configuration config) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onMovedToDisplay(int displayId, Configuration config) {
+ }
+
+ public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
+ }
+
+ public boolean resolveLayoutDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean canResolveLayoutDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public void resetResolvedLayoutDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isLayoutDirectionInherited() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isLayoutDirectionResolved() {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean isPaddingResolved() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void resolvePadding() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public void resetResolvedPadding() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void resetResolvedPaddingInternal() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ protected void onDetachedFromWindow() {
+ }
+
+ @CallSuper
+ protected void onDetachedFromWindowInternal() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public IBinder getWindowToken() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public WindowId getWindowId() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public IBinder getApplicationWindowToken() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public Display getDisplay() {
+ throw new RuntimeException("Stub!");
+ }
+
+ // /*package*/ IWindowSession getWindowSession() {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // protected IWindow getWindow() {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ int combineVisibility(int vis1, int vis2) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void fakeFocusAfterAttachingToWindow() {
+ throw new RuntimeException("Stub!");
+ }
+
+ // void dispatchAttachedToWindow(AttachInfo info, int visibility) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ void dispatchDetachedFromWindow() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void cancelPendingInputEvents() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void dispatchCancelPendingInputEvents() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onCancelPendingInputEvents() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void saveHierarchyState(SparseArray container) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void dispatchSaveInstanceState(SparseArray container) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ @Nullable protected Parcelable onSaveInstanceState() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void restoreHierarchyState(SparseArray container) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void dispatchRestoreInstanceState(SparseArray container) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ protected void onRestoreInstanceState(Parcelable state) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public long getDrawingTime() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setDuplicateParentStateEnabled(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isDuplicateParentStateEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setLayerType(@LayerType int layerType, @Nullable Paint paint) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // public void setRenderEffect(@Nullable RenderEffect renderEffect) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // public void setBackdropRenderEffect(@Nullable RenderEffect renderEffect) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ public void setLayerPaint(@Nullable Paint paint) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @LayerType
+ public int getLayerType() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void buildLayer() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean probablyHasInput() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ protected void destroyHardwareResources() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void setDrawingCacheEnabled(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public boolean isDrawingCacheEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @SuppressWarnings({"UnusedDeclaration"})
+ public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void dispatchGetDisplayList() {}
+
+ public boolean canHaveDisplayList() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @NonNull
+ public RenderNode updateDisplayListIfDirty() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public Bitmap getDrawingCache() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public Bitmap getDrawingCache(boolean autoScale) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void destroyDrawingCache() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void setDrawingCacheBackgroundColor(@ColorInt int color) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ @ColorInt
+ public int getDrawingCacheBackgroundColor() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void buildDrawingCache() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void buildDrawingCache(boolean autoScale) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ 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) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected int getFadeHeight(boolean offsetRequired) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public boolean isHardwareAccelerated() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setClipBounds(Rect clipBounds) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public Rect getClipBounds() {
+ throw new RuntimeException("Stub!");
+ }
+
+
+ public boolean getClipBounds(Rect outRect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void setDisplayListProperties(RenderNode renderNode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected final boolean drawsWithRenderNode(@NonNull Canvas canvas) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean draw(@NonNull Canvas canvas, ViewGroup parent, long drawingTime) {
+ throw new RuntimeException("Stub!");
+ }
+
+ static Paint getDebugPaint() {
+ throw new RuntimeException("Stub!");
+ }
+
+ final int dipsToPixels(int dips) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ public void draw(@NonNull Canvas canvas) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void setBackgroundBounds() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public ViewOverlay getOverlay() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ @ColorInt
+ public int getSolidColor() {
+ return 0;
+ }
+
+ public boolean isLayoutRequested() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static boolean isLayoutModeOptical(Object o) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static void setTraceLayoutSteps(boolean traceLayoutSteps) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static void setTracedRequestLayoutClassClass(String s) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public void layout(int l, int t, int r, int b) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ }
+
+ protected boolean setFrame(int left, int top, int right, int bottom) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ protected void onFinishInflate() {
+ }
+
+ public Resources getResources() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void invalidateDrawable(@NonNull Drawable drawable) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void unscheduleDrawable(Drawable who) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void resolveDrawables() {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean areDrawablesResolved() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
+ }
+
+ @TestApi
+ protected void resetResolvedDrawables() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void resetResolvedDrawablesInternal() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ protected boolean verifyDrawable(@NonNull Drawable who) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ protected void drawableStateChanged() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ public void drawableHotspotChanged(float x, float y) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void dispatchDrawableHotspotChanged(float x, float y) {
+ }
+
+ public void refreshDrawableState() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final int[] getDrawableState() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected int[] onCreateDrawableState(int extraSpace) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ public void jumpDrawablesToCurrentState() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setBackgroundColor(@ColorInt int color) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setBackgroundResource(@DrawableRes int resid) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setBackground(Drawable background) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void setBackgroundDrawable(Drawable background) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public Drawable getBackground() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setBackgroundTintList(@Nullable ColorStateList tint) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public ColorStateList getBackgroundTintList() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setBackgroundTintBlendMode(@Nullable BlendMode blendMode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public PorterDuff.Mode getBackgroundTintMode() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @Nullable BlendMode getBackgroundTintBlendMode() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public Drawable getForeground() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setForeground(Drawable foreground) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isForegroundInsidePadding() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getForegroundGravity() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setForegroundGravity(int gravity) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setForegroundTintList(@Nullable ColorStateList tint) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public ColorStateList getForegroundTintList() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setForegroundTintBlendMode(@Nullable BlendMode blendMode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public PorterDuff.Mode getForegroundTintMode() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @Nullable BlendMode getForegroundTintBlendMode() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onDrawForeground(@NonNull Canvas canvas) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setPadding(int left, int top, int right, int bottom) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void internalSetPadding(int left, int top, int right, int bottom) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setPaddingRelative(int start, int top, int end, int bottom) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @LayoutRes
+ public int getSourceLayoutResId() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getPaddingTop() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getPaddingBottom() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getPaddingLeft() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getPaddingStart() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getPaddingRight() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getPaddingEnd() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isPaddingRelative() {
+ throw new RuntimeException("Stub!");
+ }
+
+ Insets computeOpticalInsets() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void resetPaddingToInitialValues() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public Insets getOpticalInsets() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setOpticalInsets(Insets insets) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setSelected(boolean selected) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void dispatchSetSelected(boolean selected) {
+ }
+
+ @ViewDebug.ExportedProperty
+ public boolean isSelected() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setActivated(boolean activated) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void dispatchSetActivated(boolean activated) {
+ }
+
+ @ViewDebug.ExportedProperty
+ public boolean isActivated() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public ViewTreeObserver getViewTreeObserver() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public View getRootView() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean toGlobalMotionEvent(MotionEvent ev) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean toLocalMotionEvent(MotionEvent ev) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void transformMatrixToGlobal(@NonNull Matrix matrix) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void transformMatrixToLocal(@NonNull Matrix matrix) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void transformMatrixRootToLocal(@NonNull Matrix matrix) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
+ @ViewDebug.IntToString(from = 0, to = "x"),
+ @ViewDebug.IntToString(from = 1, to = "y")
+ })
+ public int[] getLocationOnScreen() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void getLocationOnScreen(@Size(2) int[] outLocation) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void getLocationInWindow(@Size(2) int[] outLocation) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected T findViewTraversal(@IdRes int id) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected T findViewWithTagTraversal(Object tag) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected T findViewByPredicateTraversal(Predicate predicate,
+ View childToSkip) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // Strictly speaking this should be marked as @Nullable but the nullability of the return value
+ // is deliberately left unspecified as idiomatically correct code can make assumptions either
+ // way based on local context, e.g. layout specification.
+ public final T findViewById(@IdRes int id) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @NonNull
+ public final T requireViewById(@IdRes int id) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public T findViewByAccessibilityIdTraversal(int accessibilityId) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public T findViewByAutofillIdTraversal(int autofillId) {
+ throw new RuntimeException("Stub!");
+ }
+
+
+ public void findAutofillableViewsByTraversal(@NonNull List autofillableViews) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final T findViewWithTag(Object tag) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final T findViewByPredicate(Predicate predicate) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final T findViewByPredicateInsideOut(
+ View start, Predicate predicate) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setId(@IdRes int id) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public void setIsRootNamespace(boolean isRoot) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isRootNamespace() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @IdRes
+ @ViewDebug.CapturedViewProperty
+ public int getId() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public long getUniqueDrawingId() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty
+ public Object getTag() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTag(final Object tag) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public Object getTag(int key) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTag(int key, final Object tag) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTagInternal(int key, Object tag) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void debug() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void debug(int depth) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected static String debugIndent(int depth) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "layout")
+ public int getBaseline() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isInLayout() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ public void requestLayout() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void forceLayout() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static int combineMeasuredStates(int curState, int newState) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static int resolveSize(int size, int measureSpec) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static int getDefaultSize(int size, int measureSpec) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected int getSuggestedMinimumHeight() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected int getSuggestedMinimumWidth() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getMinimumHeight() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setMinimumHeight(int minHeight) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getMinimumWidth() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setMinimumWidth(int minWidth) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public Animation getAnimation() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void startAnimation(Animation animation) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void clearAnimation() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAnimation(Animation animation) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ protected void onAnimationStart() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ protected void onAnimationEnd() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean onSetAlpha(int alpha) {
+ return false;
+ }
+
+ public boolean gatherTransparentRegion(@Nullable Region region) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void playSoundEffect(int soundConstant) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean performHapticFeedback(int feedbackConstant) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean performHapticFeedback(int feedbackConstant, int flags) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void performHapticFeedbackForInputDevice(int feedbackConstant, int inputDeviceId,
+ int inputSource, int flags) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void setSystemUiVisibility(int visibility) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public int getSystemUiVisibility() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public int getWindowSystemUiVisibility() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void onWindowSystemUiVisibilityChanged(int visible) {
+ }
+
+ @Deprecated
+ public void dispatchWindowSystemUiVisiblityChanged(int visible) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void dispatchSystemUiVisibilityChanged(int visibility) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ public void setDisabledSystemUiVisibility(int flags) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onSystemBarAppearanceChanged(int appearance) {
+ }
+
+ public static class DragShadowBuilder {
+ public DragShadowBuilder(View view) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public DragShadowBuilder() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @SuppressWarnings({"JavadocReference"})
+ final public View getView() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onDrawShadow(@NonNull Canvas canvas) {
+ throw new RuntimeException("Stub!");
+ }
+ }
+
+ @Deprecated
+ public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
+ Object myLocalState, int flags) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
+ Object myLocalState, int flags) {
+ throw new RuntimeException("Stub!");
+ }
+
+ static boolean hasActivityPendingIntents(ClipData data) {
+ throw new RuntimeException("Stub!");
+ }
+
+ static void cleanUpPendingIntents(ClipData data) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void setAccessibilityDragStarted(boolean started) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void cancelDragAndDrop() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean startMovingTask(float startX, float startY) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void finishMovingTask() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean onDragEvent(DragEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
+ boolean dispatchDragEnterExitInPreN(DragEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchDragEvent(DragEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ final boolean callDragEventHandler(DragEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean canAcceptDrag() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void sendWindowContentChangedAccessibilityEvent(int changeType) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onCloseSystemDialogs(String reason) {
+ }
+
+ public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @SuppressWarnings({"UnusedParameters"})
+ protected boolean overScrollBy(int deltaX, int deltaY,
+ int scrollX, int scrollY,
+ int scrollRangeX, int scrollRangeY,
+ int maxOverScrollX, int maxOverScrollY,
+ boolean isTouchEvent) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void onOverScrolled(int scrollX, int scrollY,
+ boolean clampedX, boolean clampedY) {
+ // Intentionally empty.
+ }
+
+ public int getOverScrollMode() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setOverScrollMode(int overScrollMode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setNestedScrollingEnabled(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isNestedScrollingEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean startNestedScroll(int axes) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void stopNestedScroll() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean hasNestedScrollingParent() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
+ int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchNestedPreScroll(int dx, int dy,
+ @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected float getVerticalScrollFactor() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected float getHorizontalScrollFactor() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getRawTextDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTextDirection(int textDirection) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getTextDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean resolveTextDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean canResolveTextDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public void resetResolvedTextDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isTextDirectionInherited() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isTextDirectionResolved() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TextAlignment
+ public int getRawTextAlignment() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTextAlignment(@TextAlignment int textAlignment) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TextAlignment
+ public int getTextAlignment() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean resolveTextAlignment() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean canResolveTextAlignment() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public void resetResolvedTextAlignment() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isTextAlignmentInherited() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isTextAlignmentResolved() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static int generateViewId() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void captureTransitioningViews(List transitioningViews) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void findNamedViews(Map namedElements) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setPointerIcon(PointerIcon pointerIcon) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public PointerIcon getPointerIcon() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean hasPointerCapture() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void requestPointerCapture() {
+ throw new RuntimeException("Stub!");
+ }
+
+
+ public void releasePointerCapture() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @CallSuper
+ public void onPointerCaptureChange(boolean hasCapture) {
+ }
+
+ public void dispatchPointerCaptureChanged(boolean hasCapture) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean onCapturedPointerEvent(MotionEvent event) {
+ return false;
+ }
+
+ public interface OnCapturedPointerListener {
+ boolean onCapturedPointer(View view, MotionEvent event);
+ }
+
+ public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // Properties
+ //
+ public static final Property ALPHA = null;
+
+ public static final Property TRANSLATION_X = null;
+
+ public static final Property TRANSLATION_Y = null;
+
+ public static final Property TRANSLATION_Z = null;
+
+ public static final Property X = null;
+
+ public static final Property Y = null;
+
+ public static final Property Z = null;
+
+ public static final Property ROTATION = null;
+
+ public static final Property ROTATION_X = null;
+
+ public static final Property ROTATION_Y = null;
+
+ public static final Property SCALE_X = null;
+
+ public static final Property SCALE_Y = null;
+
+ public static class MeasureSpec {
+ private static final int MODE_SHIFT = 30;
+
+ /** @hide */
+ @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) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static int makeSafeMeasureSpec(int size, int mode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @MeasureSpecMode
+ public static int getMode(int measureSpec) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static int getSize(int measureSpec) {
+ throw new RuntimeException("Stub!");
+ }
+
+ static int adjust(int measureSpec, int delta) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static String toString(int measureSpec) {
+ throw new RuntimeException("Stub!");
+ }
+ }
+
+ public ViewPropertyAnimator animate() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void setTransitionName(String transitionName) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty
+ public String getTransitionName() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void requestKeyboardShortcuts(List data, int deviceId) {
+ // Do nothing.
+ }
+
+ 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);
+ }
+
+ 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;
+
+ // Flags that describe what data in this state is valid
+ 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 CREATOR
+ = new Parcelable.ClassLoaderCreator() {
+ @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];
+ }
+ };
+ }
+
+ public static class AccessibilityDelegate {
+
+ public void sendAccessibilityEvent(@NonNull View host, int eventType) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean performAccessibilityAction(@NonNull View host, int action,
+ @Nullable Bundle args) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void sendAccessibilityEventUnchecked(@NonNull View host,
+ @NonNull AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean dispatchPopulateAccessibilityEvent(@NonNull View host,
+ @NonNull AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onPopulateAccessibilityEvent(@NonNull View host,
+ @NonNull AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onInitializeAccessibilityEvent(@NonNull View host,
+ @NonNull AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onInitializeAccessibilityNodeInfo(@NonNull View host,
+ @NonNull AccessibilityNodeInfo info) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
+ @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
+ @Nullable Bundle arguments) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean onRequestSendAccessibilityEvent(@NonNull ViewGroup host, @NonNull View child,
+ @NonNull AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public @Nullable AccessibilityNodeProvider getAccessibilityNodeProvider(
+ @NonNull View host) {
+ return null;
+ }
+
+ public AccessibilityNodeInfo createAccessibilityNodeInfo(@NonNull View host) {
+ throw new RuntimeException("Stub!");
+ }
+ }
+
+ @ScrollCaptureHint
+ public int getScrollCaptureHint() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setScrollCaptureHint(@ScrollCaptureHint int hint) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // public final void setScrollCaptureCallback(@Nullable ScrollCaptureCallback callback) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // /** {@hide} */
+ // @Nullable
+ // public ScrollCaptureCallback createScrollCaptureCallbackInternal(@NonNull Rect localVisibleRect,
+ // @NonNull Point windowOffset) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // public void dispatchScrollCaptureSearch(
+ // @NonNull Rect localVisibleRect, @NonNull Point windowOffset,
+ // @NonNull Consumer targets) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // public void onScrollCaptureSearch(@NonNull Rect localVisibleRect,
+ // @NonNull Point windowOffset, @NonNull Consumer targets) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // /** {@hide} */
+ // public void encode(@NonNull ViewHierarchyEncoder stream) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // /** {@hide} */
+ // @CallSuper
+ // protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ boolean shouldDrawRoundScrollbar() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTooltipText(@Nullable CharSequence tooltipText) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTooltip(@Nullable CharSequence tooltipText) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public CharSequence getTooltipText() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Nullable
+ public CharSequence getTooltip() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void hideTooltip() {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean dispatchTooltipHoverEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void handleTooltipKey(KeyEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public View getTooltipView() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ public static boolean isDefaultFocusHighlightEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ View dispatchUnhandledKeyEvent(KeyEvent evt) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean onUnhandledKeyEvent(@NonNull KeyEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean hasUnhandledKeyListener() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void setDetached(boolean detached) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setIsCredential(boolean isCredential) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isCredential() {
+ throw new RuntimeException("Stub!");
+ }
+
+ // TODO(316208691): Revive following removed API docs.
+ // @see EditorInfo#setStylusHandwritingEnabled(boolean)
+ public void setAutoHandwritingEnabled(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isAutoHandwritingEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isStylusHandwritingAvailable() {
+ throw new RuntimeException("Stub!");
+ }
+
+ // public void onCreateViewTranslationRequest(@NonNull int[] supportedFormats,
+ // @NonNull Consumer requestsCollector) {
+ // }
+
+ // @SuppressLint("NullableCollection")
+ // public void onCreateVirtualViewTranslationRequests(@NonNull long[] virtualIds,
+ // @NonNull int[] supportedFormats,
+ // @NonNull Consumer requestsCollector) {
+ // // no-op
+ // }
+
+ // @Nullable
+ // public ViewTranslationCallback getViewTranslationCallback() {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // public void setViewTranslationCallback(@NonNull ViewTranslationCallback callback) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // public void clearViewTranslationCallback() {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // @Nullable
+ // public ViewTranslationResponse getViewTranslationResponse() {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // public void onViewTranslationResponse(@NonNull ViewTranslationResponse response) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // public void clearViewTranslationResponse() {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // public void onVirtualViewTranslationResponses(
+ // @NonNull LongSparseArray response) {
+ // // no-op
+ // }
+
+ // public void dispatchCreateViewTranslationRequest(@NonNull Map viewIds,
+ // @NonNull int[] supportedFormats,
+ // @NonNull TranslationCapability capability,
+ // @NonNull List requests) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // public void generateDisplayHash(@NonNull String hashAlgorithm,
+ // @Nullable Rect bounds, @NonNull Executor executor,
+ // @NonNull DisplayHashResultCallback callback) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ /**
+ * The AttachedSurfaceControl itself is not a View, it is just the interface to the
+ * windowing-system object that contains the entire view hierarchy.
+ * For the root View of a given hierarchy see {@link #getRootView}.
+
+ * @return The {@link android.view.AttachedSurfaceControl} interface for this View.
+ * This will only return a non-null value when called between {@link #onAttachedToWindow}
+ * and {@link #onDetachedFromWindow}.
+ */
+ // public @Nullable AttachedSurfaceControl getRootSurfaceControl() {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ protected int calculateFrameRateCategory() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void votePreferredFrameRate() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setFrameContentVelocity(float pixelsPerSecond) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public float getFrameContentVelocity() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setRequestedFrameRate(float frameRate) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public float getRequestedFrameRate() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void overrideFrameRate(float frameRate, boolean forceOverride) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void setForcedOverrideFrameRateFlag(boolean forcedOverride) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean getForcedOverrideFrameRateFlag() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void setSelfRequestedFrameRateFlag(boolean forcedOverride) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean getSelfRequestedFrameRateFlag() {
+ throw new RuntimeException("Stub!");
+ }
+
+ // public void reportAppJankStats(@NonNull AppJankStats appJankStats) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // public @Nullable JankTracker getJankTracker() {
+ // throw new RuntimeException("Stub!");
+ // }
+}
diff --git a/AndroidCompat/src/main/java/android/view/ViewGroup.java b/AndroidCompat/src/main/java/android/view/ViewGroup.java
new file mode 100644
index 00000000..396aaa87
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/view/ViewGroup.java
@@ -0,0 +1,1787 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.animation.LayoutTransition;
+import android.annotation.CallSuper;
+import android.annotation.IdRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.annotation.UiThread;
+import android.content.ClipData;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Insets;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.WindowInsetsAnimation.Bounds;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.LayoutAnimationController;
+import android.view.animation.Transformation;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
+import android.webkit.WebView;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+@UiThread
+public abstract class ViewGroup extends View implements ViewParent, ViewManager {
+ protected ArrayList mDisappearingChildren;
+
+ protected OnHierarchyChangeListener mOnHierarchyChangeListener;
+
+ // The last child of this ViewGroup which held focus within the current cluster
+ View mFocusedInCluster;
+
+ RectF mInvalidateRegion;
+
+ Transformation mInvalidationTransformation;
+
+ protected int mGroupFlags;
+
+
+ // When set, ViewGroup invalidates only the child's rectangle
+ // Set by default
+ static final int FLAG_CLIP_CHILDREN = 0x1;
+
+ // When set, dispatchDraw() will invoke invalidate(); this is set by drawChild() when
+ // a child needs to be invalidated and FLAG_OPTIMIZE_INVALIDATE is set
+ static final int FLAG_INVALIDATE_REQUIRED = 0x4;
+
+ // When set, there is either no layout animation on the ViewGroup or the layout
+ // animation is over
+ // Set by default
+ static final int FLAG_ANIMATION_DONE = 0x10;
+
+ // When set, this ViewGroup converts calls to invalidate(Rect) to invalidate() during a
+ // layout animation; this avoid clobbering the hierarchy
+ // Automatically set when the layout animation starts, depending on the animation's
+ // characteristics
+ static final int FLAG_OPTIMIZE_INVALIDATE = 0x80;
+
+ // When set, the next call to drawChild() will clear mChildTransformation's matrix
+ static final int FLAG_CLEAR_TRANSFORMATION = 0x100;
+
+ protected static final int FLAG_USE_CHILD_DRAWING_ORDER = 0x400;
+
+ protected static final int FLAG_SUPPORT_STATIC_TRANSFORMATIONS = 0x800;
+
+ // UNUSED FLAG VALUE: 0x1000;
+
+ public static final int FOCUS_BEFORE_DESCENDANTS = 0x20000;
+
+ public static final int FOCUS_AFTER_DESCENDANTS = 0x40000;
+
+ public static final int FOCUS_BLOCK_DESCENDANTS = 0x60000;
+
+ protected static final int FLAG_DISALLOW_INTERCEPT = 0x80000;
+
+ static final int FLAG_IS_TRANSITION_GROUP = 0x1000000;
+
+ static final int FLAG_IS_TRANSITION_GROUP_SET = 0x2000000;
+
+ static final int FLAG_TOUCHSCREEN_BLOCKS_FOCUS = 0x4000000;
+
+ protected int mPersistentDrawingCache;
+
+ @Deprecated
+ public static final int PERSISTENT_NO_CACHE = 0x0;
+
+ @Deprecated
+ public static final int PERSISTENT_ANIMATION_CACHE = 0x1;
+
+ @Deprecated
+ public static final int PERSISTENT_SCROLLING_CACHE = 0x2;
+
+ @Deprecated
+ public static final int PERSISTENT_ALL_CACHES = 0x3;
+
+ // Layout Modes
+
+ public static final int LAYOUT_MODE_CLIP_BOUNDS = 0;
+
+ public static final int LAYOUT_MODE_OPTICAL_BOUNDS = 1;
+
+ /** @hide */
+ public static int LAYOUT_MODE_DEFAULT = LAYOUT_MODE_CLIP_BOUNDS;
+
+ protected static final int CLIP_TO_PADDING_MASK = 0;
+
+ // Whether layout calls are currently being suppressed, controlled by calls to
+ // suppressLayout()
+ boolean mSuppressLayout = false;
+
+ // Used to draw cached views
+ Paint mCachePaint;
+
+ int mChildUnhandledKeyListeners = 0;
+
+ public ViewGroup(Context context) {
+ this(context, null);
+ }
+
+ public ViewGroup(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public ViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public int getDescendantFocusability() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setDescendantFocusability(int focusability) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void requestChildFocus(View child, View focused) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void setDefaultFocus(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void clearDefaultFocus(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ boolean hasDefaultFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void clearFocusedInCluster(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void clearFocusedInCluster() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void focusableViewAvailable(View v) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean showContextMenuForChild(View originalView) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final boolean isShowingContextMenuWithCoords() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean showContextMenuForChild(View originalView, float x, float y) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public ActionMode startActionModeForChild(
+ View originalView, ActionMode.Callback callback, int type) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean dispatchActivityResult(
+ String who, int requestCode, int resultCode, Intent data) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public View focusSearch(View focused, int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
+ return false;
+ }
+
+ @Override
+ public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean onRequestSendAccessibilityEventInternal(View child, AccessibilityEvent event) {
+ return true;
+ }
+
+ @Override
+ public void childHasTransientStateChanged(View child, boolean childHasTransientState) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean hasTransientState() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean dispatchUnhandledMove(View focused, int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void clearChildFocus(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void clearFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ void unFocus(View focused) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public View getFocusedChild() {
+ throw new RuntimeException("Stub!");
+ }
+
+ View getDeepestFocusedChild() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean hasFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.view.View#findFocus()
+ */
+ @Override
+ public View findFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean hasFocusableChild(boolean dispatchExplicit) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void addFocusables(ArrayList views, int direction, int focusableMode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void addKeyboardNavigationClusters(Collection views, int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTouchscreenBlocksFocus(boolean touchscreenBlocksFocus) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "focus")
+ public boolean getTouchscreenBlocksFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean shouldBlockFocusForTouchscreen() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void findViewsWithText(ArrayList outViews, CharSequence text, int flags) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ @Override
+ public View findViewByAccessibilityIdTraversal(int accessibilityId) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ @Override
+ public View findViewByAutofillIdTraversal(int autofillId) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ @Override
+ public void findAutofillableViewsByTraversal(@NonNull List autofillableViews) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void dispatchWindowFocusChanged(boolean hasFocus) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void addTouchables(ArrayList views) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void makeOptionalFitsSystemWindows() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void makeFrameworkOptionalFitsSystemWindows() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void dispatchDisplayHint(int hint) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void onChildVisibilityChanged(View child, int oldVisibility, int newVisibility) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected void dispatchVisibilityChanged(View changedView, int visibility) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void dispatchWindowVisibilityChanged(int visibility) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ boolean dispatchVisibilityAggregated(boolean isVisible) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void dispatchConfigurationChanged(Configuration newConfig) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void recomputeViewAttributes(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // @Override
+ // void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ @Override
+ public void bringChildToFront(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ boolean dispatchDragEnterExitInPreN(DragEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // TODO: Write real docs
+ @Override
+ public boolean dispatchDragEvent(DragEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // Find the frontmost child view that lies under the given point, and calculate
+ // the position within its own local coordinate system.
+ View findFrontmostDroppableChildAt(float x, float y, PointF outLocalPoint) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean notifyChildOfDragStart(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ @Deprecated
+ public void dispatchWindowSystemUiVisiblityChanged(int visible) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ @Deprecated
+ public void dispatchSystemUiVisibilityChanged(int visible) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean dispatchKeyEventPreIme(KeyEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean dispatchTrackballEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean dispatchCapturedPointerEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void dispatchPointerCaptureChanged(boolean hasCapture) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @SuppressWarnings({"ConstantConditions"})
+ @Override
+ protected boolean dispatchHoverEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ boolean dispatchTooltipHoverEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ @Override
+ protected boolean hasHoveredChild() {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ @Override
+ protected boolean pointInHoveredChild(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void addChildrenForAccessibility(ArrayList outChildren) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean onInterceptHoverEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected boolean dispatchGenericPointerEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public ArrayList buildTouchDispatchChildList() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean isTransformedTouchPointInView(float x, float y, View child,
+ PointF outLocalPoint) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void transformPointToViewLocal(float[] point, View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setMotionEventSplittingEnabled(boolean split) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isMotionEventSplittingEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isTransitionGroup() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setTransitionGroup(boolean isTransitionGroup) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @SuppressWarnings({"ConstantConditions"})
+ protected boolean onRequestFocusInDescendants(int direction,
+ Rect previouslyFocusedRect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean restoreDefaultFocus() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ @Override
+ public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean restoreFocusNotInCluster() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void dispatchStartTemporaryDetach() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void dispatchFinishTemporaryDetach() {
+ throw new RuntimeException("Stub!");
+ }
+
+ // @Override
+ // void dispatchAttachedToWindow(AttachInfo info, int visibility) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ @Override
+ void dispatchScreenStateChanged(int screenState) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ void dispatchMovedToDisplay(Display display, Configuration config) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ @Override
+ public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void dispatchProvideStructure(ViewStructure structure) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void dispatchProvideAutofillStructure(ViewStructure structure,
+ @AutofillFlags int flags) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ @Override
+ public void dispatchProvideContentCaptureStructure() {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ @Override
+ public void resetSubtreeAutofillIds() {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ @Override
+ public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void addExtraDataToAccessibilityNodeInfo(@NonNull AccessibilityNodeInfo info,
+ @NonNull String extraDataKey, @Nullable Bundle arguments) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public CharSequence getAccessibilityClassName() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void notifySubtreeAccessibilityStateChanged(View child, View source, int changeType) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ @Override
+ public void notifySubtreeAccessibilityStateChangedIfNeeded() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ void resetSubtreeAccessibilityStateChanged() {
+ throw new RuntimeException("Stub!");
+ }
+
+ int getNumChildrenForAccessibility() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle args) {
+ return false;
+ }
+
+ @Override
+ void calculateAccessibilityDataSensitive() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ void dispatchDetachedFromWindow() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected void internalSetPadding(int left, int top, int right, int bottom) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected void dispatchSaveInstanceState(SparseArray container) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void dispatchFreezeSelfOnly(SparseArray container) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected void dispatchRestoreInstanceState(SparseArray container) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void dispatchThawSelfOnly(SparseArray container) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ protected void setChildrenDrawingCacheEnabled(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // @Override
+ // public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ /** Return true if this ViewGroup is laying out using optical bounds. */
+ boolean isLayoutModeOptical() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ Insets computeOpticalInsets() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void onDebugDrawMargins(@NonNull Canvas canvas, Paint paint) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void onDebugDraw(@NonNull Canvas canvas) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected void dispatchDraw(@NonNull Canvas canvas) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public ViewGroupOverlay getOverlay() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected int getChildDrawingOrder(int childCount, int drawingPosition) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final int getChildDrawingOrder(int drawingPosition) {
+ throw new RuntimeException("Stub!");
+ }
+
+ ArrayList buildOrderedChildList() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected void dispatchGetDisplayList() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean drawChild(@NonNull Canvas canvas, View child, long drawingTime) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ void getScrollIndicatorBounds(@NonNull Rect out) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public boolean getClipChildren() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setClipChildren(boolean clipChildren) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setClipToPadding(boolean clipToPadding) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public boolean getClipToPadding() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void dispatchSetSelected(boolean selected) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void dispatchSetActivated(boolean activated) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected void dispatchSetPressed(boolean pressed) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void dispatchDrawableHotspotChanged(float x, float y) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ void dispatchCancelPendingInputEvents() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void setStaticTransformationsEnabled(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean getChildStaticTransformation(View child, Transformation t) {
+ return false;
+ }
+
+ Transformation getChildTransformation() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected T findViewTraversal(@IdRes int id) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected T findViewWithTagTraversal(Object tag) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected T findViewByPredicateTraversal(Predicate predicate,
+ View childToSkip) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addTransientView(View view, int index) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void removeTransientView(View view) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getTransientViewCount() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getTransientViewIndex(int position) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public View getTransientView(int position) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addView(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addView(View child, int index) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addView(View child, int width, int height) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void addView(View child, LayoutParams params) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void addView(View child, int index, LayoutParams params) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public interface OnHierarchyChangeListener {
+ void onChildViewAdded(View parent, View child);
+
+ void onChildViewRemoved(View parent, View child);
+ }
+
+ public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void dispatchViewAdded(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onViewAdded(View child) {
+ }
+
+ void dispatchViewRemoved(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onViewRemoved(View child) {
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ @Override
+ protected void destroyHardwareResources() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean addViewInLayout(View child, int index, LayoutParams params) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected boolean addViewInLayout(View child, int index, LayoutParams params,
+ boolean preventRequestLayout) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void cleanupLayoutState(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void attachLayoutAnimationParameters(View child,
+ LayoutParams params, int index, int count) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void removeView(View view) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void removeViewInLayout(View view) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void removeViewsInLayout(int start, int count) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void removeViewAt(int index) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void removeViews(int start, int count) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setLayoutTransition(LayoutTransition transition) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public LayoutTransition getLayoutTransition() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void removeAllViews() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void removeAllViewsInLayout() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void removeDetachedView(View child, boolean animate) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void attachViewToParent(View child, int index, LayoutParams params) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void detachViewFromParent(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void detachViewFromParent(int index) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void detachViewsFromParent(int start, int count) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void detachAllViewsFromParent() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ @CallSuper
+ public void onDescendantInvalidated(@NonNull View child, @NonNull View target) {
+ throw new RuntimeException("Stub!");
+ }
+
+
+ @Deprecated
+ @Override
+ public final void invalidateChild(View child, final Rect dirty) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ @Override
+ public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void offsetDescendantRectToMyCoords(View descendant, Rect rect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void offsetRectIntoDescendantCoords(View descendant, Rect rect) {
+ throw new RuntimeException("Stub!");
+ }
+
+ void offsetRectBetweenParentAndChild(View descendant, Rect rect,
+ boolean offsetFromChildToParent, boolean clipToBounds) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void offsetChildrenTopAndBottom(int offset) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean getChildVisibleRect(
+ View child, Rect r, android.graphics.Point offset, boolean forceParentCheck) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public final void layout(int l, int t, int r, int b) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected abstract void onLayout(boolean changed,
+ int l, int t, int r, int b);
+
+ protected boolean canAnimate() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void startLayoutAnimation() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void scheduleLayoutAnimation() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setLayoutAnimation(LayoutAnimationController controller) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public LayoutAnimationController getLayoutAnimation() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public boolean isAnimationCacheEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void setAnimationCacheEnabled(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public boolean isAlwaysDrawnWithCacheEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void setAlwaysDrawnWithCacheEnabled(boolean always) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ protected boolean isChildrenDrawnWithCacheEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ protected void setChildrenDrawnWithCacheEnabled(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @ViewDebug.ExportedProperty(category = "drawing")
+ protected boolean isChildrenDrawingOrderEnabled() {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void setChildrenDrawingOrderEnabled(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ @ViewDebug.ExportedProperty(category = "drawing", mapping = {
+ @ViewDebug.IntToString(from = PERSISTENT_NO_CACHE, to = "NONE"),
+ @ViewDebug.IntToString(from = PERSISTENT_ANIMATION_CACHE, to = "ANIMATION"),
+ @ViewDebug.IntToString(from = PERSISTENT_SCROLLING_CACHE, to = "SCROLLING"),
+ @ViewDebug.IntToString(from = PERSISTENT_ALL_CACHES, to = "ALL")
+ })
+ public int getPersistentDrawingCache() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public void setPersistentDrawingCache(int drawingCacheToKeep) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // @Override
+ void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getLayoutMode() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setLayoutMode(int layoutMode) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public LayoutParams generateLayoutParams(AttributeSet attrs) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected LayoutParams generateDefaultLayoutParams() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected void debug(int depth) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int indexOfChild(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getChildCount() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public View getChildAt(int index) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void measureChild(View child, int parentWidthMeasureSpec,
+ int parentHeightMeasureSpec) {
+ throw new RuntimeException("Stub!");
+ }
+
+ protected void measureChildWithMargins(View child,
+ int parentWidthMeasureSpec, int widthUsed,
+ int parentHeightMeasureSpec, int heightUsed) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
+ throw new RuntimeException("Stub!");
+ }
+
+
+ public void clearDisappearingChildren() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void finishAnimatingView(final View view, Animation animation) {
+ throw new RuntimeException("Stub!");
+ }
+
+ boolean isViewTransitioning(View view) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void startViewTransition(View view) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void endViewTransition(View view) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void suppressLayout(boolean suppress) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isLayoutSuppressed() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean gatherTransparentRegion(Region region) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void requestTransparentRegion(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // @Override
+ public void subtractObscuredTouchableRegion(Region touchableRegion, View view) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // @Override
+ public boolean getChildLocalHitRegion(@NonNull View child, @NonNull Region region,
+ @NonNull Matrix matrix, boolean isHover) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void setWindowInsetsAnimationCallback(
+ @Nullable WindowInsetsAnimation.Callback callback) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean hasWindowInsetsAnimationCallback() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void dispatchWindowInsetsAnimationPrepare(
+ @NonNull WindowInsetsAnimation animation) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ @NonNull
+ public Bounds dispatchWindowInsetsAnimationStart(
+ @NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ @NonNull
+ public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
+ @NonNull List runningAnimations) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // @Override
+ // public void dispatchScrollCaptureSearch(
+ // @NonNull Rect localVisibleRect, @NonNull Point windowOffset,
+ // @NonNull Consumer targets) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ public Animation.AnimationListener getLayoutAnimationListener() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected void drawableStateChanged() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void jumpDrawablesToCurrentState() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected int[] onCreateDrawableState(int extraSpace) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setAddStatesFromChildren(boolean addsStates) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean addStatesFromChildren() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void childDrawableStateChanged(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setLayoutAnimationListener(Animation.AnimationListener animationListener) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void requestTransitionStart(LayoutTransition transition) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean resolveRtlPropertiesIfNeeded() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean resolveLayoutDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean resolveTextDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean resolveTextAlignment() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void resolvePadding() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected void resolveDrawables() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void resolveLayoutParams() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ @Override
+ public void resetResolvedLayoutDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ @Override
+ public void resetResolvedTextDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ @Override
+ public void resetResolvedTextAlignment() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ @Override
+ public void resetResolvedPadding() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @TestApi
+ @Override
+ protected void resetResolvedDrawables() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean shouldDelayChildPressedState() {
+ return true;
+ }
+
+ @Override
+ public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
+ return false;
+ }
+
+ @Override
+ public void onNestedScrollAccepted(View child, View target, int axes) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void onStopNestedScroll(View child) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
+ int dxUnconsumed, int dyUnconsumed) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getNestedScrollAxes() {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ protected void onSetLayoutParams(View child, LayoutParams layoutParams) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ @Override
+ public void captureTransitioningViews(List transitioningViews) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /** @hide */
+ @Override
+ public void findNamedViews(Map namedElements) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ boolean hasUnhandledKeyListener() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void incrementChildUnhandledKeyListeners() {
+ throw new RuntimeException("Stub!");
+ }
+
+ void decrementChildUnhandledKeyListeners() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ View dispatchUnhandledKeyEvent(KeyEvent evt) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static class LayoutParams {
+ @SuppressWarnings({"UnusedDeclaration"})
+ @Deprecated
+ public static final int FILL_PARENT = -1;
+
+ public static final int MATCH_PARENT = -1;
+
+ public static final int WRAP_CONTENT = -2;
+
+ public int width;
+
+ public int height;
+
+ public LayoutAnimationController.AnimationParameters layoutAnimationParameters;
+
+ public LayoutParams(Context c, AttributeSet attrs) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public LayoutParams(int width, int height) {
+ this.width = width;
+ this.height = height;
+ }
+
+ public LayoutParams(LayoutParams source) {
+ this.width = source.width;
+ this.height = source.height;
+ }
+
+ LayoutParams() {
+ }
+
+ protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void resolveLayoutDirection(int layoutDirection) {
+ }
+
+ public String debug(String output) {
+ return output + "ViewGroup.LayoutParams={ width="
+ + sizeToString(width) + ", height=" + sizeToString(height) + " }";
+ }
+
+ public void onDebugDraw(View view, Canvas canvas, Paint paint) {
+ }
+
+ protected static String sizeToString(int size) {
+ if (size == WRAP_CONTENT) {
+ return "wrap-content";
+ }
+ if (size == MATCH_PARENT) {
+ return "match-parent";
+ }
+ return String.valueOf(size);
+ }
+
+ // /** @hide */
+ // void encode(@NonNull ViewHierarchyEncoder encoder) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // /** @hide */
+ // protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+ // throw new RuntimeException("Stub!");
+ // }
+ }
+
+ public static class MarginLayoutParams extends ViewGroup.LayoutParams {
+ @ViewDebug.ExportedProperty(category = "layout")
+ public int leftMargin;
+
+ @ViewDebug.ExportedProperty(category = "layout")
+ public int topMargin;
+
+ @ViewDebug.ExportedProperty(category = "layout")
+ public int rightMargin;
+
+ @ViewDebug.ExportedProperty(category = "layout")
+ public int bottomMargin;
+
+ byte mMarginFlags;
+
+ public MarginLayoutParams(Context c, AttributeSet attrs) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public MarginLayoutParams(int width, int height) {
+ super(width, height);
+ throw new RuntimeException("Stub!");
+ }
+
+ public MarginLayoutParams(MarginLayoutParams source) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public MarginLayoutParams(LayoutParams source) {
+ super(source);
+ throw new RuntimeException("Stub!");
+ }
+
+ public final void copyMarginsFrom(MarginLayoutParams source) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setMargins(int left, int top, int right, int bottom) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setMarginsRelative(int start, int top, int end, int bottom) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setMarginStart(int start) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getMarginStart() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setMarginEnd(int end) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getMarginEnd() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isMarginRelative() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setLayoutDirection(int layoutDirection) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getLayoutDirection() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void resolveLayoutDirection(int layoutDirection) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public boolean isLayoutRtl() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public void onDebugDraw(View view, Canvas canvas, Paint paint) {
+ throw new RuntimeException("Stub!");
+ }
+
+ // /** @hide */
+ // @Override
+ // protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+ // throw new RuntimeException("Stub!");
+ // }
+ }
+
+ static class ChildListForAccessibility {
+
+ public static ChildListForAccessibility obtain(ViewGroup parent, boolean sort) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void recycle() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public int getChildCount() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public View getChildAt(int index) {
+ throw new RuntimeException("Stub!");
+ }
+ }
+
+ static class ViewLocationHolder implements Comparable {
+
+ public static final int COMPARISON_STRATEGY_STRIPE = 1;
+
+ public static final int COMPARISON_STRATEGY_LOCATION = 2;
+
+ public View mView;
+
+ public static ViewLocationHolder obtain(ViewGroup root, View view) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static void setComparisonStrategy(int strategy) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void recycle() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public int compareTo(ViewLocationHolder another) {
+ throw new RuntimeException("Stub!");
+ }
+ }
+
+ // /** @hide */
+ // @Override
+ // protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ /** @hide */
+ // @Override
+ public final void onDescendantUnbufferedRequested() {
+ throw new RuntimeException("Stub!");
+ }
+
+ // @Override
+ // public void dispatchCreateViewTranslationRequest(@NonNull Map viewIds,
+ // @NonNull int[] supportedFormats,
+ // @Nullable TranslationCapability capability,
+ // @NonNull List requests) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ // @Nullable
+ // @Override
+ // public OnBackInvokedDispatcher findOnBackInvokedDispatcherForChild(@NonNull View child,
+ // @NonNull View requester) {
+ // throw new RuntimeException("Stub!");
+ // }
+
+ @Override
+ public void setRequestedFrameRate(float frameRate) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void propagateRequestedFrameRate(float frameRate, boolean forceOverride) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ void overrideFrameRate(float frameRate, boolean forceOverride) {
+ throw new RuntimeException("Stub!");
+ }
+}
diff --git a/AndroidCompat/src/main/java/android/webkit/WebChromeClient.java b/AndroidCompat/src/main/java/android/webkit/WebChromeClient.java
new file mode 100644
index 00000000..4efc6be1
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/webkit/WebChromeClient.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Message;
+import android.view.View;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+public class WebChromeClient {
+
+ public void onProgressChanged(WebView view, int newProgress) {}
+
+ public void onReceivedTitle(WebView view, String title) {}
+
+ public void onReceivedIcon(WebView view, Bitmap icon) {}
+
+ public void onReceivedTouchIconUrl(WebView view, String url,
+ boolean precomposed) {}
+
+ public interface CustomViewCallback {
+ public void onCustomViewHidden();
+ }
+
+ public void onShowCustomView(View view, CustomViewCallback callback) {};
+
+ @Deprecated
+ public void onShowCustomView(View view, int requestedOrientation,
+ CustomViewCallback callback) {};
+
+ public void onHideCustomView() {}
+
+ public boolean onCreateWindow(WebView view, boolean isDialog,
+ boolean isUserGesture, Message resultMsg) {
+ return false;
+ }
+
+ public void onRequestFocus(WebView view) {}
+
+ public void onCloseWindow(WebView window) {}
+
+ public boolean onJsAlert(WebView view, String url, String message,
+ JsResult result) {
+ return false;
+ }
+
+ public boolean onJsConfirm(WebView view, String url, String message,
+ JsResult result) {
+ return false;
+ }
+
+ public boolean onJsPrompt(WebView view, String url, String message,
+ String defaultValue, JsPromptResult result) {
+ return false;
+ }
+
+ public boolean onJsBeforeUnload(WebView view, String url, String message,
+ JsResult result) {
+ return false;
+ }
+
+ @Deprecated
+ public void onExceededDatabaseQuota(String url, String databaseIdentifier,
+ long quota, long estimatedDatabaseSize, long totalQuota,
+ WebStorage.QuotaUpdater quotaUpdater) {
+ // This default implementation passes the current quota back to WebCore.
+ // WebCore will interpret this that new quota was declined.
+ quotaUpdater.updateQuota(quota);
+ }
+
+ @Deprecated
+ public void onReachedMaxAppCacheSize(long requiredStorage, long quota,
+ WebStorage.QuotaUpdater quotaUpdater) {
+ quotaUpdater.updateQuota(quota);
+ }
+
+ public void onGeolocationPermissionsShowPrompt(String origin,
+ GeolocationPermissions.Callback callback) {}
+
+ public void onGeolocationPermissionsHidePrompt() {}
+
+ public void onPermissionRequest(PermissionRequest request) {
+ request.deny();
+ }
+
+ public void onPermissionRequestCanceled(PermissionRequest request) {}
+
+ // This method was only called when using the JSC javascript engine. V8 became
+ // the default JS engine with Froyo and support for building with JSC was
+ // removed in b/5495373. V8 does not have a mechanism for making a callback such
+ // as this.
+ @Deprecated
+ public boolean onJsTimeout() {
+ return true;
+ }
+
+ @Deprecated
+ public void onConsoleMessage(String message, int lineNumber, String sourceID) { }
+
+ public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
+ // Call the old version of this function for backwards compatability.
+ onConsoleMessage(consoleMessage.message(), consoleMessage.lineNumber(),
+ consoleMessage.sourceId());
+ return false;
+ }
+
+ @Nullable
+ public Bitmap getDefaultVideoPoster() {
+ return null;
+ }
+
+ @Nullable
+ public View getVideoLoadingProgressView() {
+ return null;
+ }
+
+ /** Obtains a list of all visited history items, used for link coloring
+ */
+ public void getVisitedHistory(ValueCallback callback) {
+ }
+
+ public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback,
+ FileChooserParams fileChooserParams) {
+ return false;
+ }
+
+ public static abstract class FileChooserParams {
+ @SystemApi
+ public static final long ENABLE_FILE_SYSTEM_ACCESS = 364980165L;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Mode {}
+
+ /** Open single file. Requires that the file exists before allowing the user to pick it. */
+ public static final int MODE_OPEN = 0;
+ /** Like Open but allows multiple files to be selected. */
+ public static final int MODE_OPEN_MULTIPLE = 1;
+ /** Like Open but allows a folder to be selected. */
+ public static final int MODE_OPEN_FOLDER = 2;
+ /** Allows picking a nonexistent file and saving it. */
+ public static final int MODE_SAVE = 3;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PermissionMode {}
+
+ /** File or directory should be opened for reading only. */
+ public static final int PERMISSION_MODE_READ = 0;
+ /** File or directory should be opened for read and write. */
+ public static final int PERMISSION_MODE_READ_WRITE = 1;
+
+ @Nullable
+ public static Uri[] parseResult(int resultCode, Intent data) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Mode
+ public abstract int getMode();
+
+ public abstract String[] getAcceptTypes();
+
+ public abstract boolean isCaptureEnabled();
+
+ @Nullable
+ public abstract CharSequence getTitle();
+
+ @Nullable
+ public abstract String getFilenameHint();
+
+ @PermissionMode
+ public int getPermissionMode() {
+ return PERMISSION_MODE_READ;
+ }
+
+ public abstract Intent createIntent();
+ }
+
+ @SystemApi
+ @Deprecated
+ public void openFileChooser(ValueCallback uploadFile, String acceptType, String capture) {
+ uploadFile.onReceiveValue(null);
+ }
+}
diff --git a/AndroidCompat/src/main/java/android/webkit/WebSettings.java b/AndroidCompat/src/main/java/android/webkit/WebSettings.java
new file mode 100644
index 00000000..54c622e5
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/webkit/WebSettings.java
@@ -0,0 +1,1757 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.Context;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Manages settings state for a WebView. When a WebView is first created, it
+ * obtains a set of default settings. These default settings will be returned
+ * from any getter call. A {@code WebSettings} object obtained from
+ * {@link WebView#getSettings()} is tied to the life of the WebView. If a WebView has
+ * been destroyed, any method call on {@code WebSettings} will throw an
+ * {@link IllegalStateException}.
+ */
+// This is an abstract base class: concrete WebViewProviders must
+// create a class derived from this, and return an instance of it in the
+// WebViewProvider.getWebSettingsProvider() method implementation.
+public abstract class WebSettings {
+ /**
+ * Enum for controlling the layout of html.
+ *
+ * - {@code NORMAL} means no rendering changes. This is the recommended choice for maximum
+ * compatibility across different platforms and Android versions.
+ * - {@code SINGLE_COLUMN} moves all content into one column that is the width of the
+ * view.
+ * - {@code NARROW_COLUMNS} makes all columns no wider than the screen if possible. Only use
+ * this for API levels prior to {@link android.os.Build.VERSION_CODES#KITKAT}.
+ * - {@code TEXT_AUTOSIZING} boosts font size of paragraphs based on heuristics to make
+ * the text readable when viewing a wide-viewport layout in the overview mode.
+ * It is recommended to enable zoom support {@link #setSupportZoom} when
+ * using this mode. Supported from API level
+ * {@link android.os.Build.VERSION_CODES#KITKAT}
+ *
+ */
+ // XXX: These must match LayoutAlgorithm in Settings.h in WebCore.
+ public enum LayoutAlgorithm {
+ NORMAL,
+ /**
+ * @deprecated This algorithm is now obsolete.
+ */
+ @Deprecated
+ SINGLE_COLUMN,
+ /**
+ * @deprecated This algorithm is now obsolete.
+ */
+ @Deprecated
+ NARROW_COLUMNS,
+ TEXT_AUTOSIZING
+ }
+
+ /**
+ * Enum for specifying the text size.
+ *
+ * - SMALLEST is 50%
+ * - SMALLER is 75%
+ * - NORMAL is 100%
+ * - LARGER is 150%
+ * - LARGEST is 200%
+ *
+ *
+ * @deprecated Use {@link WebSettings#setTextZoom(int)} and {@link WebSettings#getTextZoom()} instead.
+ */
+ @Deprecated
+ public enum TextSize {
+ SMALLEST(50),
+ SMALLER(75),
+ NORMAL(100),
+ LARGER(150),
+ LARGEST(200);
+ TextSize(int size) {
+ value = size;
+ }
+ int value;
+ }
+
+ /**
+ * Enum for specifying the WebView's desired density.
+ *
+ * - {@code FAR} makes 100% looking like in 240dpi
+ * - {@code MEDIUM} makes 100% looking like in 160dpi
+ * - {@code CLOSE} makes 100% looking like in 120dpi
+ *
+ */
+ public enum ZoomDensity {
+ FAR(150), // 240dpi
+ MEDIUM(100), // 160dpi
+ CLOSE(75); // 120dpi
+ ZoomDensity(int size) {
+ value = size;
+ }
+
+ /**
+ * @hide Only for use by WebViewProvider implementations
+ */
+ public int getValue() {
+ return value;
+ }
+
+ int value;
+ }
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CacheMode {}
+
+ /**
+ * Enable web content to apply light or dark style according to the app's theme
+ * and WebView to attempt to darken web content by algorithmic darkening when
+ * appropriate.
+ *
+ * Refer to {@link #setAlgorithmicDarkeningAllowed} for detail.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final long ENABLE_SIMPLIFIED_DARK_MODE = 214741472L;
+
+ /**
+ * Enable User-Agent Reduction for webview.
+ * The OS, CPU, and Build information in the default User-Agent will be
+ * reduced to the static "Linux; Android 10; K" string.
+ * Minor/build/patch version information in the default User-Agent is
+ * reduced to "0.0.0". The rest of the default User-Agent remains unchanged.
+ *
+ * See https://developers.google.com/privacy-sandbox/protections/user-agent
+ * for details related to User-Agent Reduction.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final long ENABLE_USER_AGENT_REDUCTION = 371034303L;
+
+ /**
+ * Default cache usage mode. If the navigation type doesn't impose any
+ * specific behavior, use cached resources when they are available
+ * and not expired, otherwise load resources from the network.
+ * Use with {@link #setCacheMode}.
+ */
+ public static final int LOAD_DEFAULT = -1;
+
+ /**
+ * Normal cache usage mode. Use with {@link #setCacheMode}.
+ *
+ * @deprecated This value is obsolete, as from API level
+ * {@link android.os.Build.VERSION_CODES#HONEYCOMB} and onwards it has the
+ * same effect as {@link #LOAD_DEFAULT}.
+ */
+ @Deprecated
+ public static final int LOAD_NORMAL = 0;
+
+ /**
+ * Use cached resources when they are available, even if they have expired.
+ * Otherwise load resources from the network.
+ * Use with {@link #setCacheMode}.
+ */
+ public static final int LOAD_CACHE_ELSE_NETWORK = 1;
+
+ /**
+ * Don't use the cache, load from the network.
+ * Use with {@link #setCacheMode}.
+ */
+ public static final int LOAD_NO_CACHE = 2;
+
+ /**
+ * Don't use the network, load from the cache.
+ * Use with {@link #setCacheMode}.
+ */
+ public static final int LOAD_CACHE_ONLY = 3;
+
+ public enum RenderPriority {
+ NORMAL,
+ HIGH,
+ LOW
+ }
+
+ /**
+ * The plugin state effects how plugins are treated on a page. ON means
+ * that any object will be loaded even if a plugin does not exist to handle
+ * the content. ON_DEMAND means that if there is a plugin installed that
+ * can handle the content, a placeholder is shown until the user clicks on
+ * the placeholder. Once clicked, the plugin will be enabled on the page.
+ * OFF means that all plugins will be turned off and any fallback content
+ * will be used.
+ */
+ public enum PluginState {
+ ON,
+ ON_DEMAND,
+ OFF
+ }
+
+ /**
+ * In this mode, the WebView will allow a secure origin to load content from any other origin,
+ * even if that origin is insecure. This is the least secure mode of operation for the WebView,
+ * and where possible apps should not set this mode.
+ *
+ * @see #setMixedContentMode
+ */
+ public static final int MIXED_CONTENT_ALWAYS_ALLOW = 0;
+
+ /**
+ * In this mode, the WebView will not allow a secure origin to load content from an insecure
+ * origin. This is the preferred and most secure mode of operation for the WebView and apps are
+ * strongly advised to use this mode.
+ *
+ * @see #setMixedContentMode
+ */
+ public static final int MIXED_CONTENT_NEVER_ALLOW = 1;
+
+ /**
+ * In this mode, the WebView will attempt to be compatible with the approach of a modern web
+ * browser with regard to mixed content. Some insecure content may be allowed to be loaded by
+ * a secure origin and other types of content will be blocked. The types of content are allowed
+ * or blocked may change release to release and are not explicitly defined.
+ *
+ * This mode is intended to be used by apps that are not in control of the content that they
+ * render but desire to operate in a reasonably secure environment. For highest security, apps
+ * are recommended to use {@link #MIXED_CONTENT_NEVER_ALLOW}.
+ *
+ * @see #setMixedContentMode
+ */
+ public static final int MIXED_CONTENT_COMPATIBILITY_MODE = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ForceDark {}
+
+ /**
+ * Disable force dark, irrespective of the force dark mode of the WebView parent. In this mode,
+ * WebView content will always be rendered as-is, regardless of whether native views are being
+ * automatically darkened.
+ *
+ * @see #setForceDark
+ * @deprecated refer to {@link #setForceDark}
+ */
+ public static final int FORCE_DARK_OFF = 0;
+
+ /**
+ * Enable force dark dependent on the state of the WebView parent view. If the WebView parent
+ * view is being automatically force darkened
+ * (see: {@link android.view.View#setForceDarkAllowed}), then WebView content will be rendered
+ * so as to emulate a dark theme. WebViews that are not attached to the view hierarchy will not
+ * be inverted.
+ *
+ * @see #setForceDark
+ * @deprecated refer to {@link #setForceDark}
+ */
+ public static final int FORCE_DARK_AUTO = 1;
+
+ /**
+ * Unconditionally enable force dark. In this mode WebView content will always be rendered so
+ * as to emulate a dark theme.
+ *
+ * @see #setForceDark
+ * @deprecated refer to {@link #setForceDark}
+ */
+ public static final int FORCE_DARK_ON = 2;
+
+ /**
+ * Enables dumping the pages navigation cache to a text file. The default
+ * is {@code false}.
+ *
+ * @deprecated This method is now obsolete.
+ * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
+ */
+ @SuppressWarnings("HiddenAbstractMethod")
+ @SystemApi
+ @Deprecated
+ public abstract void setNavDump(boolean enabled);
+
+ /**
+ * Gets whether dumping the navigation cache is enabled.
+ *
+ * @return whether dumping the navigation cache is enabled
+ * @see #setNavDump
+ * @deprecated This method is now obsolete.
+ * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
+ */
+ @SuppressWarnings("HiddenAbstractMethod")
+ @SystemApi
+ @Deprecated
+ public abstract boolean getNavDump();
+
+ /**
+ * Sets whether the WebView should support zooming using its on-screen zoom
+ * controls and gestures. The particular zoom mechanisms that should be used
+ * can be set with {@link #setBuiltInZoomControls}. This setting does not
+ * affect zooming performed using the {@link WebView#zoomIn()} and
+ * {@link WebView#zoomOut()} methods. The default is {@code true}.
+ *
+ * @param support whether the WebView should support zoom
+ */
+ public abstract void setSupportZoom(boolean support);
+
+ /**
+ * Gets whether the WebView supports zoom.
+ *
+ * @return {@code true} if the WebView supports zoom
+ * @see #setSupportZoom
+ */
+ public abstract boolean supportZoom();
+
+ /**
+ * Sets whether the WebView requires a user gesture to play media.
+ * The default is {@code true}.
+ *
+ * @param require whether the WebView requires a user gesture to play media
+ */
+ public abstract void setMediaPlaybackRequiresUserGesture(boolean require);
+
+ /**
+ * Gets whether the WebView requires a user gesture to play media.
+ *
+ * @return {@code true} if the WebView requires a user gesture to play media
+ * @see #setMediaPlaybackRequiresUserGesture
+ */
+ public abstract boolean getMediaPlaybackRequiresUserGesture();
+
+ /**
+ * Sets whether the WebView should use its built-in zoom mechanisms. The
+ * built-in zoom mechanisms comprise on-screen zoom controls, which are
+ * displayed over the WebView's content, and the use of a pinch gesture to
+ * control zooming. Whether or not these on-screen controls are displayed
+ * can be set with {@link #setDisplayZoomControls}. The default is {@code false}.
+ *
+ * The built-in mechanisms are the only currently supported zoom
+ * mechanisms, so it is recommended that this setting is always enabled.
+ * However, on-screen zoom controls are deprecated in Android (see
+ * {@link android.widget.ZoomButtonsController}) so it's recommended to
+ * disable {@link #setDisplayZoomControls}.
+ *
+ * @param enabled whether the WebView should use its built-in zoom mechanisms
+ */
+ // This method was intended to select between the built-in zoom mechanisms
+ // and the separate zoom controls. The latter were obtained using
+ // {@link WebView#getZoomControls}, which is now hidden.
+ public abstract void setBuiltInZoomControls(boolean enabled);
+
+ /**
+ * Gets whether the zoom mechanisms built into WebView are being used.
+ *
+ * @return {@code true} if the zoom mechanisms built into WebView are being used
+ * @see #setBuiltInZoomControls
+ */
+ public abstract boolean getBuiltInZoomControls();
+
+ /**
+ * Sets whether the WebView should display on-screen zoom controls when
+ * using the built-in zoom mechanisms. See {@link #setBuiltInZoomControls}.
+ * The default is {@code true}. However, on-screen zoom controls are deprecated
+ * in Android (see {@link android.widget.ZoomButtonsController}) so it's
+ * recommended to set this to {@code false}.
+ *
+ * @param enabled whether the WebView should display on-screen zoom controls
+ */
+ public abstract void setDisplayZoomControls(boolean enabled);
+
+ /**
+ * Gets whether the WebView displays on-screen zoom controls when using
+ * the built-in zoom mechanisms.
+ *
+ * @return {@code true} if the WebView displays on-screen zoom controls when using
+ * the built-in zoom mechanisms
+ * @see #setDisplayZoomControls
+ */
+ public abstract boolean getDisplayZoomControls();
+
+ /**
+ * Enables or disables file access within WebView.
+ * Note that this enables or disables file system access only. Assets and resources
+ * are still accessible using file:///android_asset and file:///android_res.
+ *
+ * Note: Apps should not open {@code file://} URLs from any external source in
+ * WebView, don't enable this if your app accepts arbitrary URLs from external sources.
+ * It's recommended to always use
+ *
+ * androidx.webkit.WebViewAssetLoader to access files including assets and resources over
+ * {@code http(s)://} schemes, instead of {@code file://} URLs. To prevent possible security
+ * issues targeting {@link android.os.Build.VERSION_CODES#Q} and earlier, you should explicitly
+ * set this value to {@code false}.
+ *
+ * The default value is {@code true} for apps targeting
+ * {@link android.os.Build.VERSION_CODES#Q} and below, and {@code false} when targeting
+ * {@link android.os.Build.VERSION_CODES#R} and above.
+ */
+ public abstract void setAllowFileAccess(boolean allow);
+
+ /**
+ * Gets whether this WebView supports file access.
+ *
+ * @see #setAllowFileAccess
+ */
+ public abstract boolean getAllowFileAccess();
+
+ /**
+ * Enables or disables content URL access within WebView. Content URL
+ * access allows WebView to load content from a content provider installed
+ * in the system. The default is enabled.
+ */
+ public abstract void setAllowContentAccess(boolean allow);
+
+ /**
+ * Gets whether this WebView supports content URL access.
+ *
+ * @see #setAllowContentAccess
+ */
+ public abstract boolean getAllowContentAccess();
+
+ /**
+ * Sets whether the WebView loads pages in overview mode, that is,
+ * zooms out the content to fit on screen by width. This setting is
+ * taken into account when the content width is greater than the width
+ * of the WebView control, for example, when {@link #getUseWideViewPort}
+ * is enabled. The default is {@code false}.
+ */
+ public abstract void setLoadWithOverviewMode(boolean overview);
+
+ /**
+ * Gets whether this WebView loads pages in overview mode.
+ *
+ * @return whether this WebView loads pages in overview mode
+ * @see #setLoadWithOverviewMode
+ */
+ public abstract boolean getLoadWithOverviewMode();
+
+ /**
+ * Sets whether the WebView will enable smooth transition while panning or
+ * zooming or while the window hosting the WebView does not have focus.
+ * If it is {@code true}, WebView will choose a solution to maximize the performance.
+ * e.g. the WebView's content may not be updated during the transition.
+ * If it is false, WebView will keep its fidelity. The default value is {@code false}.
+ *
+ * @deprecated This method is now obsolete, and will become a no-op in future.
+ */
+ @Deprecated
+ public abstract void setEnableSmoothTransition(boolean enable);
+
+ /**
+ * Gets whether the WebView enables smooth transition while panning or
+ * zooming.
+ *
+ * @see #setEnableSmoothTransition
+ *
+ * @deprecated This method is now obsolete, and will become a no-op in future.
+ */
+ @Deprecated
+ public abstract boolean enableSmoothTransition();
+
+ /**
+ * Sets whether the WebView uses its background for over scroll background.
+ * If {@code true}, it will use the WebView's background. If {@code false}, it will use an
+ * internal pattern. Default is {@code true}.
+ *
+ * @deprecated This method is now obsolete.
+ * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
+ */
+ @SuppressWarnings("HiddenAbstractMethod")
+ @SystemApi
+ @Deprecated
+ public abstract void setUseWebViewBackgroundForOverscrollBackground(boolean view);
+
+ /**
+ * Gets whether this WebView uses WebView's background instead of
+ * internal pattern for over scroll background.
+ *
+ * @see #setUseWebViewBackgroundForOverscrollBackground
+ * @deprecated This method is now obsolete.
+ * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
+ */
+ @SuppressWarnings("HiddenAbstractMethod")
+ @SystemApi
+ @Deprecated
+ public abstract boolean getUseWebViewBackgroundForOverscrollBackground();
+
+ /**
+ * Sets whether the WebView should save form data. In {@link android.os.Build.VERSION_CODES#O},
+ * the platform has implemented a fully functional Autofill feature to store form data.
+ * Therefore, the Webview form data save feature is disabled.
+ *
+ *
Note that the feature will continue to be supported on older versions of
+ * Android as before.
+ *
+ * @see #getSaveFormData
+ * @deprecated In Android O and afterwards, this function does not have any effect. Form data
+ * will be saved to platform's autofill service if applicable.
+ */
+ @Deprecated
+ public abstract void setSaveFormData(boolean save);
+
+ /**
+ * Gets whether the WebView saves form data. In {@link android.os.Build.VERSION_CODES#O}, the
+ * platform has implemented a fully functional Autofill feature to store form data. Therefore,
+ * the Webview form data save feature is disabled.
+ *
+ *
Note that the feature will continue to be supported on older versions of
+ * Android as before.
+ *
+ * @return whether the WebView saves form data
+ * @see #setSaveFormData
+ * @deprecated In Android O and afterwards, this function does not have any effect. Form data
+ * will be filled from the platform's autofill service if applicable.
+ */
+ @Deprecated
+ public abstract boolean getSaveFormData();
+
+ /**
+ * Sets whether the WebView should save passwords. The default is {@code true}.
+ * @deprecated Saving passwords in WebView will not be supported in future versions.
+ */
+ @Deprecated
+ public abstract void setSavePassword(boolean save);
+
+ /**
+ * Gets whether the WebView saves passwords.
+ *
+ * @return whether the WebView saves passwords
+ * @see #setSavePassword
+ * @deprecated Saving passwords in WebView will not be supported in future versions.
+ */
+ @Deprecated
+ public abstract boolean getSavePassword();
+
+ /**
+ * Sets the text zoom of the page in percent. The default is 100.
+ *
+ * @param textZoom the text zoom in percent
+ */
+ public abstract void setTextZoom(int textZoom);
+
+ /**
+ * Gets the text zoom of the page in percent.
+ *
+ * @return the text zoom of the page in percent
+ * @see #setTextZoom
+ */
+ public abstract int getTextZoom();
+
+ /**
+ * Sets policy for third party cookies.
+ * Developers should access this via {@link CookieManager#setShouldAcceptThirdPartyCookies}.
+ * @hide Internal API.
+ */
+ @SuppressWarnings("HiddenAbstractMethod")
+ @SystemApi
+ public abstract void setAcceptThirdPartyCookies(boolean accept);
+
+ /**
+ * Gets policy for third party cookies.
+ * Developers should access this via {@link CookieManager#getShouldAcceptThirdPartyCookies}.
+ * @hide Internal API
+ */
+ @SuppressWarnings("HiddenAbstractMethod")
+ @SystemApi
+ public abstract boolean getAcceptThirdPartyCookies();
+
+ /**
+ * Sets the text size of the page. The default is {@link TextSize#NORMAL}.
+ *
+ * @param t the text size as a {@link TextSize} value
+ * @deprecated Use {@link #setTextZoom} instead.
+ */
+ @Deprecated
+ public synchronized void setTextSize(TextSize t) {
+ setTextZoom(t.value);
+ }
+
+ /**
+ * Gets the text size of the page. If the text size was previously specified
+ * in percent using {@link #setTextZoom}, this will return the closest
+ * matching {@link TextSize}.
+ *
+ * @return the text size as a {@link TextSize} value
+ * @see #setTextSize
+ * @deprecated Use {@link #getTextZoom} instead.
+ */
+ @Deprecated
+ public synchronized TextSize getTextSize() {
+ TextSize closestSize = null;
+ int smallestDelta = Integer.MAX_VALUE;
+ int textSize = getTextZoom();
+ for (TextSize size : TextSize.values()) {
+ int delta = Math.abs(textSize - size.value);
+ if (delta == 0) {
+ return size;
+ }
+ if (delta < smallestDelta) {
+ smallestDelta = delta;
+ closestSize = size;
+ }
+ }
+ return closestSize != null ? closestSize : TextSize.NORMAL;
+ }
+
+ /**
+ * Sets the default zoom density of the page. This must be called from the UI
+ * thread. The default is {@link ZoomDensity#MEDIUM}.
+ *
+ * This setting is not recommended for use in new applications. If the WebView
+ * is utilized to display mobile-oriented pages, the desired effect can be achieved by
+ * adjusting 'width' and 'initial-scale' attributes of page's 'meta viewport'
+ * tag. For pages lacking the tag, {@link android.webkit.WebView#setInitialScale}
+ * and {@link #setUseWideViewPort} can be used.
+ *
+ * @param zoom the zoom density
+ * @deprecated This method is no longer supported, see the function documentation for
+ * recommended alternatives.
+ */
+ @Deprecated
+ public abstract void setDefaultZoom(ZoomDensity zoom);
+
+ /**
+ * Gets the default zoom density of the page. This should be called from
+ * the UI thread.
+ *
+ * This setting is not recommended for use in new applications.
+ *
+ * @return the zoom density
+ * @see #setDefaultZoom
+ * @deprecated Will only return the default value.
+ */
+ @Deprecated
+ public abstract ZoomDensity getDefaultZoom();
+
+ /**
+ * Enables using light touches to make a selection and activate mouseovers.
+ * @deprecated From {@link android.os.Build.VERSION_CODES#JELLY_BEAN} this
+ * setting is obsolete and has no effect.
+ */
+ @Deprecated
+ public abstract void setLightTouchEnabled(boolean enabled);
+
+ /**
+ * Gets whether light touches are enabled.
+ * @see #setLightTouchEnabled
+ * @deprecated This setting is obsolete.
+ */
+ @Deprecated
+ public abstract boolean getLightTouchEnabled();
+
+ /**
+ * Controlled a rendering optimization that is no longer present. Setting
+ * it now has no effect.
+ *
+ * @deprecated This setting now has no effect.
+ * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
+ */
+ @Deprecated
+ public void setUseDoubleTree(boolean use) {
+ // Specified to do nothing, so no need for derived classes to override.
+ }
+
+ /**
+ * Controlled a rendering optimization that is no longer present. Setting
+ * it now has no effect.
+ *
+ * @deprecated This setting now has no effect.
+ * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
+ */
+ @Deprecated
+ public boolean getUseDoubleTree() {
+ // Returns false unconditionally, so no need for derived classes to override.
+ return false;
+ }
+
+ /**
+ * Sets the user-agent string using an integer code.
+ *
+ * - 0 means the WebView should use an Android user-agent string
+ * - 1 means the WebView should use a desktop user-agent string
+ *
+ * Other values are ignored. The default is an Android user-agent string,
+ * i.e. code value 0.
+ *
+ * @param ua the integer code for the user-agent string
+ * @deprecated Please use {@link #setUserAgentString} instead.
+ * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
+ */
+ @SuppressWarnings("HiddenAbstractMethod")
+ @SystemApi
+ @Deprecated
+ public abstract void setUserAgent(int ua);
+
+ /**
+ * Gets the user-agent as an integer code.
+ *
+ * - -1 means the WebView is using a custom user-agent string set with
+ * {@link #setUserAgentString}
+ * - 0 means the WebView should use an Android user-agent string
+ * - 1 means the WebView should use a desktop user-agent string
+ *
+ *
+ * @return the integer code for the user-agent string
+ * @see #setUserAgent
+ * @deprecated Please use {@link #getUserAgentString} instead.
+ * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
+ */
+ @SuppressWarnings("HiddenAbstractMethod")
+ @SystemApi
+ @Deprecated
+ public abstract int getUserAgent();
+
+ /**
+ * Sets whether the WebView should enable support for the "viewport"
+ * HTML meta tag or should use a wide viewport.
+ * When the value of the setting is {@code false}, the layout width is always set to the
+ * width of the WebView control in device-independent (CSS) pixels.
+ * When the value is {@code true} and the page contains the viewport meta tag, the value
+ * of the width specified in the tag is used. If the page does not contain the tag or
+ * does not provide a width, then a wide viewport will be used.
+ *
+ * @param use whether to enable support for the viewport meta tag
+ */
+ public abstract void setUseWideViewPort(boolean use);
+
+ /**
+ * Gets whether the WebView supports the "viewport"
+ * HTML meta tag or will use a wide viewport.
+ *
+ * @return {@code true} if the WebView supports the viewport meta tag
+ * @see #setUseWideViewPort
+ */
+ public abstract boolean getUseWideViewPort();
+
+ /**
+ * Sets whether the WebView should support multiple windows.
+ *
+ * If set to {@code true}, the {@link WebChromeClient#onCreateWindow}
+ * callback must be implemented by the application to handle the
+ * creation of new windows.
+ *
+ *
The default is {@code false}. When multiple window support is disabled,
+ * requests to open new windows (either from the {@code window.open()}
+ * JavaScript API or from links with {@code target="_blank"}) will instead
+ * be treated as top-level navigations, replacing the current page in the
+ * same WebView.
+ *
+ * @param support whether to support multiple windows
+ */
+ public abstract void setSupportMultipleWindows(boolean support);
+
+ /**
+ * Gets whether the WebView supports multiple windows.
+ *
+ * @return {@code true} if the WebView supports multiple windows
+ * @see #setSupportMultipleWindows
+ */
+ public abstract boolean supportMultipleWindows();
+
+ /**
+ * Sets the underlying layout algorithm. This will cause a re-layout of the
+ * WebView. The default is {@link LayoutAlgorithm#NARROW_COLUMNS}.
+ *
+ * @param l the layout algorithm to use, as a {@link LayoutAlgorithm} value
+ */
+ public abstract void setLayoutAlgorithm(LayoutAlgorithm l);
+
+ /**
+ * Gets the current layout algorithm.
+ *
+ * @return the layout algorithm in use, as a {@link LayoutAlgorithm} value
+ * @see #setLayoutAlgorithm
+ */
+ public abstract LayoutAlgorithm getLayoutAlgorithm();
+
+ /**
+ * Sets the standard font family name. The default is "sans-serif".
+ *
+ * @param font a font family name
+ */
+ public abstract void setStandardFontFamily(String font);
+
+ /**
+ * Gets the standard font family name.
+ *
+ * @return the standard font family name as a string
+ * @see #setStandardFontFamily
+ */
+ public abstract String getStandardFontFamily();
+
+ /**
+ * Sets the fixed font family name. The default is "monospace".
+ *
+ * @param font a font family name
+ */
+ public abstract void setFixedFontFamily(String font);
+
+ /**
+ * Gets the fixed font family name.
+ *
+ * @return the fixed font family name as a string
+ * @see #setFixedFontFamily
+ */
+ public abstract String getFixedFontFamily();
+
+ /**
+ * Sets the sans-serif font family name. The default is "sans-serif".
+ *
+ * @param font a font family name
+ */
+ public abstract void setSansSerifFontFamily(String font);
+
+ /**
+ * Gets the sans-serif font family name.
+ *
+ * @return the sans-serif font family name as a string
+ * @see #setSansSerifFontFamily
+ */
+ public abstract String getSansSerifFontFamily();
+
+ /**
+ * Sets the serif font family name. The default is "sans-serif".
+ *
+ * @param font a font family name
+ */
+ public abstract void setSerifFontFamily(String font);
+
+ /**
+ * Gets the serif font family name. The default is "serif".
+ *
+ * @return the serif font family name as a string
+ * @see #setSerifFontFamily
+ */
+ public abstract String getSerifFontFamily();
+
+ /**
+ * Sets the cursive font family name. The default is "cursive".
+ *
+ * @param font a font family name
+ */
+ public abstract void setCursiveFontFamily(String font);
+
+ /**
+ * Gets the cursive font family name.
+ *
+ * @return the cursive font family name as a string
+ * @see #setCursiveFontFamily
+ */
+ public abstract String getCursiveFontFamily();
+
+ /**
+ * Sets the fantasy font family name. The default is "fantasy".
+ *
+ * @param font a font family name
+ */
+ public abstract void setFantasyFontFamily(String font);
+
+ /**
+ * Gets the fantasy font family name.
+ *
+ * @return the fantasy font family name as a string
+ * @see #setFantasyFontFamily
+ */
+ public abstract String getFantasyFontFamily();
+
+ /**
+ * Sets the minimum font size. The default is 8.
+ *
+ * @param size a non-negative integer between 1 and 72. Any number outside
+ * the specified range will be pinned.
+ */
+ public abstract void setMinimumFontSize(int size);
+
+ /**
+ * Gets the minimum font size.
+ *
+ * @return a non-negative integer between 1 and 72
+ * @see #setMinimumFontSize
+ */
+ public abstract int getMinimumFontSize();
+
+ /**
+ * Sets the minimum logical font size. The default is 8.
+ *
+ * @param size a non-negative integer between 1 and 72. Any number outside
+ * the specified range will be pinned.
+ */
+ public abstract void setMinimumLogicalFontSize(int size);
+
+ /**
+ * Gets the minimum logical font size.
+ *
+ * @return a non-negative integer between 1 and 72
+ * @see #setMinimumLogicalFontSize
+ */
+ public abstract int getMinimumLogicalFontSize();
+
+ /**
+ * Sets the default font size. The default is 16.
+ *
+ * @param size a non-negative integer between 1 and 72. Any number outside
+ * the specified range will be pinned.
+ */
+ public abstract void setDefaultFontSize(int size);
+
+ /**
+ * Gets the default font size.
+ *
+ * @return a non-negative integer between 1 and 72
+ * @see #setDefaultFontSize
+ */
+ public abstract int getDefaultFontSize();
+
+ /**
+ * Sets the default fixed font size. The default is 16.
+ *
+ * @param size a non-negative integer between 1 and 72. Any number outside
+ * the specified range will be pinned.
+ */
+ public abstract void setDefaultFixedFontSize(int size);
+
+ /**
+ * Gets the default fixed font size.
+ *
+ * @return a non-negative integer between 1 and 72
+ * @see #setDefaultFixedFontSize
+ */
+ public abstract int getDefaultFixedFontSize();
+
+ /**
+ * Sets whether the WebView should load image resources. Note that this method
+ * controls loading of all images, including those embedded using the data
+ * URI scheme. Use {@link #setBlockNetworkImage} to control loading only
+ * of images specified using network URI schemes. Note that if the value of this
+ * setting is changed from {@code false} to {@code true}, all images resources referenced
+ * by content currently displayed by the WebView are loaded automatically.
+ * The default is {@code true}.
+ *
+ * @param flag whether the WebView should load image resources
+ */
+ public abstract void setLoadsImagesAutomatically(boolean flag);
+
+ /**
+ * Gets whether the WebView loads image resources. This includes
+ * images embedded using the data URI scheme.
+ *
+ * @return {@code true} if the WebView loads image resources
+ * @see #setLoadsImagesAutomatically
+ */
+ public abstract boolean getLoadsImagesAutomatically();
+
+ /**
+ * Sets whether the WebView should not load image resources from the
+ * network (resources accessed via http and https URI schemes). Note
+ * that this method has no effect unless
+ * {@link #getLoadsImagesAutomatically} returns {@code true}. Also note that
+ * disabling all network loads using {@link #setBlockNetworkLoads}
+ * will also prevent network images from loading, even if this flag is set
+ * to false. When the value of this setting is changed from {@code true} to {@code false},
+ * network images resources referenced by content currently displayed by
+ * the WebView are fetched automatically. The default is {@code false}.
+ *
+ * @param flag whether the WebView should not load image resources from the
+ * network
+ * @see #setBlockNetworkLoads
+ */
+ public abstract void setBlockNetworkImage(boolean flag);
+
+ /**
+ * Gets whether the WebView does not load image resources from the network.
+ *
+ * @return {@code true} if the WebView does not load image resources from the network
+ * @see #setBlockNetworkImage
+ */
+ public abstract boolean getBlockNetworkImage();
+
+ /**
+ * Sets whether the WebView should not load resources from the network.
+ * Use {@link #setBlockNetworkImage} to only avoid loading
+ * image resources. Note that if the value of this setting is
+ * changed from {@code true} to {@code false}, network resources referenced by content
+ * currently displayed by the WebView are not fetched until
+ * {@link android.webkit.WebView#reload} is called.
+ * If the application does not have the
+ * {@link android.Manifest.permission#INTERNET} permission, attempts to set
+ * a value of {@code false} will cause a {@link java.lang.SecurityException}
+ * to be thrown. The default value is {@code false} if the application has the
+ * {@link android.Manifest.permission#INTERNET} permission, otherwise it is
+ * {@code true}.
+ *
+ * @param flag {@code true} means block network loads by the WebView
+ * @see android.webkit.WebView#reload
+ */
+ public abstract void setBlockNetworkLoads(boolean flag);
+
+ /**
+ * Gets whether the WebView does not load any resources from the network.
+ *
+ * @return {@code true} if the WebView does not load any resources from the network
+ * @see #setBlockNetworkLoads
+ */
+ public abstract boolean getBlockNetworkLoads();
+
+ /**
+ * Tells the WebView to enable JavaScript execution.
+ * The default is {@code false}.
+ *
+ * @param flag {@code true} if the WebView should execute JavaScript
+ */
+ public abstract void setJavaScriptEnabled(boolean flag);
+
+ /**
+ * Sets whether cross-origin requests in the context of a file scheme URL should be allowed to
+ * access content from any origin. This includes access to content from other file
+ * scheme URLs or web contexts. Note that some access such as image HTML elements doesn't
+ * follow same-origin rules and isn't affected by this setting.
+ *
+ * Don't enable this setting if you open files that may be created or altered by
+ * external sources. Enabling this setting allows malicious scripts loaded in a {@code file://}
+ * context to launch cross-site scripting attacks, either accessing arbitrary local files
+ * including WebView cookies, app private data or even credentials used on arbitrary web sites.
+ *
+ * Loading content via {@code file://} URLs is generally discouraged. See the note in
+ * {@link #setAllowFileAccess}.
+ *
+ * The default value is {@code true} for apps targeting
+ * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and below, and {@code false}
+ * when targeting {@link android.os.Build.VERSION_CODES#JELLY_BEAN} and above. To prevent
+ * possible violation of same domain policy when targeting
+ * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and earlier, you should
+ * explicitly set this value to {@code false}.
+ *
+ * @param flag whether JavaScript running in the context of a file scheme URL should be allowed
+ * to access content from any origin
+ * @deprecated This setting is not secure, please use
+ *
+ * androidx.webkit.WebViewAssetLoader to load file content securely.
+ */
+ @Deprecated
+ public abstract void setAllowUniversalAccessFromFileURLs(boolean flag);
+
+ /**
+ * Sets whether cross-origin requests in the context of a file scheme URL should be allowed to
+ * access content from other file scheme URLs. Note that some accesses such as image HTML
+ * elements don't follow same-origin rules and aren't affected by this setting.
+ *
+ * Don't enable this setting if you open files that may be created or altered by
+ * external sources. Enabling this setting allows malicious scripts loaded in a {@code file://}
+ * context to access arbitrary local files including WebView cookies and app private data.
+ *
+ * Loading content via {@code file://} URLs is generally discouraged. See the note in
+ * {@link #setAllowFileAccess}.
+ *
+ * Note that the value of this setting is ignored if the value of
+ * {@link #getAllowUniversalAccessFromFileURLs} is {@code true}. The default value is
+ * {@code true} for apps targeting {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1}
+ * and below, and {@code false} when targeting {@link android.os.Build.VERSION_CODES#JELLY_BEAN}
+ * and above. To prevent possible violation of same domain policy when targeting
+ * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and earlier, you should
+ * explicitly set this value to {@code false}.
+ *
+ * @param flag whether JavaScript running in the context of a file scheme
+ * URL should be allowed to access content from other file
+ * scheme URLs
+ * @deprecated This setting is not secure, please use
+ *
+ * androidx.webkit.WebViewAssetLoader to load file content securely.
+ */
+ @Deprecated
+ public abstract void setAllowFileAccessFromFileURLs(boolean flag);
+
+ /**
+ * Sets whether the WebView should enable plugins. The default is {@code false}.
+ *
+ * @param flag {@code true} if plugins should be enabled
+ * @deprecated This method has been deprecated in favor of
+ * {@link #setPluginState}
+ * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}
+ */
+ @SuppressWarnings("HiddenAbstractMethod")
+ @SystemApi
+ @Deprecated
+ public abstract void setPluginsEnabled(boolean flag);
+
+ /**
+ * Tells the WebView to enable, disable, or have plugins on demand. On
+ * demand mode means that if a plugin exists that can handle the embedded
+ * content, a placeholder icon will be shown instead of the plugin. When
+ * the placeholder is clicked, the plugin will be enabled. The default is
+ * {@link PluginState#OFF}.
+ *
+ * @param state a PluginState value
+ * @deprecated Plugins are not supported in API level
+ * {@link android.os.Build.VERSION_CODES#KITKAT} or later;
+ * enabling plugins is a no-op.
+ */
+ @Deprecated
+ public abstract void setPluginState(PluginState state);
+
+ /**
+ * Sets a custom path to plugins used by the WebView. This method is
+ * obsolete since each plugin is now loaded from its own package.
+ *
+ * @param pluginsPath a String path to the directory containing plugins
+ * @deprecated This method is no longer used as plugins are loaded from
+ * their own APK via the system's package manager.
+ * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}
+ */
+ @Deprecated
+ public void setPluginsPath(String pluginsPath) {
+ // Specified to do nothing, so no need for derived classes to override.
+ }
+
+ /**
+ * Sets the path to where database storage API databases should be saved.
+ * In order for the database storage API to function correctly, this method
+ * must be called with a path to which the application can write. This
+ * method should only be called once: repeated calls are ignored.
+ *
+ * @param databasePath a path to the directory where databases should be
+ * saved.
+ * @deprecated Database paths are managed by the implementation and calling this method
+ * will have no effect.
+ */
+ @Deprecated
+ public abstract void setDatabasePath(String databasePath);
+
+ /**
+ * Sets the path where the Geolocation databases should be saved. In order
+ * for Geolocation permissions and cached positions to be persisted, this
+ * method must be called with a path to which the application can write.
+ *
+ * @param databasePath a path to the directory where databases should be
+ * saved.
+ * @deprecated Geolocation database are managed by the implementation and calling this method
+ * will have no effect.
+ */
+ @Deprecated
+ public abstract void setGeolocationDatabasePath(String databasePath);
+
+ /**
+ * Sets whether the Application Caches API should be enabled. The default
+ * is {@code false}. Note that in order for the Application Caches API to be
+ * enabled, a valid database path must also be supplied to
+ * {@link #setAppCachePath}.
+ *
+ * @param flag {@code true} if the WebView should enable Application Caches
+ * @deprecated The Application Cache API is deprecated and this method will
+ * become a no-op on all Android versions once support is
+ * removed in Chromium. Consider using Service Workers instead.
+ * See https://web.dev/appcache-removal/ for more information.
+ * @removed The Application Cache API is no longer supported and this method
+ * is a no-op on WebView 95 and later. Consider using Service Workers
+ * instead. See https://web.dev/appcache-removal/ for more information.
+ */
+ @Deprecated
+ public void setAppCacheEnabled(boolean flag) {}
+
+ /**
+ * Sets the path to the Application Caches files. In order for the
+ * Application Caches API to be enabled, this method must be called with a
+ * path to which the application can write. This method should only be
+ * called once: repeated calls are ignored.
+ *
+ * @param appCachePath a String path to the directory containing
+ * Application Caches files.
+ * @see #setAppCacheEnabled
+ * @deprecated The Application Cache API is deprecated and this method will
+ * become a no-op on all Android versions once support is
+ * removed in Chromium. Consider using Service Workers instead.
+ * See https://web.dev/appcache-removal/ for more information.
+ * @removed The Application Cache API is no longer supported and this method
+ * is a no-op on WebView 95 and later. Consider using Service Workers
+ * instead. See https://web.dev/appcache-removal/ for more information.
+ */
+ @Deprecated
+ public void setAppCachePath(String appCachePath) {}
+
+ /**
+ * Sets the maximum size for the Application Cache content. The passed size
+ * will be rounded to the nearest value that the database can support, so
+ * this should be viewed as a guide, not a hard limit. Setting the
+ * size to a value less than current database size does not cause the
+ * database to be trimmed. The default size is {@link Long#MAX_VALUE}.
+ * It is recommended to leave the maximum size set to the default value.
+ *
+ * @param appCacheMaxSize the maximum size in bytes
+ * @deprecated Quota is managed automatically; this method is a no-op.
+ * @removed Quota is managed automatically; this method is a no-op.
+ */
+ @Deprecated
+ public void setAppCacheMaxSize(long appCacheMaxSize) {}
+
+ /**
+ * Sets whether the database storage API is enabled. The default value is
+ * false. See also {@link #setDatabasePath} for how to correctly set up the
+ * database storage API.
+ *
+ * This setting is global in effect, across all WebView instances in a process.
+ * Note you should only modify this setting prior to making any WebView
+ * page load within a given process, as the WebView implementation may ignore
+ * changes to this setting after that point.
+ *
+ * @param flag {@code true} if the WebView should use the database storage API
+ * @deprecated WebSQL is deprecated and this method will become a no-op on all
+ * Android versions once support is removed in Chromium. See
+ * https://developer.chrome.com/blog/deprecating-web-sql for more information.
+ */
+ @Deprecated
+ public abstract void setDatabaseEnabled(boolean flag);
+
+ /**
+ * Sets whether the DOM storage API is enabled. The default value is {@code false}.
+ *
+ * @param flag {@code true} if the WebView should use the DOM storage API
+ */
+ public abstract void setDomStorageEnabled(boolean flag);
+
+ /**
+ * Gets whether the DOM Storage APIs are enabled.
+ *
+ * @return {@code true} if the DOM Storage APIs are enabled
+ * @see #setDomStorageEnabled
+ */
+ public abstract boolean getDomStorageEnabled();
+
+ /**
+ * Gets the path to where database storage API databases are saved.
+ *
+ * @return the String path to the database storage API databases
+ * @see #setDatabasePath
+ * @deprecated Database paths are managed by the implementation this method is obsolete.
+ */
+ @Deprecated
+ public abstract String getDatabasePath();
+
+ /**
+ * Gets whether the database storage API is enabled.
+ *
+ * @return {@code true} if the database storage API is enabled
+ * @see #setDatabaseEnabled
+ * @deprecated WebSQL is deprecated and this method will become a no-op on all
+ * Android versions once support is removed in Chromium. See
+ * https://developer.chrome.com/blog/deprecating-web-sql for more information.
+ */
+ @Deprecated
+ public abstract boolean getDatabaseEnabled();
+
+ /**
+ * Sets whether Geolocation is enabled. The default is {@code true}.
+ *
+ * Please note that in order for the Geolocation API to be usable
+ * by a page in the WebView, the following requirements must be met:
+ *
+ * - an application must have permission to access the device location,
+ * see {@link android.Manifest.permission#ACCESS_COARSE_LOCATION},
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION};
+ *
- an application must provide an implementation of the
+ * {@link WebChromeClient#onGeolocationPermissionsShowPrompt} callback
+ * to receive notifications that a page is requesting access to location
+ * via the JavaScript Geolocation API.
+ *
+ *
+ *
+ * @param flag whether Geolocation should be enabled
+ */
+ public abstract void setGeolocationEnabled(boolean flag);
+
+ /**
+ * Gets whether JavaScript is enabled.
+ *
+ * @return {@code true} if JavaScript is enabled
+ * @see #setJavaScriptEnabled
+ */
+ public abstract boolean getJavaScriptEnabled();
+
+ /**
+ * Gets whether JavaScript running in the context of a file scheme URL can
+ * access content from any origin. This includes access to content from
+ * other file scheme URLs.
+ *
+ * @return whether JavaScript running in the context of a file scheme URL
+ * can access content from any origin
+ * @see #setAllowUniversalAccessFromFileURLs
+ */
+ public abstract boolean getAllowUniversalAccessFromFileURLs();
+
+ /**
+ * Gets whether JavaScript running in the context of a file scheme URL can
+ * access content from other file scheme URLs.
+ *
+ * @return whether JavaScript running in the context of a file scheme URL
+ * can access content from other file scheme URLs
+ * @see #setAllowFileAccessFromFileURLs
+ */
+ public abstract boolean getAllowFileAccessFromFileURLs();
+
+ /**
+ * Gets whether plugins are enabled.
+ *
+ * @return {@code true} if plugins are enabled
+ * @see #setPluginsEnabled
+ * @deprecated This method has been replaced by {@link #getPluginState}
+ * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}
+ */
+ @SuppressWarnings("HiddenAbstractMethod")
+ @SystemApi
+ @Deprecated
+ public abstract boolean getPluginsEnabled();
+
+ /**
+ * Gets the current state regarding whether plugins are enabled.
+ *
+ * @return the plugin state as a {@link PluginState} value
+ * @see #setPluginState
+ * @deprecated Plugins are not supported in API level
+ * {@link android.os.Build.VERSION_CODES#KITKAT} or later;
+ * enabling plugins is a no-op.
+ */
+ @Deprecated
+ public abstract PluginState getPluginState();
+
+ /**
+ * Gets the directory that contains the plugin libraries. This method is
+ * obsolete since each plugin is now loaded from its own package.
+ *
+ * @return an empty string
+ * @deprecated This method is no longer used as plugins are loaded from
+ * their own APK via the system's package manager.
+ * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}
+ */
+ @Deprecated
+ public String getPluginsPath() {
+ // Unconditionally returns empty string, so no need for derived classes to override.
+ return "";
+ }
+
+ /**
+ * Allows JavaScript to open windows without a user gesture. This applies to
+ * the JavaScript function {@code window.open()}. The default is
+ * {@code false}: attempts without a user gesture will fail and do nothing.
+ *
+ * This is not affected by the {@link #setSupportMultipleWindows} setting;
+ * the user gesture requirement is enforced even if multiple windows are
+ * disabled.
+ *
+ * @param flag {@code true} if JavaScript can open windows without a user
+ * gesture.
+ */
+ public abstract void setJavaScriptCanOpenWindowsAutomatically(boolean flag);
+
+ /**
+ * Gets whether JavaScript can open windows without a user gesture.
+ *
+ * @return {@code true} if JavaScript can open windows without a user
+ * gesture using {@code window.open()}
+ * @see #setJavaScriptCanOpenWindowsAutomatically
+ */
+ public abstract boolean getJavaScriptCanOpenWindowsAutomatically();
+
+ /**
+ * Sets the default text encoding name to use when decoding html pages.
+ * The default is "UTF-8".
+ *
+ * @param encoding the text encoding name
+ */
+ public abstract void setDefaultTextEncodingName(String encoding);
+
+ /**
+ * Gets the default text encoding name.
+ *
+ * @return the default text encoding name as a string
+ * @see #setDefaultTextEncodingName
+ */
+ public abstract String getDefaultTextEncodingName();
+
+ /**
+ * Sets the WebView's user-agent string. If the string is {@code null} or empty,
+ * the system default value will be used.
+ *
+ *
If the user-agent is overridden in this way, the values of the User-Agent Client Hints
+ * headers and {@code navigator.userAgentData} for this WebView could be changed.
+ *
See androidx.webkit.WebSettingsCompat
+ * #setUserAgentMetadata(WebSettings,UserAgentMetadata) for details.
+ *
+ *
Note that starting from {@link android.os.Build.VERSION_CODES#KITKAT} Android
+ * version, changing the user-agent while loading a web page causes WebView
+ * to initiate loading once again.
+ *
+ * @param ua new user-agent string
+ */
+ public abstract void setUserAgentString(@Nullable String ua);
+
+ /**
+ * Gets the WebView's user-agent string.
+ *
+ * @return the WebView's user-agent string
+ * @see #setUserAgentString
+ */
+ public abstract String getUserAgentString();
+
+ /**
+ * Returns the default User-Agent used by a WebView.
+ * An instance of WebView could use a different User-Agent if a call
+ * is made to {@link WebSettings#setUserAgentString(String)}.
+ *
+ * @param context a Context object used to access application assets
+ */
+ public static String getDefaultUserAgent(Context context) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /**
+ * Tells the WebView whether it needs to set a node to have focus when
+ * {@link WebView#requestFocus(int, android.graphics.Rect)} is called. The
+ * default value is {@code true}.
+ *
+ * @param flag whether the WebView needs to set a node
+ */
+ public abstract void setNeedInitialFocus(boolean flag);
+
+ /**
+ * Sets the priority of the Render thread. Unlike the other settings, this
+ * one only needs to be called once per process. The default value is
+ * {@link RenderPriority#NORMAL}.
+ *
+ * @param priority the priority
+ * @deprecated It is not recommended to adjust thread priorities, and this will
+ * not be supported in future versions.
+ */
+ @Deprecated
+ public abstract void setRenderPriority(RenderPriority priority);
+
+ /**
+ * Overrides the way the cache is used. The way the cache is used is based
+ * on the navigation type. For a normal page load, the cache is checked
+ * and content is re-validated as needed. When navigating back, content is
+ * not revalidated, instead the content is just retrieved from the cache.
+ * This method allows the client to override this behavior by specifying
+ * one of {@link #LOAD_DEFAULT},
+ * {@link #LOAD_CACHE_ELSE_NETWORK}, {@link #LOAD_NO_CACHE} or
+ * {@link #LOAD_CACHE_ONLY}. The default value is {@link #LOAD_DEFAULT}.
+ *
+ * @param mode the mode to use
+ */
+ public abstract void setCacheMode(@CacheMode int mode);
+
+ /**
+ * Gets the current setting for overriding the cache mode.
+ *
+ * @return the current setting for overriding the cache mode
+ * @see #setCacheMode
+ */
+ @CacheMode
+ public abstract int getCacheMode();
+
+ /**
+ * Configures the WebView's behavior when a secure origin attempts to load a resource from an
+ * insecure origin.
+ *
+ * By default, apps that target {@link android.os.Build.VERSION_CODES#KITKAT} or below default
+ * to {@link #MIXED_CONTENT_ALWAYS_ALLOW}. Apps targeting
+ * {@link android.os.Build.VERSION_CODES#LOLLIPOP} default to {@link #MIXED_CONTENT_NEVER_ALLOW}.
+ *
+ * The preferred and most secure mode of operation for the WebView is
+ * {@link #MIXED_CONTENT_NEVER_ALLOW} and use of {@link #MIXED_CONTENT_ALWAYS_ALLOW} is
+ * strongly discouraged.
+ *
+ * @param mode The mixed content mode to use. One of {@link #MIXED_CONTENT_NEVER_ALLOW},
+ * {@link #MIXED_CONTENT_ALWAYS_ALLOW} or {@link #MIXED_CONTENT_COMPATIBILITY_MODE}.
+ */
+ public abstract void setMixedContentMode(int mode);
+
+ /**
+ * Gets the current behavior of the WebView with regard to loading insecure content from a
+ * secure origin.
+ * @return The current setting, one of {@link #MIXED_CONTENT_NEVER_ALLOW},
+ * {@link #MIXED_CONTENT_ALWAYS_ALLOW} or {@link #MIXED_CONTENT_COMPATIBILITY_MODE}.
+ */
+ public abstract int getMixedContentMode();
+
+ /**
+ * Sets whether to use a video overlay for embedded encrypted video.
+ * In API levels prior to {@link android.os.Build.VERSION_CODES#LOLLIPOP}, encrypted video can
+ * only be rendered directly on a secure video surface, so it had been a hard problem to play
+ * encrypted video in HTML. When this flag is on, WebView can play encrypted video (MSE/EME)
+ * by using a video overlay (aka hole-punching) for videos embedded using HTML <video>
+ * tag.
+ * Caution: This setting is intended for use only in a narrow set of circumstances and apps
+ * should only enable it if they require playback of encrypted video content. It will impose
+ * the following limitations on the WebView:
+ *
+ * - Only one video overlay can be played at a time.
+ *
- Changes made to position or dimensions of a video element may be propagated to the
+ * corresponding video overlay with a noticeable delay.
+ *
- The video overlay is not visible to web APIs and as such may not interact with
+ * script or styling. For example, CSS styles applied to the <video> tag may be ignored.
+ *
+ * This is not an exhaustive set of constraints and it may vary with new versions of the
+ * WebView.
+ * @hide
+ */
+ @SuppressWarnings("HiddenAbstractMethod")
+ @SystemApi
+ public abstract void setVideoOverlayForEmbeddedEncryptedVideoEnabled(boolean flag);
+
+ /**
+ * Gets whether a video overlay will be used for embedded encrypted video.
+ *
+ * @return {@code true} if WebView uses a video overlay for embedded encrypted video.
+ * @see #setVideoOverlayForEmbeddedEncryptedVideoEnabled
+ * @hide
+ */
+ @SuppressWarnings("HiddenAbstractMethod")
+ @SystemApi
+ public abstract boolean getVideoOverlayForEmbeddedEncryptedVideoEnabled();
+
+ /**
+ * Sets whether this WebView should raster tiles when it is
+ * offscreen but attached to a window. Turning this on can avoid
+ * rendering artifacts when animating an offscreen WebView on-screen.
+ * Offscreen WebViews in this mode use more memory. The default value is
+ * false.
+ * Please follow these guidelines to limit memory usage:
+ *
+ * - WebView size should be not be larger than the device screen size.
+ *
- Limit use of this mode to a small number of WebViews. Use it for
+ * visible WebViews and WebViews about to be animated to visible.
+ *
+ */
+ public abstract void setOffscreenPreRaster(boolean enabled);
+
+ /**
+ * Gets whether this WebView should raster tiles when it is
+ * offscreen but attached to a window.
+ * @return {@code true} if this WebView will raster tiles when it is
+ * offscreen but attached to a window.
+ */
+ public abstract boolean getOffscreenPreRaster();
+
+
+ /**
+ * Sets whether Safe Browsing is enabled. Safe Browsing allows WebView to
+ * protect against malware and phishing attacks by verifying the links.
+ *
+ *
+ * Safe Browsing can be disabled for all WebViews using a manifest tag (read general Safe Browsing info). The
+ * manifest tag has a lower precedence than this API.
+ *
+ *
+ * Safe Browsing is enabled by default for devices which support it.
+ *
+ * @param enabled Whether Safe Browsing is enabled.
+ */
+ public abstract void setSafeBrowsingEnabled(boolean enabled);
+
+ /**
+ * Gets whether Safe Browsing is enabled.
+ * See {@link #setSafeBrowsingEnabled}.
+ *
+ * @return {@code true} if Safe Browsing is enabled and {@code false} otherwise.
+ */
+ public abstract boolean getSafeBrowsingEnabled();
+
+
+ /**
+ * Set the force dark mode for this WebView.
+ *
+ * @param forceDark the force dark mode to set.
+ * @see #getForceDark
+ * @deprecated The "force dark" model previously implemented by WebView was complex
+ * and didn't interoperate well with current Web standards for
+ * {@code prefers-color-scheme} and {@code color-scheme}. In apps with
+ * {@code targetSdkVersion} ≥ {@link android.os.Build.VERSION_CODES#TIRAMISU}
+ * this API is a no-op and WebView will always use the dark style defined by web content
+ * authors if the app's theme is dark. To customize the behavior, refer to
+ * {@link #setAlgorithmicDarkeningAllowed}.
+ */
+ public void setForceDark(@ForceDark int forceDark) {
+ // Stub implementation to satisfy Roboelectrc shadows that don't override this yet.
+ }
+
+ /**
+ * Get the force dark mode for this WebView.
+ * The default force dark mode is {@link #FORCE_DARK_AUTO}.
+ *
+ * @return the currently set force dark mode.
+ * @see #setForceDark
+ * @deprecated refer to {@link #setForceDark}.
+ */
+ public @ForceDark int getForceDark() {
+ // Stub implementation to satisfy Roboelectrc shadows that don't override this yet.
+ return FORCE_DARK_AUTO;
+ }
+
+ /**
+ * Control whether algorithmic darkening is allowed.
+ *
+ *
+ * Note: This API and the behaviour described only apply to apps with
+ * {@code targetSdkVersion} ≥ {@link android.os.Build.VERSION_CODES#TIRAMISU}.
+ *
+ *
+ * WebView always sets the media query {@code prefers-color-scheme} according to the app's
+ * theme attribute {@link android.R.styleable#Theme_isLightTheme isLightTheme}, i.e.
+ * {@code prefers-color-scheme} is {@code light} if isLightTheme is true or not specified,
+ * otherwise it is {@code dark}. This means that the web content's light or dark style will
+ * be applied automatically to match the app's theme if the content supports it.
+ *
+ *
+ * Algorithmic darkening is disallowed by default.
+ *
+ * If the app's theme is dark and it allows algorithmic darkening, WebView will attempt to
+ * darken web content using an algorithm, if the content doesn't define its own dark styles
+ * and doesn't explicitly disable darkening.
+ *
+ *
+ * If Android is applying Force Dark to WebView then WebView will ignore the value of
+ * this setting and behave as if it were set to true.
+ *
+ *
+ * The deprecated {@link #setForceDark} and related API are no-ops in apps with
+ * {@code targetSdkVersion} ≥ {@link android.os.Build.VERSION_CODES#TIRAMISU},
+ * but they still apply to apps with
+ * {@code targetSdkVersion} < {@link android.os.Build.VERSION_CODES#TIRAMISU}.
+ *
+ *
+ * The below table summarizes how APIs work with different apps.
+ *
+ *
+ *
+ *
+ * | App |
+ * Web content which uses {@code prefers-color-scheme} |
+ * Web content which does not use {@code prefers-color-scheme} |
+ *
+ *
+ *
+ *
+ * | App with {@code isLightTheme} True or not set |
+ * Renders with the light theme defined by the content author. |
+ * Renders with the default styling defined by the content author. |
+ *
+ *
+ * | App with Android forceDark in effect |
+ * Renders with the dark theme defined by the content author. |
+ * Renders with the styling modified to dark colors by an algorithm
+ * if allowed by the content author. |
+ *
+ *
+ * | App with {@code isLightTheme} False,
+ * {@code targetSdkVersion} < {@link android.os.Build.VERSION_CODES#TIRAMISU},
+ * and has {@code FORCE_DARK_AUTO} |
+ * Renders with the dark theme defined by the content author. |
+ * Renders with the default styling defined by the content author. |
+ *
+ *
+ * | App with {@code isLightTheme} False,
+ * {@code targetSdkVersion} ≥ {@link android.os.Build.VERSION_CODES#TIRAMISU},
+ * and {@code setAlgorithmicDarkening(false)} |
+ * Renders with the dark theme defined by the content author. |
+ * Renders with the default styling defined by the content author. |
+ *
+ *
+ * | App with {@code isLightTheme} False,
+ * {@code targetSdkVersion} ≥ {@link android.os.Build.VERSION_CODES#TIRAMISU},
+ * and {@code setAlgorithmicDarkening(true)} |
+ * Renders with the dark theme defined by the content author. |
+ * Renders with the styling modified to dark colors by an algorithm if allowed
+ * by the content author. |
+ *
+ *
+ *
+ *
+ *
+ * @param allow allow algorithmic darkening or not.
+ */
+ public void setAlgorithmicDarkeningAllowed(boolean allow) {
+ // Stub implementation to satisfy Roboelectrc shadows that don't override this yet.
+ }
+
+ /**
+ * Get if algorithmic darkening is allowed or not for this WebView.
+ * The default is false.
+ *
+ * @return if the algorithmic darkening is allowed or not.
+ * @see #setAlgorithmicDarkeningAllowed
+ */
+ public boolean isAlgorithmicDarkeningAllowed() {
+ // Stub implementation to satisfy Roboelectrc shadows that don't override this yet.
+ return false;
+ }
+
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ElementType.PARAMETER, ElementType.METHOD})
+ private @interface MenuItemFlags {}
+
+ /**
+ * Disables the action mode menu items according to {@code menuItems} flag.
+ * @param menuItems an integer field flag for the menu items to be disabled.
+ */
+ public abstract void setDisabledActionModeMenuItems(@MenuItemFlags int menuItems);
+
+ /**
+ * Gets the action mode menu items that are disabled, expressed in an integer field flag.
+ * The default value is {@link #MENU_ITEM_NONE}
+ *
+ * @return all the disabled menu item flags combined with bitwise OR.
+ */
+ public abstract @MenuItemFlags int getDisabledActionModeMenuItems();
+
+ /**
+ * No menu items should be disabled.
+ *
+ * @see #setDisabledActionModeMenuItems
+ */
+ public static final int MENU_ITEM_NONE = 0;
+
+ /**
+ * Disable menu item "Share".
+ *
+ * @see #setDisabledActionModeMenuItems
+ */
+ public static final int MENU_ITEM_SHARE = 1 << 0;
+
+ /**
+ * Disable menu item "Web Search".
+ *
+ * @see #setDisabledActionModeMenuItems
+ */
+ public static final int MENU_ITEM_WEB_SEARCH = 1 << 1;
+
+ /**
+ * Disable all the action mode menu items for text processing.
+ * By default WebView searches for activities that are able to handle
+ * {@link android.content.Intent#ACTION_PROCESS_TEXT} and show them in the
+ * action mode menu. If this flag is set via {@link
+ * #setDisabledActionModeMenuItems}, these menu items will be disabled.
+ *
+ * @see #setDisabledActionModeMenuItems
+ */
+ public static final int MENU_ITEM_PROCESS_TEXT = 1 << 2;
+}
diff --git a/AndroidCompat/src/main/java/android/webkit/WebView.java b/AndroidCompat/src/main/java/android/webkit/WebView.java
new file mode 100644
index 00000000..f82a39cb
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/webkit/WebView.java
@@ -0,0 +1,1368 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.Widget;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Picture;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.net.http.SslCertificate;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.StrictMode;
+import android.print.PrintDocumentAdapter;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.LongSparseArray;
+import android.util.SparseArray;
+import android.view.DragEvent;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.PointerIcon;
+import android.view.View;
+import android.view.ViewDebug;
+import android.view.ViewGroup;
+import android.view.ViewStructure;
+import android.view.ViewTreeObserver;
+import android.view.WindowInsets;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeProvider;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.textclassifier.TextClassifier;
+import android.widget.AbsoluteLayout;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+import xyz.nulldev.androidcompat.CallableArgument;
+
+// Implementation notes.
+// The WebView is a thin API class that delegates its public API to a backend WebViewProvider
+// class instance. WebView extends {@link AbsoluteLayout} for backward compatibility reasons.
+// Methods are delegated to the provider implementation: all public API methods introduced in this
+// file are fully delegated, whereas public and protected methods from the View base classes are
+// only delegated where a specific need exists for them to do so.
+@Widget
+public class WebView extends AbsoluteLayout
+ implements ViewTreeObserver.OnGlobalFocusChangeListener,
+ ViewGroup.OnHierarchyChangeListener /*, ViewDebug.HierarchyHandler */ {
+
+ private static final String LOGTAG = "WebView";
+
+ // Throwing an exception for incorrect thread usage if the
+ // build target is JB MR2 or newer. Defaults to false, and is
+ // set in the WebView constructor.
+ private static volatile boolean sEnforceThreadChecking = false;
+ private static CallableArgument mProviderFactory;
+
+ public static void setProviderFactory(CallableArgument factory) {
+ mProviderFactory = factory;
+ }
+
+ public class WebViewTransport {
+ private WebView mWebview;
+
+ public synchronized void setWebView(@Nullable WebView webview) {
+ mWebview = webview;
+ }
+
+ @Nullable
+ public synchronized WebView getWebView() {
+ return mWebview;
+ }
+ }
+
+ public static final String SCHEME_GEO = "geo:0,0?q=";
+
+ public interface FindListener {
+ public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
+ boolean isDoneCounting);
+ }
+
+ public static abstract class VisualStateCallback {
+ public abstract void onComplete(long requestId);
+ }
+
+ @Deprecated
+ public interface PictureListener {
+ @Deprecated
+ void onNewPicture(WebView view, @Nullable Picture picture);
+ }
+
+ public static class HitTestResult {
+ public static final int EDIT_TEXT_TYPE = 9;
+
+ private int mType;
+ private String mExtra;
+
+ @SystemApi
+ public HitTestResult() {
+ }
+
+ @SystemApi
+ public void setType(int type) {
+ mType = type;
+ }
+
+ @SystemApi
+ public void setExtra(String extra) {
+ mExtra = extra;
+ }
+
+ public int getType() {
+ return mType;
+ }
+
+ @Nullable
+ public String getExtra() {
+ return mExtra;
+ }
+ }
+
+ public WebView(@NonNull Context context) {
+ this(context, null);
+ }
+
+ public WebView(@NonNull Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public WebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public WebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ this(context, attrs, defStyleAttr, defStyleRes, null, false);
+ }
+
+ @Deprecated
+ public WebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+ boolean privateBrowsing) {
+ this(context, attrs, defStyleAttr, 0, null, privateBrowsing);
+ }
+
+ protected WebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+ @Nullable Map javaScriptInterfaces, boolean privateBrowsing) {
+ this(context, attrs, defStyleAttr, 0, javaScriptInterfaces, privateBrowsing);
+ }
+
+ @SuppressWarnings("deprecation") // for super() call into deprecated base class constructor.
+ protected WebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+ int defStyleRes, @Nullable Map javaScriptInterfaces,
+ boolean privateBrowsing) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ if (context == null) {
+ throw new IllegalArgumentException("Invalid context argument");
+ }
+ if (mWebViewThread == null) {
+ throw new RuntimeException(
+ "WebView cannot be initialized on a thread that has no Looper.");
+ }
+ sEnforceThreadChecking = true;
+ checkThread();
+
+ ensureProviderCreated();
+ mProvider.init(javaScriptInterfaces, privateBrowsing);
+ }
+
+ @Deprecated
+ public void setHorizontalScrollbarOverlay(boolean overlay) {
+ }
+
+ @Deprecated
+ public void setVerticalScrollbarOverlay(boolean overlay) {
+ }
+
+ @Deprecated
+ public boolean overlayHorizontalScrollbar() {
+ // The old implementation defaulted to true, so return true for consistency
+ return true;
+ }
+
+ @Deprecated
+ public boolean overlayVerticalScrollbar() {
+ // The old implementation defaulted to false, so return false for consistency
+ return false;
+ }
+
+ @Deprecated
+ public int getVisibleTitleHeight() {
+ checkThread();
+ return mProvider.getVisibleTitleHeight();
+ }
+
+ @Nullable
+ public SslCertificate getCertificate() {
+ checkThread();
+ return mProvider.getCertificate();
+ }
+
+ @Deprecated
+ public void setCertificate(SslCertificate certificate) {
+ checkThread();
+ mProvider.setCertificate(certificate);
+ }
+
+ //-------------------------------------------------------------------------
+ // Methods called by activity
+ //-------------------------------------------------------------------------
+
+ @Deprecated
+ public void savePassword(String host, String username, String password) {
+ checkThread();
+ mProvider.savePassword(host, username, password);
+ }
+
+ @Deprecated
+ public void setHttpAuthUsernamePassword(String host, String realm,
+ String username, String password) {
+ checkThread();
+ mProvider.setHttpAuthUsernamePassword(host, realm, username, password);
+ }
+
+ @Deprecated
+ @Nullable
+ public String[] getHttpAuthUsernamePassword(String host, String realm) {
+ checkThread();
+ return mProvider.getHttpAuthUsernamePassword(host, realm);
+ }
+
+ public void destroy() {
+ checkThread();
+ mProvider.destroy();
+ }
+
+ @Deprecated
+ public static void enablePlatformNotifications() {
+ // noop
+ }
+
+ @Deprecated
+ public static void disablePlatformNotifications() {
+ // noop
+ }
+
+ public static void freeMemoryForTests() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void setNetworkAvailable(boolean networkUp) {
+ checkThread();
+ mProvider.setNetworkAvailable(networkUp);
+ }
+
+ @Nullable
+ public WebBackForwardList saveState(@NonNull Bundle outState) {
+ checkThread();
+ return mProvider.saveState(outState);
+ }
+
+ @Deprecated
+ public boolean savePicture(Bundle b, final File dest) {
+ checkThread();
+ return mProvider.savePicture(b, dest);
+ }
+
+ @Deprecated
+ public boolean restorePicture(Bundle b, File src) {
+ checkThread();
+ return mProvider.restorePicture(b, src);
+ }
+
+ @Nullable
+ public WebBackForwardList restoreState(@NonNull Bundle inState) {
+ checkThread();
+ return mProvider.restoreState(inState);
+ }
+
+ public void loadUrl(@NonNull String url, @NonNull Map additionalHttpHeaders) {
+ checkThread();
+ mProvider.loadUrl(url, additionalHttpHeaders);
+ }
+
+ public void loadUrl(@NonNull String url) {
+ checkThread();
+ mProvider.loadUrl(url);
+ }
+
+ public void postUrl(@NonNull String url, @NonNull byte[] postData) {
+ checkThread();
+ if (URLUtil.isNetworkUrl(url)) {
+ mProvider.postUrl(url, postData);
+ } else {
+ mProvider.loadUrl(url);
+ }
+ }
+
+ public void loadData(@NonNull String data, @Nullable String mimeType,
+ @Nullable String encoding) {
+ checkThread();
+ mProvider.loadData(data, mimeType, encoding);
+ }
+
+ public void loadDataWithBaseURL(@Nullable String baseUrl, @NonNull String data,
+ @Nullable String mimeType, @Nullable String encoding, @Nullable String historyUrl) {
+ checkThread();
+ mProvider.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
+ }
+
+ public void evaluateJavascript(@NonNull String script, @Nullable ValueCallback
+ resultCallback) {
+ checkThread();
+ mProvider.evaluateJavaScript(script, resultCallback);
+ }
+
+ public void saveWebArchive(@NonNull String filename) {
+ checkThread();
+ mProvider.saveWebArchive(filename);
+ }
+
+ public void saveWebArchive(@NonNull String basename, boolean autoname,
+ @Nullable ValueCallback callback) {
+ checkThread();
+ mProvider.saveWebArchive(basename, autoname, callback);
+ }
+
+ public void stopLoading() {
+ checkThread();
+ mProvider.stopLoading();
+ }
+
+ public void reload() {
+ checkThread();
+ mProvider.reload();
+ }
+
+ public boolean canGoBack() {
+ checkThread();
+ return mProvider.canGoBack();
+ }
+
+ public void goBack() {
+ checkThread();
+ mProvider.goBack();
+ }
+
+ public boolean canGoForward() {
+ checkThread();
+ return mProvider.canGoForward();
+ }
+
+ public void goForward() {
+ checkThread();
+ mProvider.goForward();
+ }
+
+ public boolean canGoBackOrForward(int steps) {
+ checkThread();
+ return mProvider.canGoBackOrForward(steps);
+ }
+
+ public void goBackOrForward(int steps) {
+ checkThread();
+ mProvider.goBackOrForward(steps);
+ }
+
+ public boolean isPrivateBrowsingEnabled() {
+ checkThread();
+ return mProvider.isPrivateBrowsingEnabled();
+ }
+
+ public boolean pageUp(boolean top) {
+ checkThread();
+ return mProvider.pageUp(top);
+ }
+
+ public boolean pageDown(boolean bottom) {
+ checkThread();
+ return mProvider.pageDown(bottom);
+ }
+
+ public void postVisualStateCallback(long requestId, @NonNull VisualStateCallback callback) {
+ checkThread();
+ mProvider.insertVisualStateCallback(requestId, callback);
+ }
+
+ @Deprecated
+ public void clearView() {
+ checkThread();
+ mProvider.clearView();
+ }
+
+ @Deprecated
+ public Picture capturePicture() {
+ checkThread();
+ return mProvider.capturePicture();
+ }
+
+ @Deprecated
+ public PrintDocumentAdapter createPrintDocumentAdapter() {
+ checkThread();
+ return mProvider.createPrintDocumentAdapter("default");
+ }
+
+ @NonNull
+ public PrintDocumentAdapter createPrintDocumentAdapter(@NonNull String documentName) {
+ checkThread();
+ return mProvider.createPrintDocumentAdapter(documentName);
+ }
+
+ @Deprecated
+ @ViewDebug.ExportedProperty(category = "webview")
+ public float getScale() {
+ checkThread();
+ return mProvider.getScale();
+ }
+
+ public void setInitialScale(int scaleInPercent) {
+ checkThread();
+ mProvider.setInitialScale(scaleInPercent);
+ }
+
+ public void invokeZoomPicker() {
+ checkThread();
+ mProvider.invokeZoomPicker();
+ }
+
+ @NonNull
+ public HitTestResult getHitTestResult() {
+ checkThread();
+ return mProvider.getHitTestResult();
+ }
+
+ public void requestFocusNodeHref(@Nullable Message hrefMsg) {
+ checkThread();
+ mProvider.requestFocusNodeHref(hrefMsg);
+ }
+
+ public void requestImageRef(@NonNull Message msg) {
+ checkThread();
+ mProvider.requestImageRef(msg);
+ }
+
+ @ViewDebug.ExportedProperty(category = "webview")
+ @Nullable
+ public String getUrl() {
+ checkThread();
+ return mProvider.getUrl();
+ }
+
+ @ViewDebug.ExportedProperty(category = "webview")
+ @Nullable
+ public String getOriginalUrl() {
+ checkThread();
+ return mProvider.getOriginalUrl();
+ }
+
+ @ViewDebug.ExportedProperty(category = "webview")
+ @Nullable
+ public String getTitle() {
+ checkThread();
+ return mProvider.getTitle();
+ }
+
+ @Nullable
+ public Bitmap getFavicon() {
+ checkThread();
+ return mProvider.getFavicon();
+ }
+
+ public String getTouchIconUrl() {
+ return mProvider.getTouchIconUrl();
+ }
+
+ public int getProgress() {
+ checkThread();
+ return mProvider.getProgress();
+ }
+
+ @ViewDebug.ExportedProperty(category = "webview")
+ public int getContentHeight() {
+ checkThread();
+ return mProvider.getContentHeight();
+ }
+
+ @ViewDebug.ExportedProperty(category = "webview")
+ public int getContentWidth() {
+ return mProvider.getContentWidth();
+ }
+
+ public void pauseTimers() {
+ checkThread();
+ mProvider.pauseTimers();
+ }
+
+ public void resumeTimers() {
+ checkThread();
+ mProvider.resumeTimers();
+ }
+
+ public void onPause() {
+ checkThread();
+ mProvider.onPause();
+ }
+
+ public void onResume() {
+ checkThread();
+ mProvider.onResume();
+ }
+
+ public boolean isPaused() {
+ return mProvider.isPaused();
+ }
+
+ @Deprecated
+ public void freeMemory() {
+ checkThread();
+ mProvider.freeMemory();
+ }
+
+ public void clearCache(boolean includeDiskFiles) {
+ checkThread();
+ mProvider.clearCache(includeDiskFiles);
+ }
+
+ public void clearFormData() {
+ checkThread();
+ mProvider.clearFormData();
+ }
+
+ public void clearHistory() {
+ checkThread();
+ mProvider.clearHistory();
+ }
+
+ public void clearSslPreferences() {
+ checkThread();
+ mProvider.clearSslPreferences();
+ }
+
+ public static void clearClientCertPreferences(@Nullable Runnable onCleared) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Deprecated
+ public static void startSafeBrowsing(@NonNull Context context,
+ @Nullable ValueCallback callback) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static void setSafeBrowsingWhitelist(@NonNull List hosts,
+ @Nullable ValueCallback callback) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @NonNull
+ public static Uri getSafeBrowsingPrivacyPolicyUrl() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @NonNull
+ public WebBackForwardList copyBackForwardList() {
+ checkThread();
+ return mProvider.copyBackForwardList();
+
+ }
+
+ public void setFindListener(@Nullable FindListener listener) {
+ checkThread();
+ setupFindListenerIfNeeded();
+ mFindListener.mUserFindListener = listener;
+ }
+
+ public void findNext(boolean forward) {
+ checkThread();
+ mProvider.findNext(forward);
+ }
+
+ @Deprecated
+ public int findAll(String find) {
+ checkThread();
+ StrictMode.noteSlowCall("findAll blocks UI: prefer findAllAsync");
+ return mProvider.findAll(find);
+ }
+
+ public void findAllAsync(@NonNull String find) {
+ checkThread();
+ mProvider.findAllAsync(find);
+ }
+
+ @Deprecated
+ public boolean showFindDialog(@Nullable String text, boolean showIme) {
+ checkThread();
+ return mProvider.showFindDialog(text, showIme);
+ }
+
+ @Nullable
+ @Deprecated
+ public static String findAddress(String addr) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static void enableSlowWholeDocumentDraw() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void clearMatches() {
+ checkThread();
+ mProvider.clearMatches();
+ }
+
+ public void documentHasImages(@NonNull Message response) {
+ checkThread();
+ mProvider.documentHasImages(response);
+ }
+
+ public void setWebViewClient(@NonNull WebViewClient client) {
+ checkThread();
+ mProvider.setWebViewClient(client);
+ }
+
+ @NonNull
+ public WebViewClient getWebViewClient() {
+ checkThread();
+ return mProvider.getWebViewClient();
+ }
+
+
+ @Nullable
+ public WebViewRenderProcess getWebViewRenderProcess() {
+ checkThread();
+ return mProvider.getWebViewRenderProcess();
+ }
+
+ public void setWebViewRenderProcessClient(
+ @NonNull Executor executor,
+ @NonNull WebViewRenderProcessClient webViewRenderProcessClient) {
+ checkThread();
+ mProvider.setWebViewRenderProcessClient(
+ executor, webViewRenderProcessClient);
+ }
+
+ public void setWebViewRenderProcessClient(
+ @Nullable WebViewRenderProcessClient webViewRenderProcessClient) {
+ checkThread();
+ mProvider.setWebViewRenderProcessClient(null, webViewRenderProcessClient);
+ }
+
+ @Nullable
+ public WebViewRenderProcessClient getWebViewRenderProcessClient() {
+ checkThread();
+ return mProvider.getWebViewRenderProcessClient();
+ }
+
+ public void setDownloadListener(@Nullable DownloadListener listener) {
+ checkThread();
+ mProvider.setDownloadListener(listener);
+ }
+
+ public void setWebChromeClient(@Nullable WebChromeClient client) {
+ checkThread();
+ mProvider.setWebChromeClient(client);
+ }
+
+ @Nullable
+ public WebChromeClient getWebChromeClient() {
+ checkThread();
+ return mProvider.getWebChromeClient();
+ }
+
+ @Deprecated
+ public void setPictureListener(PictureListener listener) {
+ checkThread();
+ mProvider.setPictureListener(listener);
+ }
+
+ public void addJavascriptInterface(@NonNull Object object, @NonNull String name) {
+ checkThread();
+ mProvider.addJavascriptInterface(object, name);
+ }
+
+ public void removeJavascriptInterface(@NonNull String name) {
+ checkThread();
+ mProvider.removeJavascriptInterface(name);
+ }
+
+ @NonNull
+ public WebMessagePort[] createWebMessageChannel() {
+ checkThread();
+ return mProvider.createWebMessageChannel();
+ }
+
+ public void postWebMessage(@NonNull WebMessage message, @NonNull Uri targetOrigin) {
+ checkThread();
+ mProvider.postMessageToMainFrame(message, targetOrigin);
+ }
+
+ @NonNull
+ public WebSettings getSettings() {
+ checkThread();
+ return mProvider.getSettings();
+ }
+
+ public static void setWebContentsDebuggingEnabled(boolean enabled) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static void setDataDirectorySuffix(@NonNull String suffix) {
+ throw new RuntimeException("Stub!");
+ }
+
+ public static void disableWebView() {
+ }
+
+
+ @Deprecated
+ public void refreshPlugins(boolean reloadOpenPages) {
+ checkThread();
+ }
+
+ @Deprecated
+ public void emulateShiftHeld() {
+ checkThread();
+ }
+
+ @Override
+ // Cannot add @hide as this can always be accessed via the interface.
+ @Deprecated
+ public void onChildViewAdded(View parent, View child) {}
+
+ @Override
+ // Cannot add @hide as this can always be accessed via the interface.
+ @Deprecated
+ public void onChildViewRemoved(View p, View child) {}
+
+ @Override
+ // Cannot add @hide as this can always be accessed via the interface.
+ @Deprecated
+ public void onGlobalFocusChanged(View oldFocus, View newFocus) {
+ }
+
+ @Deprecated
+ public void setMapTrackballToArrowKeys(boolean setMap) {
+ checkThread();
+ mProvider.setMapTrackballToArrowKeys(setMap);
+ }
+
+
+ public void flingScroll(int vx, int vy) {
+ checkThread();
+ mProvider.flingScroll(vx, vy);
+ }
+
+ @Deprecated
+ public View getZoomControls() {
+ checkThread();
+ return mProvider.getZoomControls();
+ }
+
+ @Deprecated
+ public boolean canZoomIn() {
+ checkThread();
+ return mProvider.canZoomIn();
+ }
+
+ @Deprecated
+ public boolean canZoomOut() {
+ checkThread();
+ return mProvider.canZoomOut();
+ }
+
+ public void zoomBy(float zoomFactor) {
+ checkThread();
+ if (zoomFactor < 0.01)
+ throw new IllegalArgumentException("zoomFactor must be greater than 0.01.");
+ if (zoomFactor > 100.0)
+ throw new IllegalArgumentException("zoomFactor must be less than 100.");
+ mProvider.zoomBy(zoomFactor);
+ }
+
+ public boolean zoomIn() {
+ checkThread();
+ return mProvider.zoomIn();
+ }
+
+ public boolean zoomOut() {
+ checkThread();
+ return mProvider.zoomOut();
+ }
+
+ @Deprecated
+ public void debugDump() {
+ checkThread();
+ }
+
+ public void dumpViewHierarchyWithProperties(BufferedWriter out, int level) {
+ mProvider.dumpViewHierarchyWithProperties(out, level);
+ }
+
+ public View findHierarchyView(String className, int hashCode) {
+ return mProvider.findHierarchyView(className, hashCode);
+ }
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RendererPriority {}
+
+ public static final int RENDERER_PRIORITY_IMPORTANT = 2;
+
+ public void setRendererPriorityPolicy(
+ @RendererPriority int rendererRequestedPriority,
+ boolean waivedWhenNotVisible) {
+ mProvider.setRendererPriorityPolicy(rendererRequestedPriority, waivedWhenNotVisible);
+ }
+
+ @RendererPriority
+ public int getRendererRequestedPriority() {
+ return mProvider.getRendererRequestedPriority();
+ }
+
+ public boolean getRendererPriorityWaivedWhenNotVisible() {
+ return mProvider.getRendererPriorityWaivedWhenNotVisible();
+ }
+
+ public void setTextClassifier(@Nullable TextClassifier textClassifier) {
+ mProvider.setTextClassifier(textClassifier);
+ }
+
+ @NonNull
+ public TextClassifier getTextClassifier() {
+ return mProvider.getTextClassifier();
+ }
+
+ @NonNull
+ public static ClassLoader getWebViewClassLoader() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @NonNull
+ public Looper getWebViewLooper() {
+ return mWebViewThread;
+ }
+
+ //-------------------------------------------------------------------------
+ // Interface for WebView providers
+ //-------------------------------------------------------------------------
+
+ @SystemApi
+ public WebViewProvider getWebViewProvider() {
+ return mProvider;
+ }
+
+ //-------------------------------------------------------------------------
+ // Package-private internal stuff
+ //-------------------------------------------------------------------------
+
+ // Only used by android.webkit.FindActionModeCallback.
+ void setFindDialogFindListener(FindListener listener) {
+ checkThread();
+ setupFindListenerIfNeeded();
+ mFindListener.mFindDialogFindListener = listener;
+ }
+
+ // Only used by android.webkit.FindActionModeCallback.
+ void notifyFindDialogDismissed() {
+ checkThread();
+ mProvider.notifyFindDialogDismissed();
+ }
+
+ //-------------------------------------------------------------------------
+ // Private internal stuff
+ //-------------------------------------------------------------------------
+
+ private WebViewProvider mProvider;
+
+ private class FindListenerDistributor implements FindListener {
+ private FindListener mFindDialogFindListener;
+ private FindListener mUserFindListener;
+
+ @Override
+ public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
+ boolean isDoneCounting) {
+ if (mFindDialogFindListener != null) {
+ mFindDialogFindListener.onFindResultReceived(activeMatchOrdinal, numberOfMatches,
+ isDoneCounting);
+ }
+
+ if (mUserFindListener != null) {
+ mUserFindListener.onFindResultReceived(activeMatchOrdinal, numberOfMatches,
+ isDoneCounting);
+ }
+ }
+ }
+ private FindListenerDistributor mFindListener;
+
+ private void setupFindListenerIfNeeded() {
+ if (mFindListener == null) {
+ mFindListener = new FindListenerDistributor();
+ mProvider.setFindListener(mFindListener);
+ }
+ }
+
+ private void ensureProviderCreated() {
+ checkThread();
+ if (mProvider == null) {
+ if (mProviderFactory == null)
+ throw new IllegalStateException("No factory registered");
+ // As this can get called during the base class constructor chain, pass the minimum
+ // number of dependencies here; the rest are deferred to init().
+ mProvider = mProviderFactory.call(this);
+ }
+ }
+
+ private final Looper mWebViewThread = Looper.myLooper();
+
+ private void checkThread() {
+ // Ignore mWebViewThread == null because this can be called during in the super class
+ // constructor, before this class's own constructor has even started.
+ if (mWebViewThread != null && Looper.myLooper() != mWebViewThread) {
+ Throwable throwable = new Throwable(
+ "A WebView method was called on thread '" +
+ Thread.currentThread().getName() + "'. " +
+ "All WebView methods must be called on the same thread. " +
+ "(Expected Looper " + mWebViewThread + " called on " + Looper.myLooper() +
+ ", FYI main Looper is " + Looper.getMainLooper() + ")");
+ Log.w(LOGTAG, Log.getStackTraceString(throwable));
+
+ if (sEnforceThreadChecking) {
+ throw new RuntimeException(throwable);
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ // Override View methods
+ //-------------------------------------------------------------------------
+
+ // TODO: Add a test that enumerates all methods in ViewDelegte & ScrollDelegate, and ensures
+ // there's a corresponding override (or better, caller) for each of them in here.
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mProvider.getViewDelegate().onAttachedToWindow();
+ }
+
+ // /** @hide */
+ // protected void onDetachedFromWindowInternal() {
+ // mProvider.getViewDelegate().onDetachedFromWindow();
+ // super.onDetachedFromWindowInternal();
+ // }
+
+ /** @hide */
+ public void onMovedToDisplay(int displayId, Configuration config) {
+ mProvider.getViewDelegate().onMovedToDisplay(displayId, config);
+ }
+
+ @Override
+ public void setLayoutParams(ViewGroup.LayoutParams params) {
+ mProvider.getViewDelegate().setLayoutParams(params);
+ }
+
+ @Override
+ public void setOverScrollMode(int mode) {
+ super.setOverScrollMode(mode);
+ // This method may be called in the constructor chain, before the WebView provider is
+ // created.
+ ensureProviderCreated();
+ mProvider.getViewDelegate().setOverScrollMode(mode);
+ }
+
+ @Override
+ public void setScrollBarStyle(int style) {
+ mProvider.getViewDelegate().setScrollBarStyle(style);
+ super.setScrollBarStyle(style);
+ }
+
+ @Override
+ protected int computeHorizontalScrollRange() {
+ return mProvider.getScrollDelegate().computeHorizontalScrollRange();
+ }
+
+ @Override
+ protected int computeHorizontalScrollOffset() {
+ return mProvider.getScrollDelegate().computeHorizontalScrollOffset();
+ }
+
+ @Override
+ protected int computeVerticalScrollRange() {
+ return mProvider.getScrollDelegate().computeVerticalScrollRange();
+ }
+
+ @Override
+ protected int computeVerticalScrollOffset() {
+ return mProvider.getScrollDelegate().computeVerticalScrollOffset();
+ }
+
+ @Override
+ protected int computeVerticalScrollExtent() {
+ return mProvider.getScrollDelegate().computeVerticalScrollExtent();
+ }
+
+ @Override
+ public void computeScroll() {
+ mProvider.getScrollDelegate().computeScroll();
+ }
+
+ @Override
+ public boolean onHoverEvent(MotionEvent event) {
+ return mProvider.getViewDelegate().onHoverEvent(event);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ return mProvider.getViewDelegate().onTouchEvent(event);
+ }
+
+ @Override
+ public boolean onGenericMotionEvent(MotionEvent event) {
+ return mProvider.getViewDelegate().onGenericMotionEvent(event);
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+ return mProvider.getViewDelegate().onTrackballEvent(event);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return mProvider.getViewDelegate().onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ return mProvider.getViewDelegate().onKeyUp(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
+ return mProvider.getViewDelegate().onKeyMultiple(keyCode, repeatCount, event);
+ }
+
+ /*
+ TODO: These are not currently implemented in WebViewClassic, but it seems inconsistent not
+ to be delegating them too.
+
+ @Override
+ public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+ return mProvider.getViewDelegate().onKeyPreIme(keyCode, event);
+ }
+ @Override
+ public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+ return mProvider.getViewDelegate().onKeyLongPress(keyCode, event);
+ }
+ @Override
+ public boolean onKeyShortcut(int keyCode, KeyEvent event) {
+ return mProvider.getViewDelegate().onKeyShortcut(keyCode, event);
+ }
+ */
+
+ @Override
+ public AccessibilityNodeProvider getAccessibilityNodeProvider() {
+ AccessibilityNodeProvider provider =
+ mProvider.getViewDelegate().getAccessibilityNodeProvider();
+ return provider == null ? super.getAccessibilityNodeProvider() : provider;
+ }
+
+ @Deprecated
+ @Override
+ public boolean shouldDelayChildPressedState() {
+ return mProvider.getViewDelegate().shouldDelayChildPressedState();
+ }
+
+ @Override
+ public CharSequence getAccessibilityClassName() {
+ return WebView.class.getName();
+ }
+
+ @Override
+ public void onProvideVirtualStructure(ViewStructure structure) {
+ mProvider.getViewDelegate().onProvideVirtualStructure(structure);
+ }
+
+ @Override
+ public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
+ mProvider.getViewDelegate().onProvideAutofillVirtualStructure(structure, flags);
+ }
+
+ @Override
+ public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
+ mProvider.getViewDelegate().onProvideContentCaptureStructure(structure, flags);
+ }
+
+ @Override
+ public void autofill(SparseArrayvalues) {
+ mProvider.getViewDelegate().autofill(values);
+ }
+
+ @Override
+ public boolean isVisibleToUserForAutofill(int virtualId) {
+ return mProvider.getViewDelegate().isVisibleToUserForAutofill(virtualId);
+ }
+
+ // @Nullable
+ // public void onCreateVirtualViewTranslationRequests(@NonNull long[] virtualIds,
+ // @NonNull int[] supportedFormats,
+ // @NonNull Consumer requestsCollector) {
+ // mProvider.getViewDelegate().onCreateVirtualViewTranslationRequests(virtualIds,
+ // supportedFormats, requestsCollector);
+ // }
+
+ // public void dispatchCreateViewTranslationRequest(@NonNull Map viewIds,
+ // @NonNull int[] supportedFormats,
+ // @Nullable TranslationCapability capability,
+ // @NonNull List requests) {
+ // super.dispatchCreateViewTranslationRequest(viewIds, supportedFormats, capability, requests);
+ // mProvider.getViewDelegate().dispatchCreateViewTranslationRequest(viewIds, supportedFormats,
+ // capability, requests);
+ // }
+
+ // public void onVirtualViewTranslationResponses(
+ // @NonNull LongSparseArray response) {
+ // mProvider.getViewDelegate().onVirtualViewTranslationResponses(response);
+ // }
+
+ // /** @hide */
+ // public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
+ // super.onInitializeAccessibilityNodeInfoInternal(info);
+ // mProvider.getViewDelegate().onInitializeAccessibilityNodeInfo(info);
+ // }
+
+ // /** @hide */
+ // public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
+ // super.onInitializeAccessibilityEventInternal(event);
+ // mProvider.getViewDelegate().onInitializeAccessibilityEvent(event);
+ // }
+
+ /** @hide */
+ public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
+ return mProvider.getViewDelegate().performAccessibilityAction(action, arguments);
+ }
+
+ /** @hide */
+ protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
+ int l, int t, int r, int b) {
+ mProvider.getViewDelegate().onDrawVerticalScrollBar(canvas, scrollBar, l, t, r, b);
+ }
+
+ @Override
+ protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
+ mProvider.getViewDelegate().onOverScrolled(scrollX, scrollY, clampedX, clampedY);
+ }
+
+ @Override
+ protected void onWindowVisibilityChanged(int visibility) {
+ super.onWindowVisibilityChanged(visibility);
+ mProvider.getViewDelegate().onWindowVisibilityChanged(visibility);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ mProvider.getViewDelegate().onDraw(canvas);
+ }
+
+ @Override
+ public boolean performLongClick() {
+ return mProvider.getViewDelegate().performLongClick();
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ mProvider.getViewDelegate().onConfigurationChanged(newConfig);
+ }
+
+ @Override
+ public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+ return mProvider.getViewDelegate().onCreateInputConnection(outAttrs);
+ }
+
+ @Override
+ public boolean onDragEvent(DragEvent event) {
+ return mProvider.getViewDelegate().onDragEvent(event);
+ }
+
+ @Override
+ protected void onVisibilityChanged(View changedView, int visibility) {
+ super.onVisibilityChanged(changedView, visibility);
+ // This method may be called in the constructor chain, before the WebView provider is
+ // created.
+ ensureProviderCreated();
+ mProvider.getViewDelegate().onVisibilityChanged(changedView, visibility);
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ mProvider.getViewDelegate().onWindowFocusChanged(hasWindowFocus);
+ super.onWindowFocusChanged(hasWindowFocus);
+ }
+
+ @Override
+ protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+ mProvider.getViewDelegate().onFocusChanged(focused, direction, previouslyFocusedRect);
+ super.onFocusChanged(focused, direction, previouslyFocusedRect);
+ }
+
+ /** @hide */
+ protected boolean setFrame(int left, int top, int right, int bottom) {
+ return mProvider.getViewDelegate().setFrame(left, top, right, bottom);
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int ow, int oh) {
+ super.onSizeChanged(w, h, ow, oh);
+ mProvider.getViewDelegate().onSizeChanged(w, h, ow, oh);
+ }
+
+ @Override
+ protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+ super.onScrollChanged(l, t, oldl, oldt);
+ mProvider.getViewDelegate().onScrollChanged(l, t, oldl, oldt);
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ return mProvider.getViewDelegate().dispatchKeyEvent(event);
+ }
+
+ @Override
+ public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
+ return mProvider.getViewDelegate().requestFocus(direction, previouslyFocusedRect);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ mProvider.getViewDelegate().onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ @Override
+ public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) {
+ return mProvider.getViewDelegate().requestChildRectangleOnScreen(child, rect, immediate);
+ }
+
+ @Override
+ public void setBackgroundColor(int color) {
+ mProvider.getViewDelegate().setBackgroundColor(color);
+ }
+
+ @Override
+ public void setLayerType(int layerType, Paint paint) {
+ // ignore
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ mProvider.getViewDelegate().preDispatchDraw(canvas);
+ super.dispatchDraw(canvas);
+ }
+
+ @Override
+ public void onStartTemporaryDetach() {
+ super.onStartTemporaryDetach();
+ mProvider.getViewDelegate().onStartTemporaryDetach();
+ }
+
+ @Override
+ public void onFinishTemporaryDetach() {
+ super.onFinishTemporaryDetach();
+ mProvider.getViewDelegate().onFinishTemporaryDetach();
+ }
+
+ @Override
+ public Handler getHandler() {
+ return mProvider.getViewDelegate().getHandler(super.getHandler());
+ }
+
+ @Override
+ public View findFocus() {
+ return mProvider.getViewDelegate().findFocus(super.findFocus());
+ }
+
+ @Nullable
+ public static PackageInfo getCurrentWebViewPackage() {
+ throw new RuntimeException("Stub!");
+ }
+
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ mProvider.getViewDelegate().onActivityResult(requestCode, resultCode, data);
+ }
+
+ @Override
+ public boolean onCheckIsTextEditor() {
+ return mProvider.getViewDelegate().onCheckIsTextEditor();
+ }
+
+ // /** @hide */
+ // protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+ // super.encodeProperties(encoder);
+
+ // checkThread();
+ // encoder.addProperty("webview:contentHeight", mProvider.getContentHeight());
+ // encoder.addProperty("webview:contentWidth", mProvider.getContentWidth());
+ // encoder.addProperty("webview:scale", mProvider.getScale());
+ // encoder.addProperty("webview:title", mProvider.getTitle());
+ // encoder.addProperty("webview:url", mProvider.getUrl());
+ // encoder.addProperty("webview:originalUrl", mProvider.getOriginalUrl());
+ // }
+
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ WindowInsets result = mProvider.getViewDelegate().onApplyWindowInsets(insets);
+ if (result == null) return super.onApplyWindowInsets(insets);
+ return result;
+ }
+
+ @Override
+ @Nullable
+ public PointerIcon onResolvePointerIcon(@NonNull MotionEvent event, int pointerIndex) {
+ PointerIcon icon =
+ mProvider.getViewDelegate().onResolvePointerIcon(event, pointerIndex);
+ if (icon != null) {
+ return icon;
+ }
+ return super.onResolvePointerIcon(event, pointerIndex);
+ }
+}
diff --git a/AndroidCompat/src/main/java/android/webkit/WebViewClient.java b/AndroidCompat/src/main/java/android/webkit/WebViewClient.java
new file mode 100644
index 00000000..5bc1172b
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/webkit/WebViewClient.java
@@ -0,0 +1,609 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.annotation.Nullable;
+import android.graphics.Bitmap;
+import android.net.http.SslError;
+import android.os.Message;
+import android.view.InputEvent;
+import android.view.KeyEvent;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+public class WebViewClient {
+
+ /**
+ * Give the host application a chance to take control when a URL is about to be loaded in the
+ * current WebView. If a WebViewClient is not provided, by default WebView will ask Activity
+ * Manager to choose the proper handler for the URL. If a WebViewClient is provided, returning
+ * {@code true} causes the current WebView to abort loading the URL, while returning
+ * {@code false} causes the WebView to continue loading the URL as usual.
+ *
+ * Note: Do not call {@link WebView#loadUrl(String)} with the same
+ * URL and then return {@code true}. This unnecessarily cancels the current load and starts a
+ * new load with the same URL. The correct way to continue loading a given URL is to simply
+ * return {@code false}, without calling {@link WebView#loadUrl(String)}.
+ *
+ *
Note: This method is not called for POST requests.
+ *
+ *
Note: This method may be called for subframes and with non-HTTP(S)
+ * schemes; calling {@link WebView#loadUrl(String)} with such a URL will fail.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param url The URL to be loaded.
+ * @return {@code true} to cancel the current load, otherwise return {@code false}.
+ * @deprecated Use {@link #shouldOverrideUrlLoading(WebView, WebResourceRequest)
+ * shouldOverrideUrlLoading(WebView, WebResourceRequest)} instead.
+ */
+ @Deprecated
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ return false;
+ }
+
+ /**
+ * Give the host application a chance to take control when a URL is about to be loaded in the
+ * current WebView. If a WebViewClient is not provided, by default WebView will ask Activity
+ * Manager to choose the proper handler for the URL. If a WebViewClient is provided, returning
+ * {@code true} causes the current WebView to abort loading the URL, while returning
+ * {@code false} causes the WebView to continue loading the URL as usual.
+ *
+ *
This callback is not called for all page navigations. In particular, this is not called
+ * for navigations which the app initiated with {@code loadUrl()}: this callback would not serve
+ * a purpose in this case, because the app already knows about the navigation. This callback
+ * lets the app know about navigations initiated by the web page (such as navigations initiated
+ * by JavaScript code), by the user (such as when the user taps on a link), or by an HTTP
+ * redirect (ex. if {@code loadUrl("foo.com")} redirects to {@code "bar.com"} because of HTTP
+ * 301).
+ *
+ *
Note: Do not call {@link WebView#loadUrl(String)} with the request's
+ * URL and then return {@code true}. This unnecessarily cancels the current load and starts a
+ * new load with the same URL. The correct way to continue loading a given URL is to simply
+ * return {@code false}, without calling {@link WebView#loadUrl(String)}.
+ *
+ *
Note: This method is not called for POST requests.
+ *
+ *
Note: This method may be called for subframes and with non-HTTP(S)
+ * schemes; calling {@link WebView#loadUrl(String)} with such a URL will fail.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param request Object containing the details of the request.
+ * @return {@code true} to cancel the current load, otherwise return {@code false}.
+ */
+ public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
+ return shouldOverrideUrlLoading(view, request.getUrl().toString());
+ }
+
+ /**
+ * Notify the host application that a page has started loading. This method
+ * is called once for each main frame load so a page with iframes or
+ * framesets will call onPageStarted one time for the main frame. This also
+ * means that onPageStarted will not be called when the contents of an
+ * embedded frame changes, i.e. clicking a link whose target is an iframe,
+ * it will also not be called for fragment navigations (navigations to
+ * #fragment_id).
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param url The url to be loaded.
+ * @param favicon The favicon for this page if it already exists in the
+ * database.
+ */
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+ }
+
+ /**
+ * Notify the host application that a page has finished loading. This method
+ * is called only for main frame. Receiving an {@code onPageFinished()} callback does not
+ * guarantee that the next frame drawn by WebView will reflect the state of the DOM at this
+ * point. In order to be notified that the current DOM state is ready to be rendered, request a
+ * visual state callback with {@link WebView#postVisualStateCallback} and wait for the supplied
+ * callback to be triggered.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param url The url of the page.
+ */
+ public void onPageFinished(WebView view, String url) {
+ }
+
+ /**
+ * Notify the host application that the WebView will load the resource
+ * specified by the given url.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param url The url of the resource the WebView will load.
+ */
+ public void onLoadResource(WebView view, String url) {
+ }
+
+ /**
+ * Notify the host application that {@link android.webkit.WebView} content left over from
+ * previous page navigations will no longer be drawn.
+ *
+ *
This callback can be used to determine the point at which it is safe to make a recycled
+ * {@link android.webkit.WebView} visible, ensuring that no stale content is shown. It is called
+ * at the earliest point at which it can be guaranteed that {@link WebView#onDraw} will no
+ * longer draw any content from previous navigations. The next draw will display either the
+ * {@link WebView#setBackgroundColor background color} of the {@link WebView}, or some of the
+ * contents of the newly loaded page.
+ *
+ *
This method is called when the body of the HTTP response has started loading, is reflected
+ * in the DOM, and will be visible in subsequent draws. This callback occurs early in the
+ * document loading process, and as such you should expect that linked resources (for example,
+ * CSS and images) may not be available.
+ *
+ *
For more fine-grained notification of visual state updates, see {@link
+ * WebView#postVisualStateCallback}.
+ *
+ *
Please note that all the conditions and recommendations applicable to
+ * {@link WebView#postVisualStateCallback} also apply to this API.
+ *
+ *
This callback is only called for main frame navigations.
+ *
+ * @param view The {@link android.webkit.WebView} for which the navigation occurred.
+ * @param url The URL corresponding to the page navigation that triggered this callback.
+ */
+ public void onPageCommitVisible(WebView view, String url) {
+ }
+
+ /**
+ * Notify the host application of a resource request and allow the
+ * application to return the data. If the return value is {@code null}, the WebView
+ * will continue to load the resource as usual. Otherwise, the return
+ * response and data will be used.
+ *
+ *
This callback is invoked for a variety of URL schemes (e.g., {@code http(s):}, {@code
+ * data:}, {@code file:}, etc.), not only those schemes which send requests over the network.
+ * This is not called for {@code javascript:} URLs, {@code blob:} URLs, or for assets accessed
+ * via {@code file:///android_asset/} or {@code file:///android_res/} URLs.
+ *
+ *
In the case of redirects, this is only called for the initial resource URL, not any
+ * subsequent redirect URLs.
+ *
+ *
Note: This method is called on a thread
+ * other than the UI thread so clients should exercise caution
+ * when accessing private data or the view system.
+ *
+ *
Note: When Safe Browsing is enabled, these URLs still undergo Safe
+ * Browsing checks. If this is undesired, you can use {@link WebView#setSafeBrowsingWhitelist}
+ * to skip Safe Browsing checks for that host or dismiss the warning in {@link
+ * #onSafeBrowsingHit} by calling {@link SafeBrowsingResponse#proceed}.
+ *
+ * @param view The {@link android.webkit.WebView} that is requesting the
+ * resource.
+ * @param url The raw url of the resource.
+ * @return A {@link android.webkit.WebResourceResponse} containing the
+ * response information or {@code null} if the WebView should load the
+ * resource itself.
+ * @deprecated Use {@link #shouldInterceptRequest(WebView, WebResourceRequest)
+ * shouldInterceptRequest(WebView, WebResourceRequest)} instead.
+ */
+ @Deprecated
+ @Nullable
+ public WebResourceResponse shouldInterceptRequest(WebView view,
+ String url) {
+ return null;
+ }
+
+ /**
+ * Notify the host application of a resource request and allow the
+ * application to return the data. If the return value is {@code null}, the WebView
+ * will continue to load the resource as usual. Otherwise, the return
+ * response and data will be used.
+ *
+ *
This callback is invoked for a variety of URL schemes (e.g., {@code http(s):}, {@code
+ * data:}, {@code file:}, etc.), not only those schemes which send requests over the network.
+ * This is not called for {@code javascript:} URLs, {@code blob:} URLs, or for assets accessed
+ * via {@code file:///android_asset/} or {@code file:///android_res/} URLs.
+ *
+ *
In the case of redirects, this is only called for the initial resource URL, not any
+ * subsequent redirect URLs.
+ *
+ *
Note: This method is called on a thread
+ * other than the UI thread so clients should exercise caution
+ * when accessing private data or the view system.
+ *
+ *
Note: When Safe Browsing is enabled, these URLs still undergo Safe
+ * Browsing checks. If this is undesired, you can use {@link WebView#setSafeBrowsingWhitelist}
+ * to skip Safe Browsing checks for that host or dismiss the warning in {@link
+ * #onSafeBrowsingHit} by calling {@link SafeBrowsingResponse#proceed}.
+ *
+ * @param view The {@link android.webkit.WebView} that is requesting the
+ * resource.
+ * @param request Object containing the details of the request.
+ * @return A {@link android.webkit.WebResourceResponse} containing the
+ * response information or {@code null} if the WebView should load the
+ * resource itself.
+ */
+ @Nullable
+ public WebResourceResponse shouldInterceptRequest(WebView view,
+ WebResourceRequest request) {
+ return shouldInterceptRequest(view, request.getUrl().toString());
+ }
+
+ /**
+ * Notify the host application that there have been an excessive number of
+ * HTTP redirects. As the host application if it would like to continue
+ * trying to load the resource. The default behavior is to send the cancel
+ * message.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param cancelMsg The message to send if the host wants to cancel
+ * @param continueMsg The message to send if the host wants to continue
+ * @deprecated This method is no longer called. When the WebView encounters
+ * a redirect loop, it will cancel the load.
+ */
+ @Deprecated
+ public void onTooManyRedirects(WebView view, Message cancelMsg,
+ Message continueMsg) {
+ cancelMsg.sendToTarget();
+ }
+
+ // These ints must match up to the hidden values in EventHandler.
+ /** Generic error */
+ public static final int ERROR_UNKNOWN = -1;
+ /** Server or proxy hostname lookup failed */
+ public static final int ERROR_HOST_LOOKUP = -2;
+ /** Unsupported authentication scheme (not basic or digest) */
+ public static final int ERROR_UNSUPPORTED_AUTH_SCHEME = -3;
+ /** User authentication failed on server */
+ public static final int ERROR_AUTHENTICATION = -4;
+ /** User authentication failed on proxy */
+ public static final int ERROR_PROXY_AUTHENTICATION = -5;
+ /** Failed to connect to the server */
+ public static final int ERROR_CONNECT = -6;
+ /** Failed to read or write to the server */
+ public static final int ERROR_IO = -7;
+ /** Connection timed out */
+ public static final int ERROR_TIMEOUT = -8;
+ /** Too many redirects */
+ public static final int ERROR_REDIRECT_LOOP = -9;
+ /** Unsupported URI scheme */
+ public static final int ERROR_UNSUPPORTED_SCHEME = -10;
+ /** Failed to perform SSL handshake */
+ public static final int ERROR_FAILED_SSL_HANDSHAKE = -11;
+ /** Malformed URL */
+ public static final int ERROR_BAD_URL = -12;
+ /** Generic file error */
+ public static final int ERROR_FILE = -13;
+ /** File not found */
+ public static final int ERROR_FILE_NOT_FOUND = -14;
+ /** Too many requests during this load */
+ public static final int ERROR_TOO_MANY_REQUESTS = -15;
+ /** Resource load was canceled by Safe Browsing */
+ public static final int ERROR_UNSAFE_RESOURCE = -16;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SafeBrowsingThreat {}
+
+ /** The resource was blocked for an unknown reason. */
+ public static final int SAFE_BROWSING_THREAT_UNKNOWN = 0;
+ /** The resource was blocked because it contains malware. */
+ public static final int SAFE_BROWSING_THREAT_MALWARE = 1;
+ /** The resource was blocked because it contains deceptive content. */
+ public static final int SAFE_BROWSING_THREAT_PHISHING = 2;
+ /** The resource was blocked because it contains unwanted software. */
+ public static final int SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE = 3;
+ /**
+ * The resource was blocked because it may trick the user into a billing agreement.
+ *
+ *
This constant is only used when targetSdkVersion is at least {@link
+ * android.os.Build.VERSION_CODES#Q}. Otherwise, {@link #SAFE_BROWSING_THREAT_UNKNOWN} is used
+ * instead.
+ */
+ public static final int SAFE_BROWSING_THREAT_BILLING = 4;
+
+ /**
+ * Report an error to the host application. These errors are unrecoverable
+ * (i.e. the main resource is unavailable). The {@code errorCode} parameter
+ * corresponds to one of the {@code ERROR_*} constants.
+ * @param view The WebView that is initiating the callback.
+ * @param errorCode The error code corresponding to an ERROR_* value.
+ * @param description A String describing the error.
+ * @param failingUrl The url that failed to load.
+ * @deprecated Use {@link #onReceivedError(WebView, WebResourceRequest, WebResourceError)
+ * onReceivedError(WebView, WebResourceRequest, WebResourceError)} instead.
+ */
+ @Deprecated
+ public void onReceivedError(WebView view, int errorCode,
+ String description, String failingUrl) {
+ }
+
+ /**
+ * Report web resource loading error to the host application. These errors usually indicate
+ * inability to connect to the server. Note that unlike the deprecated version of the callback,
+ * the new version will be called for any resource (iframe, image, etc.), not just for the main
+ * page. Thus, it is recommended to perform minimum required work in this callback.
+ * @param view The WebView that is initiating the callback.
+ * @param request The originating request.
+ * @param error Information about the error occurred.
+ */
+ public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
+ if (request.isForMainFrame()) {
+ onReceivedError(view,
+ error.getErrorCode(), error.getDescription().toString(),
+ request.getUrl().toString());
+ }
+ }
+
+ /**
+ * Notify the host application that an HTTP error has been received from the server while
+ * loading a resource. HTTP errors have status codes >= 400. This callback will be called
+ * for any resource (iframe, image, etc.), not just for the main page. Thus, it is recommended
+ * to perform minimum required work in this callback. Note that the content of the server
+ * response may not be provided within the {@code errorResponse} parameter.
+ * @param view The WebView that is initiating the callback.
+ * @param request The originating request.
+ * @param errorResponse Information about the error occurred.
+ */
+ public void onReceivedHttpError(
+ WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
+ }
+
+ /**
+ * As the host application if the browser should resend data as the
+ * requested page was a result of a POST. The default is to not resend the
+ * data.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param dontResend The message to send if the browser should not resend
+ * @param resend The message to send if the browser should resend data
+ */
+ public void onFormResubmission(WebView view, Message dontResend,
+ Message resend) {
+ dontResend.sendToTarget();
+ }
+
+ /**
+ * Notify the host application to update its visited links database.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param url The url being visited.
+ * @param isReload {@code true} if this url is being reloaded.
+ */
+ public void doUpdateVisitedHistory(WebView view, String url,
+ boolean isReload) {
+ }
+
+ /**
+ * Notifies the host application that an SSL error occurred while loading a
+ * resource. The host application must call either
+ * {@link SslErrorHandler#cancel()} or {@link SslErrorHandler#proceed()}.
+ *
+ *
Warning: Application overrides of this method
+ * can be used to display custom error pages or to silently log issues, but
+ * the host application should always call {@code SslErrorHandler#cancel()}
+ * and never proceed past errors.
+ *
+ *
Note: Do not prompt the user about SSL errors.
+ * Users are unlikely to be able to make an informed security decision, and
+ * {@code WebView} does not provide a UI for showing the details of the
+ * error in a meaningful way.
+ *
+ *
The decision to call {@code proceed()} or {@code cancel()} may be
+ * retained to facilitate responses to future SSL errors. The default
+ * behavior is to cancel the resource loading process.
+ *
+ *
This API is called only for recoverable SSL certificate errors. For
+ * non-recoverable errors (such as when the server fails the client), the
+ * {@code WebView} calls {@link #onReceivedError(WebView,
+ * WebResourceRequest, WebResourceError) onReceivedError(WebView,
+ * WebResourceRequest, WebResourceError)} with the
+ * {@link #ERROR_FAILED_SSL_HANDSHAKE} argument.
+ *
+ * @param view {@code WebView} that initiated the callback.
+ * @param handler {@link SslErrorHandler} that handles the user's response.
+ * @param error SSL error object.
+ */
+ public void onReceivedSslError(WebView view, SslErrorHandler handler,
+ SslError error) {
+ handler.cancel();
+ }
+
+ /**
+ * Notify the host application to handle a SSL client certificate request. The host application
+ * is responsible for showing the UI if desired and providing the keys. There are three ways to
+ * respond: {@link ClientCertRequest#proceed}, {@link ClientCertRequest#cancel}, or {@link
+ * ClientCertRequest#ignore}. Webview stores the response in memory (for the life of the
+ * application) if {@link ClientCertRequest#proceed} or {@link ClientCertRequest#cancel} is
+ * called and does not call {@code onReceivedClientCertRequest()} again for the same host and
+ * port pair. Webview does not store the response if {@link ClientCertRequest#ignore}
+ * is called. Note that, multiple layers in chromium network stack might be
+ * caching the responses, so the behavior for ignore is only a best case
+ * effort.
+ *
+ * This method is called on the UI thread. During the callback, the
+ * connection is suspended.
+ *
+ * For most use cases, the application program should implement the
+ * {@link android.security.KeyChainAliasCallback} interface and pass it to
+ * {@link android.security.KeyChain#choosePrivateKeyAlias} to start an
+ * activity for the user to choose the proper alias. The keychain activity will
+ * provide the alias through the callback method in the implemented interface. Next
+ * the application should create an async task to call
+ * {@link android.security.KeyChain#getPrivateKey} to receive the key.
+ *
+ * An example implementation of client certificates can be seen at
+ *
+ * AOSP Browser
+ *
+ * The default behavior is to cancel, returning no client certificate.
+ *
+ * @param view The WebView that is initiating the callback
+ * @param request An instance of a {@link ClientCertRequest}
+ *
+ */
+ public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
+ request.cancel();
+ }
+
+ /**
+ * Notifies the host application that the WebView received an HTTP
+ * authentication request. The host application can use the supplied
+ * {@link HttpAuthHandler} to set the WebView's response to the request.
+ * The default behavior is to cancel the request.
+ *
+ *
Note: The supplied HttpAuthHandler must be used on
+ * the UI thread.
+ *
+ * @param view the WebView that is initiating the callback
+ * @param handler the HttpAuthHandler used to set the WebView's response
+ * @param host the host requiring authentication
+ * @param realm the realm for which authentication is required
+ * @see WebView#getHttpAuthUsernamePassword
+ */
+ public void onReceivedHttpAuthRequest(WebView view,
+ HttpAuthHandler handler, String host, String realm) {
+ handler.cancel();
+ }
+
+ /**
+ * Give the host application a chance to handle the key event synchronously.
+ * e.g. menu shortcut key events need to be filtered this way. If return
+ * true, WebView will not handle the key event. If return {@code false}, WebView
+ * will always handle the key event, so none of the super in the view chain
+ * will see the key event. The default behavior returns {@code false}.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param event The key event.
+ * @return {@code true} if the host application wants to handle the key event
+ * itself, otherwise return {@code false}
+ */
+ public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
+ return false;
+ }
+
+ /**
+ * Notify the host application that a key was not handled by the WebView.
+ * Except system keys, WebView always consumes the keys in the normal flow
+ * or if {@link #shouldOverrideKeyEvent} returns {@code true}. This is called asynchronously
+ * from where the key is dispatched. It gives the host application a chance
+ * to handle the unhandled key events.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param event The key event.
+ */
+ public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
+ onUnhandledInputEventInternal(view, event);
+ }
+
+ /**
+ * Notify the host application that a input event was not handled by the WebView.
+ * Except system keys, WebView always consumes input events in the normal flow
+ * or if {@link #shouldOverrideKeyEvent} returns {@code true}. This is called asynchronously
+ * from where the event is dispatched. It gives the host application a chance
+ * to handle the unhandled input events.
+ *
+ * Note that if the event is a {@link android.view.MotionEvent}, then it's lifetime is only
+ * that of the function call. If the WebViewClient wishes to use the event beyond that, then it
+ * must create a copy of the event.
+ *
+ * It is the responsibility of overriders of this method to call
+ * {@link #onUnhandledKeyEvent(WebView, KeyEvent)}
+ * when appropriate if they wish to continue receiving events through it.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param event The input event.
+ * @removed
+ */
+ public void onUnhandledInputEvent(WebView view, InputEvent event) {
+ if (event instanceof KeyEvent) {
+ onUnhandledKeyEvent(view, (KeyEvent) event);
+ return;
+ }
+ onUnhandledInputEventInternal(view, event);
+ }
+
+ private void onUnhandledInputEventInternal(WebView view, InputEvent event) {
+ throw new RuntimeException("Stub!");
+ }
+
+ /**
+ * Notify the host application that the scale applied to the WebView has
+ * changed.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param oldScale The old scale factor
+ * @param newScale The new scale factor
+ */
+ public void onScaleChanged(WebView view, float oldScale, float newScale) {
+ }
+
+ /**
+ * Notify the host application that a request to automatically log in the
+ * user has been processed.
+ * @param view The WebView requesting the login.
+ * @param realm The account realm used to look up accounts.
+ * @param account An optional account. If not {@code null}, the account should be
+ * checked against accounts on the device. If it is a valid
+ * account, it should be used to log in the user.
+ * @param args Authenticator specific arguments used to log in the user.
+ */
+ public void onReceivedLoginRequest(WebView view, String realm,
+ @Nullable String account, String args) {
+ }
+
+ /**
+ * Notify host application that the given WebView's render process has exited.
+ *
+ * Multiple WebView instances may be associated with a single render process;
+ * onRenderProcessGone will be called for each WebView that was affected.
+ * The application's implementation of this callback should only attempt to
+ * clean up the specific WebView given as a parameter, and should not assume
+ * that other WebView instances are affected.
+ *
+ * The given WebView can't be used, and should be removed from the view hierarchy,
+ * all references to it should be cleaned up, e.g any references in the Activity
+ * or other classes saved using {@link android.view.View#findViewById} and similar calls, etc.
+ *
+ * To cause an render process crash for test purpose, the application can
+ * call {@code loadUrl("chrome://crash")} on the WebView. Note that multiple WebView
+ * instances may be affected if they share a render process, not just the
+ * specific WebView which loaded chrome://crash.
+ *
+ * @param view The WebView which needs to be cleaned up.
+ * @param detail the reason why it exited.
+ * @return {@code true} if the host application handled the situation that process has
+ * exited, otherwise, application will crash if render process crashed,
+ * or be killed if render process was killed by the system.
+ */
+ public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) {
+ return false;
+ }
+
+ /**
+ * Notify the host application that a loading URL has been flagged by Safe Browsing.
+ *
+ * The application must invoke the callback to indicate the preferred response. The default
+ * behavior is to show an interstitial to the user, with the reporting checkbox visible.
+ *
+ * If the application needs to show its own custom interstitial UI, the callback can be invoked
+ * asynchronously with {@link SafeBrowsingResponse#backToSafety} or {@link
+ * SafeBrowsingResponse#proceed}, depending on user response.
+ *
+ * @param view The WebView that hit the malicious resource.
+ * @param request Object containing the details of the request.
+ * @param threatType The reason the resource was caught by Safe Browsing, corresponding to a
+ * {@code SAFE_BROWSING_THREAT_*} value.
+ * @param callback Applications must invoke one of the callback methods.
+ */
+ public void onSafeBrowsingHit(WebView view, WebResourceRequest request,
+ @SafeBrowsingThreat int threatType, SafeBrowsingResponse callback) {
+ callback.showInterstitial(/* allowReporting */ true);
+ }
+}
diff --git a/AndroidCompat/src/main/java/android/webkit/WebViewProvider.java b/AndroidCompat/src/main/java/android/webkit/WebViewProvider.java
new file mode 100644
index 00000000..7ef66e2c
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/webkit/WebViewProvider.java
@@ -0,0 +1,541 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Picture;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.net.http.SslCertificate;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.print.PrintDocumentAdapter;
+import android.util.LongSparseArray;
+import android.util.SparseArray;
+import android.view.DragEvent;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.PointerIcon;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.view.WindowInsets;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeProvider;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.textclassifier.TextClassifier;
+import android.webkit.WebView.HitTestResult;
+import android.webkit.WebView.PictureListener;
+import android.webkit.WebView.VisualStateCallback;
+
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * WebView backend provider interface: this interface is the abstract backend to a WebView
+ * instance; each WebView object is bound to exactly one WebViewProvider object which implements
+ * the runtime behavior of that WebView.
+ *
+ * All methods must behave as per their namesake in {@link WebView}, unless otherwise noted.
+ *
+ * @hide Not part of the public API; only required by system implementors.
+ */
+@SystemApi
+public interface WebViewProvider {
+ //-------------------------------------------------------------------------
+ // Main interface for backend provider of the WebView class.
+ //-------------------------------------------------------------------------
+ /**
+ * Initialize this WebViewProvider instance. Called after the WebView has fully constructed.
+ * @param javaScriptInterfaces is a Map of interface names, as keys, and
+ * object implementing those interfaces, as values.
+ * @param privateBrowsing If {@code true} the web view will be initialized in private /
+ * incognito mode.
+ */
+ public void init(Map javaScriptInterfaces,
+ boolean privateBrowsing);
+
+ // Deprecated - should never be called
+ public void setHorizontalScrollbarOverlay(boolean overlay);
+
+ // Deprecated - should never be called
+ public void setVerticalScrollbarOverlay(boolean overlay);
+
+ // Deprecated - should never be called
+ public boolean overlayHorizontalScrollbar();
+
+ // Deprecated - should never be called
+ public boolean overlayVerticalScrollbar();
+
+ public int getVisibleTitleHeight();
+
+ public SslCertificate getCertificate();
+
+ public void setCertificate(SslCertificate certificate);
+
+ public void savePassword(String host, String username, String password);
+
+ public void setHttpAuthUsernamePassword(String host, String realm,
+ String username, String password);
+
+ public String[] getHttpAuthUsernamePassword(String host, String realm);
+
+ /**
+ * See {@link WebView#destroy()}.
+ * As well as releasing the internal state and resources held by the implementation,
+ * the provider should null all references it holds on the WebView proxy class, and ensure
+ * no further method calls are made to it.
+ */
+ public void destroy();
+
+ public void setNetworkAvailable(boolean networkUp);
+
+ public WebBackForwardList saveState(Bundle outState);
+
+ public boolean savePicture(Bundle b, final File dest);
+
+ public boolean restorePicture(Bundle b, File src);
+
+ public WebBackForwardList restoreState(Bundle inState);
+
+ public void loadUrl(String url, Map additionalHttpHeaders);
+
+ public void loadUrl(String url);
+
+ public void postUrl(String url, byte[] postData);
+
+ public void loadData(String data, String mimeType, String encoding);
+
+ public void loadDataWithBaseURL(String baseUrl, String data,
+ String mimeType, String encoding, String historyUrl);
+
+ public void evaluateJavaScript(String script, ValueCallback resultCallback);
+
+ public void saveWebArchive(String filename);
+
+ public void saveWebArchive(String basename, boolean autoname, ValueCallback callback);
+
+ public void stopLoading();
+
+ public void reload();
+
+ public boolean canGoBack();
+
+ public void goBack();
+
+ public boolean canGoForward();
+
+ public void goForward();
+
+ public boolean canGoBackOrForward(int steps);
+
+ public void goBackOrForward(int steps);
+
+ public boolean isPrivateBrowsingEnabled();
+
+ public boolean pageUp(boolean top);
+
+ public boolean pageDown(boolean bottom);
+
+ public void insertVisualStateCallback(long requestId, VisualStateCallback callback);
+
+ public void clearView();
+
+ public Picture capturePicture();
+
+ public PrintDocumentAdapter createPrintDocumentAdapter(String documentName);
+
+ public float getScale();
+
+ public void setInitialScale(int scaleInPercent);
+
+ public void invokeZoomPicker();
+
+ public HitTestResult getHitTestResult();
+
+ public void requestFocusNodeHref(Message hrefMsg);
+
+ public void requestImageRef(Message msg);
+
+ public String getUrl();
+
+ public String getOriginalUrl();
+
+ public String getTitle();
+
+ public Bitmap getFavicon();
+
+ public String getTouchIconUrl();
+
+ public int getProgress();
+
+ public int getContentHeight();
+
+ public int getContentWidth();
+
+ public void pauseTimers();
+
+ public void resumeTimers();
+
+ public void onPause();
+
+ public void onResume();
+
+ public boolean isPaused();
+
+ public void freeMemory();
+
+ public void clearCache(boolean includeDiskFiles);
+
+ public void clearFormData();
+
+ public void clearHistory();
+
+ public void clearSslPreferences();
+
+ public WebBackForwardList copyBackForwardList();
+
+ public void setFindListener(WebView.FindListener listener);
+
+ public void findNext(boolean forward);
+
+ public int findAll(String find);
+
+ public void findAllAsync(String find);
+
+ public boolean showFindDialog(String text, boolean showIme);
+
+ public void clearMatches();
+
+ public void documentHasImages(Message response);
+
+ public void setWebViewClient(WebViewClient client);
+
+ public WebViewClient getWebViewClient();
+
+ @Nullable
+ public WebViewRenderProcess getWebViewRenderProcess();
+
+ public void setWebViewRenderProcessClient(
+ @Nullable Executor executor,
+ @Nullable WebViewRenderProcessClient client);
+
+ @Nullable
+ public WebViewRenderProcessClient getWebViewRenderProcessClient();
+
+ public void setDownloadListener(DownloadListener listener);
+
+ public void setWebChromeClient(WebChromeClient client);
+
+ public WebChromeClient getWebChromeClient();
+
+ public void setPictureListener(PictureListener listener);
+
+ public void addJavascriptInterface(Object obj, String interfaceName);
+
+ public void removeJavascriptInterface(String interfaceName);
+
+ public WebMessagePort[] createWebMessageChannel();
+
+ public void postMessageToMainFrame(WebMessage message, Uri targetOrigin);
+
+ public WebSettings getSettings();
+
+ public void setMapTrackballToArrowKeys(boolean setMap);
+
+ public void flingScroll(int vx, int vy);
+
+ public View getZoomControls();
+
+ public boolean canZoomIn();
+
+ public boolean canZoomOut();
+
+ public boolean zoomBy(float zoomFactor);
+
+ public boolean zoomIn();
+
+ public boolean zoomOut();
+
+ public void dumpViewHierarchyWithProperties(BufferedWriter out, int level);
+
+ public View findHierarchyView(String className, int hashCode);
+
+ public void setRendererPriorityPolicy(int rendererRequestedPriority, boolean waivedWhenNotVisible);
+
+ public int getRendererRequestedPriority();
+
+ public boolean getRendererPriorityWaivedWhenNotVisible();
+
+ @SuppressWarnings("unused")
+ public default void setTextClassifier(@Nullable TextClassifier textClassifier) {}
+
+ @NonNull
+ public default TextClassifier getTextClassifier() { return TextClassifier.NO_OP; }
+
+ //-------------------------------------------------------------------------
+ // Provider internal methods
+ //-------------------------------------------------------------------------
+
+ /**
+ * @return the ViewDelegate implementation. This provides the functionality to back all of
+ * the name-sake functions from the View and ViewGroup base classes of WebView.
+ */
+ /* package */ ViewDelegate getViewDelegate();
+
+ /**
+ * @return a ScrollDelegate implementation. Normally this would be same object as is
+ * returned by getViewDelegate().
+ */
+ /* package */ ScrollDelegate getScrollDelegate();
+
+ /**
+ * Only used by FindActionModeCallback to inform providers that the find dialog has
+ * been dismissed.
+ */
+ public void notifyFindDialogDismissed();
+
+ //-------------------------------------------------------------------------
+ // View / ViewGroup delegation methods
+ //-------------------------------------------------------------------------
+
+ /**
+ * Provides mechanism for the name-sake methods declared in View and ViewGroup to be delegated
+ * into the WebViewProvider instance.
+ * NOTE: For many of these methods, the WebView will provide a super.Foo() call before or after
+ * making the call into the provider instance. This is done for convenience in the common case
+ * of maintaining backward compatibility. For remaining super class calls (e.g. where the
+ * provider may need to only conditionally make the call based on some internal state) see the
+ * {@link WebView.PrivateAccess} callback class.
+ */
+ // TODO: See if the pattern of the super-class calls can be rationalized at all, and document
+ // the remainder on the methods below.
+ interface ViewDelegate {
+ public boolean shouldDelayChildPressedState();
+
+ public void onProvideVirtualStructure(android.view.ViewStructure structure);
+
+ default void onProvideAutofillVirtualStructure(
+ @SuppressWarnings("unused") android.view.ViewStructure structure,
+ @SuppressWarnings("unused") int flags) {
+ }
+
+ default void autofill(@SuppressWarnings("unused") SparseArray values) {
+ }
+
+ default boolean isVisibleToUserForAutofill(@SuppressWarnings("unused") int virtualId) {
+ return true; // true is the default value returned by View.isVisibleToUserForAutofill()
+ }
+
+ default void onProvideContentCaptureStructure(
+ @NonNull @SuppressWarnings("unused") android.view.ViewStructure structure,
+ @SuppressWarnings("unused") int flags) {
+ }
+
+ // @SuppressLint("NullableCollection")
+ // default void onCreateVirtualViewTranslationRequests(
+ // @NonNull @SuppressWarnings("unused") long[] virtualIds,
+ // @NonNull @SuppressWarnings("unused") @DataFormat int[] supportedFormats,
+ // @NonNull @SuppressWarnings("unused")
+ // Consumer requestsCollector) {
+ // }
+
+ // default void onVirtualViewTranslationResponses(
+ // @NonNull @SuppressWarnings("unused")
+ // LongSparseArray response) {
+ // }
+
+ // default void dispatchCreateViewTranslationRequest(
+ // @NonNull @SuppressWarnings("unused") Map viewIds,
+ // @NonNull @SuppressWarnings("unused") @DataFormat int[] supportedFormats,
+ // @Nullable @SuppressWarnings("unused") TranslationCapability capability,
+ // @NonNull @SuppressWarnings("unused") List requests) {
+
+ // }
+
+ public AccessibilityNodeProvider getAccessibilityNodeProvider();
+
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info);
+
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event);
+
+ public boolean performAccessibilityAction(int action, Bundle arguments);
+
+ public void setOverScrollMode(int mode);
+
+ public void setScrollBarStyle(int style);
+
+ public void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t,
+ int r, int b);
+
+ public void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY);
+
+ public void onWindowVisibilityChanged(int visibility);
+
+ public void onDraw(Canvas canvas);
+
+ public void setLayoutParams(LayoutParams layoutParams);
+
+ public boolean performLongClick();
+
+ public void onConfigurationChanged(Configuration newConfig);
+
+ public InputConnection onCreateInputConnection(EditorInfo outAttrs);
+
+ public boolean onDragEvent(DragEvent event);
+
+ public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event);
+
+ public boolean onKeyDown(int keyCode, KeyEvent event);
+
+ public boolean onKeyUp(int keyCode, KeyEvent event);
+
+ public void onAttachedToWindow();
+
+ public void onDetachedFromWindow();
+
+ public default void onMovedToDisplay(int displayId, Configuration config) {}
+
+ public void onVisibilityChanged(View changedView, int visibility);
+
+ public void onWindowFocusChanged(boolean hasWindowFocus);
+
+ public void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect);
+
+ public boolean setFrame(int left, int top, int right, int bottom);
+
+ public void onSizeChanged(int w, int h, int ow, int oh);
+
+ public void onScrollChanged(int l, int t, int oldl, int oldt);
+
+ public boolean dispatchKeyEvent(KeyEvent event);
+
+ public boolean onTouchEvent(MotionEvent ev);
+
+ public boolean onHoverEvent(MotionEvent event);
+
+ public boolean onGenericMotionEvent(MotionEvent event);
+
+ public boolean onTrackballEvent(MotionEvent ev);
+
+ public boolean requestFocus(int direction, Rect previouslyFocusedRect);
+
+ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec);
+
+ public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate);
+
+ public void setBackgroundColor(int color);
+
+ public void setLayerType(int layerType, Paint paint);
+
+ public void preDispatchDraw(Canvas canvas);
+
+ public void onStartTemporaryDetach();
+
+ public void onFinishTemporaryDetach();
+
+ public void onActivityResult(int requestCode, int resultCode, Intent data);
+
+ public Handler getHandler(Handler originalHandler);
+
+ public View findFocus(View originalFocusedView);
+
+ @SuppressWarnings("unused")
+ default boolean onCheckIsTextEditor() {
+ return false;
+ }
+
+ /**
+ * @see View#onApplyWindowInsets(WindowInsets).
+ *
+ * This is the entry point for the WebView implementation to override. It returns
+ * {@code null} when the WebView implementation hasn't implemented the WindowInsets support
+ * on S yet. In this case, the {@link View#onApplyWindowInsets()} super method will be
+ * called instead.
+ *
+ * @param insets Insets to apply
+ * @return The supplied insets with any applied insets consumed.
+ */
+ @SuppressWarnings("unused")
+ @Nullable
+ default WindowInsets onApplyWindowInsets(@Nullable WindowInsets insets) {
+ return null;
+ }
+
+ /**
+ * @hide Only used by WebView.
+ */
+ @SuppressWarnings("unused")
+ @Nullable
+ default PointerIcon onResolvePointerIcon(@NonNull MotionEvent event, int pointerIndex) {
+ return null;
+ }
+ }
+
+ interface ScrollDelegate {
+ // These methods are declared protected in the ViewGroup base class. This interface
+ // exists to promote them to public so they may be called by the WebView proxy class.
+ // TODO: Combine into ViewDelegate?
+ /**
+ * See {@link android.webkit.WebView#computeHorizontalScrollRange}
+ */
+ public int computeHorizontalScrollRange();
+
+ /**
+ * See {@link android.webkit.WebView#computeHorizontalScrollOffset}
+ */
+ public int computeHorizontalScrollOffset();
+
+ /**
+ * See {@link android.webkit.WebView#computeVerticalScrollRange}
+ */
+ public int computeVerticalScrollRange();
+
+ /**
+ * See {@link android.webkit.WebView#computeVerticalScrollOffset}
+ */
+ public int computeVerticalScrollOffset();
+
+ /**
+ * See {@link android.webkit.WebView#computeVerticalScrollExtent}
+ */
+ public int computeVerticalScrollExtent();
+
+ /**
+ * See {@link android.webkit.WebView#computeScroll}
+ */
+ public void computeScroll();
+ }
+}
diff --git a/AndroidCompat/src/main/java/android/widget/AbsoluteLayout.java b/AndroidCompat/src/main/java/android/widget/AbsoluteLayout.java
new file mode 100644
index 00000000..f4b8ef65
--- /dev/null
+++ b/AndroidCompat/src/main/java/android/widget/AbsoluteLayout.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RemoteViews.RemoteView;
+
+
+@Deprecated
+@RemoteView
+public class AbsoluteLayout extends ViewGroup {
+ public AbsoluteLayout(Context context) {
+ this(context, null);
+ }
+
+ public AbsoluteLayout(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AbsoluteLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public AbsoluteLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
+ return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0, 0);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t,
+ int r, int b) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @Override
+ public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return new AbsoluteLayout.LayoutParams(getContext(), attrs);
+ }
+
+ // Override to allow type-checking of LayoutParams.
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ return p instanceof AbsoluteLayout.LayoutParams;
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+ return new LayoutParams(p);
+ }
+
+ @Override
+ public boolean shouldDelayChildPressedState() {
+ return false;
+ }
+
+ public static class LayoutParams extends ViewGroup.LayoutParams {
+ public int x;
+ public int y;
+
+ public LayoutParams(int width, int height, int x, int y) {
+ super(width, height);
+ this.x = x;
+ this.y = y;
+ }
+
+ public LayoutParams(Context c, AttributeSet attrs) {
+ super(c, attrs);
+ throw new RuntimeException("Stub!");
+ }
+
+ public LayoutParams(ViewGroup.LayoutParams source) {
+ super(source);
+ }
+
+ public String debug(String output) {
+ return output + "Absolute.LayoutParams={width="
+ + String.valueOf(width) + ", height=" + String.valueOf(height)
+ + " x=" + x + " y=" + y + "}";
+ }
+ }
+}
diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/AndroidCompatInitializer.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/AndroidCompatInitializer.kt
index 3d1e446d..f6b1d1b2 100644
--- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/AndroidCompatInitializer.kt
+++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/AndroidCompatInitializer.kt
@@ -1,8 +1,10 @@
package xyz.nulldev.androidcompat
+import android.webkit.WebView
import xyz.nulldev.androidcompat.config.ApplicationInfoConfigModule
import xyz.nulldev.androidcompat.config.FilesConfigModule
import xyz.nulldev.androidcompat.config.SystemConfigModule
+import xyz.nulldev.androidcompat.webkit.KcefWebViewProvider
import xyz.nulldev.ts.config.GlobalConfigManager
/**
@@ -17,6 +19,8 @@ class AndroidCompatInitializer {
SystemConfigModule.register(GlobalConfigManager.config),
)
+ WebView.setProviderFactory({ view: WebView -> KcefWebViewProvider(view) })
+
// Set some properties extensions use
System.setProperty(
"http.agent",
diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/CallableArgument.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/CallableArgument.kt
new file mode 100644
index 00000000..57eb1da8
--- /dev/null
+++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/CallableArgument.kt
@@ -0,0 +1,5 @@
+package xyz.nulldev.androidcompat
+
+fun interface CallableArgument {
+ fun call(arg: A): R
+}
diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/webkit/KcefWebSettings.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/webkit/KcefWebSettings.kt
new file mode 100644
index 00000000..4f0f88eb
--- /dev/null
+++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/webkit/KcefWebSettings.kt
@@ -0,0 +1,429 @@
+package xyz.nulldev.androidcompat.webkit
+
+import android.webkit.WebSettings
+
+class KcefWebSettings : WebSettings() {
+ // Boolean settings
+ private var navDumps = false
+ private var mediaPlaybackRequiresUserGesture = true
+ private var builtInZoomControls = false
+ private var displayZoomControls = true
+ private var allowFileAccess = true
+ private var allowContentAccess = true
+ private var pluginsEnabled = false
+ private var loadWithOverviewMode = false
+ private var enableSmoothTransition = false
+ private var useWebViewBackgroundForOverscrollBackground = false
+ private var saveFormData = true
+ private var savePassword = false
+ private var acceptThirdPartyCookies = true
+ private var lightTouchEnabled = false
+ private var useWideViewPort = true
+ private var supportMultipleWindows = false
+ private var loadsImagesAutomatically = true
+ private var blockNetworkImage = false
+ private var blockNetworkLoads = false
+ private var javaScriptEnabled = true
+ private var allowUniversalAccessFromFileURLs = false
+ private var allowFileAccessFromFileURLs = false
+ private var domStorageEnabled = true
+ private var geolocationEnabled = true
+ private var javaScriptCanOpenWindowsAutomatically = false
+ private var needInitialFocus = false
+ private var offscreenPreRaster = false
+ private var videoOverlayForEmbeddedEncryptedVideoEnabled = false
+ private var safeBrowsingEnabled = true
+
+ // Integer settings
+ private var textZoom = 100
+ private var minimumFontSize = 8
+ private var minimumLogicalFontSize = 8
+ private var defaultFontSize = 16
+ private var defaultFixedFontSize = 13
+ private var cacheMode = 0
+ private var mixedContentMode = 0
+ private var disabledActionModeMenuItems = 0
+
+ // String settings
+ private var databasePath: String? = null
+ private var geolocationDatabasePath: String? = null
+ private var appCachePath: String? = null
+ private var defaultTextEncodingName: String? = null
+ private var userAgentString: String? = null
+ private var standardFontFamily: String? = null
+ private var fixedFontFamily: String? = null
+ private var sansSerifFontFamily: String? = null
+ private var serifFontFamily: String? = null
+ private var cursiveFontFamily: String? = null
+ private var fantasyFontFamily: String? = null
+
+ // Enum settings
+ private var defaultZoom: ZoomDensity? = null
+ private var layoutAlgorithm: LayoutAlgorithm? = null
+ private var pluginState: PluginState? = null
+ private var renderPriority: RenderPriority? = null
+
+ // Long settings
+ private var appCacheMaxSize: Long = 0L
+
+ // Implementations
+
+ @SuppressWarnings("HiddenAbstractMethod")
+ @Deprecated("inherit")
+ override fun setNavDump(p0: Boolean) {
+ navDumps = p0
+ }
+
+ @Deprecated("inherit")
+ @SuppressWarnings("HiddenAbstractMethod")
+ override fun getNavDump(): Boolean = navDumps
+
+ override fun setSupportZoom(p0: Boolean) {
+ mediaPlaybackRequiresUserGesture = p0
+ }
+
+ override fun supportZoom() = mediaPlaybackRequiresUserGesture
+
+ override fun setMediaPlaybackRequiresUserGesture(p0: Boolean) {
+ mediaPlaybackRequiresUserGesture = p0
+ }
+
+ override fun getMediaPlaybackRequiresUserGesture() = mediaPlaybackRequiresUserGesture
+
+ override fun setBuiltInZoomControls(p0: Boolean) {
+ builtInZoomControls = p0
+ }
+
+ override fun getBuiltInZoomControls() = builtInZoomControls
+
+ override fun setDisplayZoomControls(p0: Boolean) {
+ displayZoomControls = p0
+ }
+
+ override fun getDisplayZoomControls() = displayZoomControls
+
+ override fun setAllowFileAccess(p0: Boolean) {
+ allowFileAccess = p0
+ }
+
+ override fun getAllowFileAccess() = allowFileAccess
+
+ override fun setAllowContentAccess(p0: Boolean) {
+ allowContentAccess = p0
+ }
+
+ override fun getAllowContentAccess() = allowContentAccess
+
+ override fun setLoadWithOverviewMode(p0: Boolean) {
+ loadWithOverviewMode = p0
+ }
+
+ override fun getLoadWithOverviewMode() = loadWithOverviewMode
+
+ @Deprecated("inherit")
+ override fun setPluginsEnabled(p0: Boolean) {
+ pluginsEnabled = p0
+ }
+
+ @Deprecated("inherit")
+ override fun getPluginsEnabled() = pluginsEnabled
+
+ @Deprecated("inherit")
+ override fun setEnableSmoothTransition(p0: Boolean) {
+ enableSmoothTransition = p0
+ }
+
+ @Deprecated("inherit")
+ override fun enableSmoothTransition() = enableSmoothTransition
+
+ @Deprecated("inherit")
+ override fun setUseWebViewBackgroundForOverscrollBackground(p0: Boolean) {
+ useWebViewBackgroundForOverscrollBackground = p0
+ }
+
+ @Deprecated("inherit")
+ override fun getUseWebViewBackgroundForOverscrollBackground() = useWebViewBackgroundForOverscrollBackground
+
+ @Deprecated("inherit")
+ override fun setSaveFormData(p0: Boolean) {
+ saveFormData = p0
+ }
+
+ @Deprecated("inherit")
+ override fun getSaveFormData() = saveFormData
+
+ @Deprecated("inherit")
+ override fun setSavePassword(p0: Boolean) {
+ savePassword = p0
+ }
+
+ @Deprecated("inherit")
+ override fun getSavePassword() = savePassword
+
+ override fun setTextZoom(p0: Int) {
+ textZoom = p0
+ }
+
+ override fun getTextZoom() = textZoom
+
+ @Deprecated("inherit")
+ override fun setDefaultZoom(p0: ZoomDensity?) {
+ defaultZoom = p0
+ }
+
+ override fun setAcceptThirdPartyCookies(p0: Boolean) {
+ acceptThirdPartyCookies = p0
+ }
+
+ override fun getAcceptThirdPartyCookies() = acceptThirdPartyCookies
+
+ @Deprecated("inherit")
+ override fun getDefaultZoom() = defaultZoom
+
+ @Deprecated("inherit")
+ override fun setLightTouchEnabled(p0: Boolean) {
+ lightTouchEnabled = p0
+ }
+
+ @Deprecated("inherit")
+ override fun getLightTouchEnabled() = lightTouchEnabled
+
+ @Deprecated("inherit")
+ override fun setUserAgent(ua: Int) = throw RuntimeException("Stub!")
+
+ @Deprecated("inherit")
+ override fun getUserAgent(): Int = throw RuntimeException("Stub!")
+
+ override fun setUseWideViewPort(p0: Boolean) {
+ useWideViewPort = p0
+ }
+
+ override fun getUseWideViewPort() = useWideViewPort
+
+ override fun setSupportMultipleWindows(p0: Boolean) {
+ supportMultipleWindows = p0
+ }
+
+ override fun supportMultipleWindows() = supportMultipleWindows
+
+ override fun setLayoutAlgorithm(p0: LayoutAlgorithm?) {
+ layoutAlgorithm = p0
+ }
+
+ override fun getLayoutAlgorithm() = layoutAlgorithm
+
+ override fun setStandardFontFamily(p0: String?) {
+ standardFontFamily = p0
+ }
+
+ override fun getStandardFontFamily() = standardFontFamily
+
+ override fun setFixedFontFamily(p0: String?) {
+ fixedFontFamily = p0
+ }
+
+ override fun getFixedFontFamily() = fixedFontFamily
+
+ override fun setSansSerifFontFamily(p0: String?) {
+ sansSerifFontFamily = p0
+ }
+
+ override fun getSansSerifFontFamily() = sansSerifFontFamily
+
+ override fun setSerifFontFamily(p0: String?) {
+ serifFontFamily = p0
+ }
+
+ override fun getSerifFontFamily() = serifFontFamily
+
+ override fun setCursiveFontFamily(p0: String?) {
+ cursiveFontFamily = p0
+ }
+
+ override fun getCursiveFontFamily() = cursiveFontFamily
+
+ override fun setFantasyFontFamily(p0: String?) {
+ fantasyFontFamily = p0
+ }
+
+ override fun getFantasyFontFamily() = fantasyFontFamily
+
+ override fun setMinimumFontSize(p0: Int) {
+ minimumFontSize = p0
+ }
+
+ override fun getMinimumFontSize() = minimumFontSize
+
+ override fun setMinimumLogicalFontSize(p0: Int) {
+ minimumLogicalFontSize = p0
+ }
+
+ override fun getMinimumLogicalFontSize() = minimumLogicalFontSize
+
+ override fun setDefaultFontSize(p0: Int) {
+ defaultFontSize = p0
+ }
+
+ override fun getDefaultFontSize() = defaultFontSize
+
+ override fun setDefaultFixedFontSize(p0: Int) {
+ defaultFixedFontSize = p0
+ }
+
+ override fun getDefaultFixedFontSize() = defaultFixedFontSize
+
+ override fun setLoadsImagesAutomatically(p0: Boolean) {
+ loadsImagesAutomatically = p0
+ }
+
+ override fun getLoadsImagesAutomatically() = loadsImagesAutomatically
+
+ override fun setBlockNetworkImage(p0: Boolean) {
+ blockNetworkImage = p0
+ }
+
+ override fun getBlockNetworkImage() = blockNetworkImage
+
+ override fun setBlockNetworkLoads(p0: Boolean) {
+ blockNetworkLoads = p0
+ }
+
+ override fun getBlockNetworkLoads() = blockNetworkLoads
+
+ override fun setJavaScriptEnabled(p0: Boolean) {
+ javaScriptEnabled = p0
+ }
+
+ override fun getJavaScriptEnabled() = javaScriptEnabled
+
+ @Deprecated("inherit")
+ override fun setAllowUniversalAccessFromFileURLs(p0: Boolean) {
+ allowUniversalAccessFromFileURLs = p0
+ }
+
+ override fun getAllowUniversalAccessFromFileURLs() = allowUniversalAccessFromFileURLs
+
+ @Deprecated("inherit")
+ override fun setAllowFileAccessFromFileURLs(p0: Boolean) {
+ allowFileAccessFromFileURLs = p0
+ }
+
+ override fun getAllowFileAccessFromFileURLs() = allowFileAccessFromFileURLs
+
+ @Deprecated("inherit")
+ override fun setPluginState(p0: PluginState?) {
+ pluginState = p0
+ }
+
+ @Deprecated("inherit")
+ override fun getPluginState() = pluginState
+
+ @Deprecated("inherit")
+ override fun setDatabasePath(p0: String?) {
+ databasePath = p0
+ }
+
+ @Deprecated("inherit")
+ override fun getDatabasePath() = databasePath ?: ""
+
+ @Deprecated("inherit")
+ override fun setGeolocationDatabasePath(p0: String?) {
+ geolocationDatabasePath = p0
+ }
+
+ @Deprecated("inherit")
+ override fun setAppCacheEnabled(p0: Boolean) {}
+
+ @Deprecated("inherit")
+ override fun setAppCachePath(p0: String?) {
+ appCachePath = p0
+ }
+
+ @Deprecated("inherit")
+ override fun setAppCacheMaxSize(p0: Long) {
+ appCacheMaxSize = p0
+ }
+
+ @Deprecated("inherit")
+ override fun setDatabaseEnabled(p0: Boolean) {}
+
+ @Deprecated("inherit")
+ override fun getDatabaseEnabled() = true
+
+ override fun setDomStorageEnabled(p0: Boolean) {
+ domStorageEnabled = p0
+ }
+
+ override fun getDomStorageEnabled() = domStorageEnabled
+
+ override fun setGeolocationEnabled(p0: Boolean) {
+ geolocationEnabled = p0
+ }
+
+ override fun setJavaScriptCanOpenWindowsAutomatically(p0: Boolean) {
+ javaScriptCanOpenWindowsAutomatically = p0
+ }
+
+ override fun getJavaScriptCanOpenWindowsAutomatically() = javaScriptCanOpenWindowsAutomatically
+
+ override fun setDefaultTextEncodingName(p0: String?) {
+ defaultTextEncodingName = p0
+ }
+
+ override fun getDefaultTextEncodingName() = defaultTextEncodingName ?: ""
+
+ override fun setUserAgentString(p0: String?) {
+ userAgentString = p0
+ }
+
+ override fun getUserAgentString() = userAgentString ?: defaultUserAgent()
+
+ override fun setNeedInitialFocus(p0: Boolean) {
+ needInitialFocus = p0
+ }
+
+ @Deprecated("inherit")
+ override fun setRenderPriority(p0: RenderPriority?) {
+ renderPriority = p0
+ }
+
+ override fun setCacheMode(p0: Int) {
+ cacheMode = p0
+ }
+
+ override fun getCacheMode() = cacheMode
+
+ override fun setMixedContentMode(p0: Int) {
+ mixedContentMode = p0
+ }
+
+ override fun getMixedContentMode() = mixedContentMode
+
+ override fun setOffscreenPreRaster(p0: Boolean) {
+ offscreenPreRaster = p0
+ }
+
+ override fun getOffscreenPreRaster() = offscreenPreRaster
+
+ override fun setVideoOverlayForEmbeddedEncryptedVideoEnabled(p0: Boolean) {
+ videoOverlayForEmbeddedEncryptedVideoEnabled = p0
+ }
+
+ override fun getVideoOverlayForEmbeddedEncryptedVideoEnabled() = videoOverlayForEmbeddedEncryptedVideoEnabled
+
+ override fun setSafeBrowsingEnabled(p0: Boolean) {
+ safeBrowsingEnabled = p0
+ }
+
+ override fun getSafeBrowsingEnabled() = safeBrowsingEnabled
+
+ override fun setDisabledActionModeMenuItems(p0: Int) {
+ disabledActionModeMenuItems = p0
+ }
+
+ override fun getDisabledActionModeMenuItems() = disabledActionModeMenuItems
+
+ companion object {
+ fun defaultUserAgent() = System.getProperty("http.agent")
+ }
+}
diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/webkit/KcefWebViewProvider.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/webkit/KcefWebViewProvider.kt
new file mode 100644
index 00000000..8e3ccb95
--- /dev/null
+++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/webkit/KcefWebViewProvider.kt
@@ -0,0 +1,1049 @@
+package xyz.nulldev.androidcompat.webkit
+
+import android.content.Intent
+import android.content.res.Configuration
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.graphics.Picture
+import android.graphics.Rect
+import android.graphics.drawable.Drawable
+import android.net.Uri
+import android.net.http.SslCertificate
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.print.PrintDocumentAdapter
+import android.util.Log
+import android.util.SparseArray
+import android.view.DragEvent
+import android.view.KeyEvent
+import android.view.MotionEvent
+import android.view.PointerIcon
+import android.view.View
+import android.view.ViewGroup.LayoutParams
+import android.view.WindowInsets
+import android.view.accessibility.AccessibilityEvent
+import android.view.accessibility.AccessibilityNodeInfo
+import android.view.accessibility.AccessibilityNodeProvider
+import android.view.autofill.AutofillValue
+import android.view.inputmethod.EditorInfo
+import android.view.inputmethod.InputConnection
+import android.view.textclassifier.TextClassifier
+import android.webkit.DownloadListener
+import android.webkit.RenderProcessGoneDetail
+import android.webkit.ValueCallback
+import android.webkit.WebBackForwardList
+import android.webkit.WebChromeClient
+import android.webkit.WebMessage
+import android.webkit.WebMessagePort
+import android.webkit.WebResourceRequest
+import android.webkit.WebResourceResponse
+import android.webkit.WebSettings
+import android.webkit.WebView
+import android.webkit.WebView.HitTestResult
+import android.webkit.WebView.PictureListener
+import android.webkit.WebView.VisualStateCallback
+import android.webkit.WebViewClient
+import android.webkit.WebViewProvider
+import android.webkit.WebViewProvider.ScrollDelegate
+import android.webkit.WebViewProvider.ViewDelegate
+import android.webkit.WebViewRenderProcess
+import android.webkit.WebViewRenderProcessClient
+import dev.datlag.kcef.KCEF
+import dev.datlag.kcef.KCEFBrowser
+import dev.datlag.kcef.KCEFClient
+import dev.datlag.kcef.KCEFResourceRequestHandler
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.decodeFromString
+import kotlinx.serialization.json.Json
+import org.cef.CefSettings
+import org.cef.browser.CefBrowser
+import org.cef.browser.CefFrame
+import org.cef.browser.CefMessageRouter
+import org.cef.browser.CefRendering
+import org.cef.browser.CefRequestContext
+import org.cef.callback.CefCallback
+import org.cef.callback.CefQueryCallback
+import org.cef.handler.CefDisplayHandlerAdapter
+import org.cef.handler.CefLoadHandler
+import org.cef.handler.CefLoadHandlerAdapter
+import org.cef.handler.CefMessageRouterHandlerAdapter
+import org.cef.handler.CefRequestHandler
+import org.cef.handler.CefRequestHandlerAdapter
+import org.cef.handler.CefResourceHandler
+import org.cef.handler.CefResourceHandlerAdapter
+import org.cef.handler.CefResourceRequestHandler
+import org.cef.handler.CefResourceRequestHandlerAdapter
+import org.cef.misc.BoolRef
+import org.cef.misc.IntRef
+import org.cef.misc.StringRef
+import org.cef.network.CefPostData
+import org.cef.network.CefPostDataElement
+import org.cef.network.CefRequest
+import org.cef.network.CefResponse
+import java.io.BufferedWriter
+import java.io.File
+import java.io.IOException
+import java.util.concurrent.Executor
+import kotlin.collections.Map
+import kotlin.reflect.KFunction
+import kotlin.reflect.full.declaredMemberFunctions
+
+class KcefWebViewProvider(
+ private val view: WebView,
+) : WebViewProvider {
+ private val settings = KcefWebSettings()
+ private var viewClient = WebViewClient()
+ private var chromeClient = WebChromeClient()
+ private val mappings: MutableList = mutableListOf()
+
+ private var kcefClient: KCEFClient? = null
+ private var browser: KCEFBrowser? = null
+
+ private val handler = Handler(view.webViewLooper)
+
+ companion object {
+ const val TAG = "KcefWebViewProvider"
+ const val QUERY_FN = "__\$_suwayomiQuery"
+ const val QUERY_CANCEL_FN = "__\$_suwayomiQueryCancel"
+ }
+
+ private class CefWebResourceRequest(
+ val request: CefRequest?,
+ val frame: CefFrame?,
+ val redirect: Boolean,
+ ) : WebResourceRequest {
+ override fun getUrl(): Uri = Uri.parse(request?.url)
+
+ override fun isForMainFrame(): Boolean = frame?.isMain ?: false
+
+ override fun isRedirect(): Boolean = redirect
+
+ override fun hasGesture(): Boolean = false
+
+ override fun getMethod(): String = request?.method ?: "GET"
+
+ override fun getRequestHeaders(): Map {
+ val headers = mutableMapOf()
+ request?.getHeaderMap(headers)
+ return headers
+ }
+ }
+
+ private inner class DisplayHandler : CefDisplayHandlerAdapter() {
+ override fun onConsoleMessage(
+ browser: CefBrowser,
+ level: CefSettings.LogSeverity,
+ message: String,
+ source: String,
+ line: Int,
+ ): Boolean {
+ Log.v(TAG, "$source:$line[$level]: $message")
+ return true
+ }
+
+ override fun onAddressChange(
+ browser: CefBrowser,
+ frame: CefFrame,
+ url: String,
+ ) {
+ Log.d(TAG, "Navigate to $url")
+ }
+
+ override fun onStatusMessage(
+ browser: CefBrowser,
+ value: String,
+ ) {
+ Log.v(TAG, "Status update: $value")
+ }
+ }
+
+ private inner class LoadHandler : CefLoadHandlerAdapter() {
+ override fun onLoadEnd(
+ browser: CefBrowser,
+ frame: CefFrame,
+ httpStatusCode: Int,
+ ) {
+ val url = frame.url ?: ""
+ Log.v(TAG, "Load end $url")
+ handler.post {
+ if (httpStatusCode == 404) {
+ viewClient.onReceivedError(
+ view,
+ WebViewClient.ERROR_FILE_NOT_FOUND,
+ "Not Found",
+ url,
+ )
+ }
+ if (httpStatusCode == 429) {
+ viewClient.onReceivedError(
+ view,
+ WebViewClient.ERROR_TOO_MANY_REQUESTS,
+ "Too Many Requests",
+ url,
+ )
+ }
+ if (httpStatusCode >= 400) {
+ // TODO: create request and response
+ // viewClient.onReceivedHttpError(_view, ...);
+ }
+ viewClient.onPageFinished(view, url)
+ chromeClient.onProgressChanged(view, 100)
+ }
+ }
+
+ override fun onLoadError(
+ browser: CefBrowser,
+ frame: CefFrame,
+ errorCode: CefLoadHandler.ErrorCode,
+ errorText: String,
+ failedUrl: String,
+ ) {
+ Log.w(TAG, "Load error ($failedUrl) [$errorCode]: $errorText")
+ // TODO: translate correctly
+ handler.post {
+ viewClient.onReceivedError(view, WebViewClient.ERROR_UNKNOWN, errorText, url)
+ }
+ }
+
+ override fun onLoadStart(
+ browser: CefBrowser,
+ frame: CefFrame,
+ transitionType: CefRequest.TransitionType,
+ ) {
+ Log.v(TAG, "Load start, pushing mappings")
+ mappings.forEach {
+ val js =
+ """
+ window.${it.interfaceName} = window.${it.interfaceName} || {}
+ window.${it.interfaceName}.${it.functionName} = function() {
+ return new Promise((resolve, reject) => {
+ window.${QUERY_FN}({
+ request: JSON.stringify({
+ functionName: ${Json.encodeToString(it.functionName)},
+ interfaceName: ${Json.encodeToString(it.interfaceName)},
+ args: Array.from(arguments),
+ }),
+ persistent: false,
+ onSuccess: resolve,
+ onFailure: (_, err) => reject(err),
+ })
+ });
+ }
+ """
+ browser.executeJavaScript(js, "SUWAYOMI ${it.toNice()}", 0)
+ }
+
+ handler.post { viewClient.onPageStarted(view, frame.url, null) }
+ }
+ }
+
+ private inner class MessageRouterHandler : CefMessageRouterHandlerAdapter() {
+ override fun onQuery(
+ browser: CefBrowser,
+ frame: CefFrame,
+ queryId: Long,
+ request: String,
+ persistent: Boolean,
+ callback: CefQueryCallback,
+ ): Boolean {
+ val invoke =
+ try {
+ Json.decodeFromString(request)
+ } catch (e: Exception) {
+ Log.w(TAG, "Invalid request received $e")
+ return false
+ }
+ // TODO: Use a map
+ mappings
+ .find {
+ it.functionName == invoke.functionName &&
+ it.interfaceName == invoke.interfaceName
+ }?.let {
+ handler.post {
+ try {
+ Log.v(TAG, "Received request to invoke ${it.toNice()}")
+ // NOTE: first argument is
+ // implicitly this
+ val retval = it.fn.call(it.obj, *invoke.args)
+ callback.success(retval.toString())
+ } catch (e: Exception) {
+ Log.w(TAG, "JS-invoke on ${it.toNice()} failed: $e")
+ callback.failure(0, e.message)
+ }
+ }
+ return true
+ }
+ return false
+ }
+ }
+
+ private inner class WebResponseResourceHandler(
+ val webResponse: WebResourceResponse,
+ ) : CefResourceHandlerAdapter() {
+ private var resolvedData: ByteArray? = null
+ private var readOffset = 0
+
+ override fun processRequest(
+ request: CefRequest,
+ callback: CefCallback,
+ ): Boolean {
+ Log.v(TAG, "Handling request from client's response for ${request.url}")
+ handler.post {
+ try {
+ resolvedData = webResponse.data.readAllBytes()
+ } catch (e: IOException) {
+ }
+ callback.Continue()
+ }
+ return true
+ }
+
+ override fun getResponseHeaders(
+ response: CefResponse,
+ responseLength: IntRef,
+ redirectUrl: StringRef,
+ ) {
+ webResponse.responseHeaders.forEach { response.setHeaderByName(it.key, it.value, true) }
+ responseLength.set(resolvedData?.size ?: 0)
+ }
+
+ override fun readResponse(
+ dataOut: ByteArray,
+ bytesToRead: Int,
+ bytesRead: IntRef,
+ callback: CefCallback,
+ ): Boolean {
+ val data = resolvedData ?: return false
+ val bytesToTransfer = Math.min(bytesToRead, data.size - readOffset)
+ Log.v(
+ TAG,
+ "readResponse: $readOffset/${data.size}, reading $bytesToRead->$bytesToTransfer",
+ )
+ data.copyInto(dataOut, startIndex = readOffset, endIndex = readOffset + bytesToTransfer)
+ bytesRead.set(bytesToTransfer)
+ readOffset += bytesToTransfer
+ return readOffset < data.size
+ }
+ }
+
+ private inner class ResourceRequestHandler : CefResourceRequestHandlerAdapter() {
+ override fun onBeforeResourceLoad(
+ browser: CefBrowser?,
+ frame: CefFrame?,
+ request: CefRequest,
+ ): Boolean {
+ request.setHeaderByName("user-agent", settings.userAgentString, true)
+
+ // TODO: we should be calling this on the handler, since CEF calls us on its IO thread
+ // thus if a client tried to use WebView#loadUrl as the docs suggest, this fails
+ val cancel =
+ viewClient.shouldOverrideUrlLoading(
+ view,
+ CefWebResourceRequest(request, frame, false),
+ )
+ Log.v(TAG, "Resource ${request?.url}, result is cancel? $cancel")
+
+ handler.post { viewClient.onLoadResource(view, frame?.url) }
+
+ return cancel || settings.blockNetworkLoads
+ }
+
+ override fun getResourceHandler(
+ browser: CefBrowser,
+ frame: CefFrame,
+ request: CefRequest,
+ ): CefResourceHandler? {
+ // TODO: we should be calling this on the handler, since CEF calls us on its IO thread
+ val response =
+ viewClient.shouldInterceptRequest(
+ view,
+ CefWebResourceRequest(request, frame, false),
+ )
+ response ?: return null
+ return WebResponseResourceHandler(response)
+ }
+ }
+
+ private inner class RequestHandler : CefRequestHandlerAdapter() {
+ override fun getResourceRequestHandler(
+ browser: CefBrowser,
+ frame: CefFrame,
+ request: CefRequest,
+ isNavigation: Boolean,
+ isDownload: Boolean,
+ requestInitiator: String,
+ disableDefaultHandling: BoolRef,
+ ): CefResourceRequestHandler? = ResourceRequestHandler()
+
+ override fun onRenderProcessTerminated(
+ browser: CefBrowser,
+ status: CefRequestHandler.TerminationStatus,
+ ) {
+ handler.post {
+ viewClient.onRenderProcessGone(
+ view,
+ object : RenderProcessGoneDetail() {
+ override fun didCrash(): Boolean = status == CefRequestHandler.TerminationStatus.TS_PROCESS_CRASHED
+
+ override fun rendererPriorityAtExit(): Int = -1
+ },
+ )
+ }
+ }
+ }
+
+ override fun init(
+ javaScriptInterfaces: Map?,
+ privateBrowsing: Boolean,
+ ) {
+ destroy()
+ kcefClient =
+ KCEF.newClientBlocking().apply {
+ addDisplayHandler(DisplayHandler())
+ addLoadHandler(LoadHandler())
+ addRequestHandler(RequestHandler())
+
+ val config = CefMessageRouter.CefMessageRouterConfig()
+ config.jsQueryFunction = QUERY_FN
+ config.jsCancelFunction = QUERY_CANCEL_FN
+ addMessageRouter(CefMessageRouter.create(config, MessageRouterHandler()))
+ }
+ }
+
+ // Deprecated - should never be called
+ override fun setHorizontalScrollbarOverlay(overlay: Boolean): Unit = throw RuntimeException("Stub!")
+
+ // Deprecated - should never be called
+ override fun setVerticalScrollbarOverlay(overlay: Boolean): Unit = throw RuntimeException("Stub!")
+
+ // Deprecated - should never be called
+ override fun overlayHorizontalScrollbar(): Boolean = throw RuntimeException("Stub!")
+
+ // Deprecated - should never be called
+ override fun overlayVerticalScrollbar(): Boolean = throw RuntimeException("Stub!")
+
+ override fun getVisibleTitleHeight(): Int = throw RuntimeException("Stub!")
+
+ override fun getCertificate(): SslCertificate = throw RuntimeException("Stub!")
+
+ override fun setCertificate(certificate: SslCertificate): Unit = throw RuntimeException("Stub!")
+
+ override fun savePassword(
+ host: String,
+ username: String,
+ password: String,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun setHttpAuthUsernamePassword(
+ host: String,
+ realm: String,
+ username: String,
+ password: String,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun getHttpAuthUsernamePassword(
+ host: String,
+ realm: String,
+ ): Array = throw RuntimeException("Stub!")
+
+ override fun destroy() {
+ browser?.close(true)
+ browser?.dispose()
+ browser = null
+ kcefClient?.dispose()
+ kcefClient = null
+ }
+
+ override fun setNetworkAvailable(networkUp: Boolean): Unit = throw RuntimeException("Stub!")
+
+ override fun saveState(outState: Bundle): WebBackForwardList = throw RuntimeException("Stub!")
+
+ override fun savePicture(
+ b: Bundle,
+ dest: File,
+ ): Boolean = throw RuntimeException("Stub!")
+
+ override fun restorePicture(
+ b: Bundle,
+ src: File,
+ ): Boolean = throw RuntimeException("Stub!")
+
+ override fun restoreState(inState: Bundle): WebBackForwardList = throw RuntimeException("Stub!")
+
+ override fun loadUrl(
+ loadUrl: String,
+ additionalHttpHeaders: Map,
+ ) {
+ browser?.close(true)
+ browser?.dispose()
+ chromeClient.onProgressChanged(view, 0)
+ browser =
+ kcefClient!!
+ .createBrowser(
+ loadUrl,
+ CefRendering.OFFSCREEN,
+ context = createContext(additionalHttpHeaders),
+ ).apply {
+ // NOTE: Without this, we don't seem to be receiving any events
+ createImmediately()
+ }
+ Log.d(TAG, "Page loaded at URL $loadUrl")
+ }
+
+ override fun loadUrl(url: String) {
+ loadUrl(url, mapOf())
+ }
+
+ override fun postUrl(
+ url: String,
+ postData: ByteArray,
+ ) {
+ browser?.close(true)
+ browser?.dispose()
+ chromeClient.onProgressChanged(view, 0)
+ browser =
+ kcefClient!!
+ .createBrowser(
+ url,
+ CefRendering.OFFSCREEN,
+ context = createContext(postData = postData),
+ ).apply {
+ // NOTE: Without this, we don't seem to be receiving any events
+ createImmediately()
+ }
+ Log.d(TAG, "Page posted at URL $url")
+ }
+
+ override fun loadData(
+ data: String,
+ mimeType: String,
+ encoding: String,
+ ) {
+ loadDataWithBaseURL(null, data, mimeType, encoding, null)
+ }
+
+ override fun loadDataWithBaseURL(
+ baseUrl: String?,
+ data: String,
+ mimeType: String,
+ encoding: String,
+ historyUrl: String?,
+ ) {
+ browser?.close(true)
+ browser?.dispose()
+ chromeClient.onProgressChanged(view, 0)
+ browser =
+ kcefClient!!
+ .createBrowserWithHtml(
+ data,
+ baseUrl ?: KCEFBrowser.BLANK_URI,
+ CefRendering.OFFSCREEN,
+ ).apply {
+ // NOTE: Without this, we don't seem to be receiving any events
+ createImmediately()
+ }
+ Log.d(TAG, "Page loaded from data at base URL $baseUrl")
+ }
+
+ override fun evaluateJavaScript(
+ script: String,
+ resultCallback: ValueCallback,
+ ) {
+ browser!!.evaluateJavaScript(
+ script.removePrefix("javascript:"),
+ {
+ Log.v(TAG, "JS returned: $it")
+ it?.let { resultCallback.onReceiveValue(it) }
+ },
+ )
+ }
+
+ override fun saveWebArchive(filename: String): Unit = throw RuntimeException("Stub!")
+
+ override fun saveWebArchive(
+ basename: String,
+ autoname: Boolean,
+ callback: ValueCallback,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun stopLoading() {
+ browser!!.stopLoad()
+ }
+
+ override fun reload() {
+ browser!!.reload()
+ }
+
+ override fun canGoBack(): Boolean = browser!!.canGoBack()
+
+ override fun goBack() {
+ browser!!.goBack()
+ }
+
+ override fun canGoForward(): Boolean = browser!!.canGoForward()
+
+ override fun goForward() {
+ browser!!.goForward()
+ }
+
+ override fun canGoBackOrForward(steps: Int): Boolean = throw RuntimeException("Stub!")
+
+ override fun goBackOrForward(steps: Int): Unit = throw RuntimeException("Stub!")
+
+ override fun isPrivateBrowsingEnabled(): Boolean = throw RuntimeException("Stub!")
+
+ override fun pageUp(top: Boolean): Boolean = throw RuntimeException("Stub!")
+
+ override fun pageDown(bottom: Boolean): Boolean = throw RuntimeException("Stub!")
+
+ override fun insertVisualStateCallback(
+ requestId: Long,
+ callback: VisualStateCallback,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun clearView(): Unit = throw RuntimeException("Stub!")
+
+ override fun capturePicture(): Picture = throw RuntimeException("Stub!")
+
+ override fun createPrintDocumentAdapter(documentName: String): PrintDocumentAdapter = throw RuntimeException("Stub!")
+
+ override fun getScale(): Float = throw RuntimeException("Stub!")
+
+ override fun setInitialScale(scaleInPercent: Int): Unit = throw RuntimeException("Stub!")
+
+ override fun invokeZoomPicker(): Unit = throw RuntimeException("Stub!")
+
+ override fun getHitTestResult(): HitTestResult = throw RuntimeException("Stub!")
+
+ override fun requestFocusNodeHref(hrefMsg: Message): Unit = throw RuntimeException("Stub!")
+
+ override fun requestImageRef(msg: Message): Unit = throw RuntimeException("Stub!")
+
+ override fun getUrl(): String = browser!!.url
+
+ override fun getOriginalUrl(): String = browser!!.url
+
+ override fun getTitle(): String = throw RuntimeException("Stub!")
+
+ override fun getFavicon(): Bitmap = throw RuntimeException("Stub!")
+
+ override fun getTouchIconUrl(): String = throw RuntimeException("Stub!")
+
+ override fun getProgress(): Int = throw RuntimeException("Stub!")
+
+ override fun getContentHeight(): Int = throw RuntimeException("Stub!")
+
+ override fun getContentWidth(): Int = throw RuntimeException("Stub!")
+
+ override fun pauseTimers(): Unit = throw RuntimeException("Stub!")
+
+ override fun resumeTimers(): Unit = throw RuntimeException("Stub!")
+
+ override fun onPause(): Unit = throw RuntimeException("Stub!")
+
+ override fun onResume(): Unit = throw RuntimeException("Stub!")
+
+ override fun isPaused(): Boolean = throw RuntimeException("Stub!")
+
+ override fun freeMemory(): Unit = throw RuntimeException("Stub!")
+
+ override fun clearCache(includeDiskFiles: Boolean): Unit = throw RuntimeException("Stub!")
+
+ override fun clearFormData(): Unit = throw RuntimeException("Stub!")
+
+ override fun clearHistory(): Unit = throw RuntimeException("Stub!")
+
+ override fun clearSslPreferences(): Unit = throw RuntimeException("Stub!")
+
+ override fun copyBackForwardList(): WebBackForwardList = throw RuntimeException("Stub!")
+
+ override fun setFindListener(listener: WebView.FindListener): Unit = throw RuntimeException("Stub!")
+
+ override fun findNext(forward: Boolean): Unit = throw RuntimeException("Stub!")
+
+ override fun findAll(find: String): Int = throw RuntimeException("Stub!")
+
+ override fun findAllAsync(find: String): Unit = throw RuntimeException("Stub!")
+
+ override fun showFindDialog(
+ text: String,
+ showIme: Boolean,
+ ): Boolean = throw RuntimeException("Stub!")
+
+ override fun clearMatches(): Unit = throw RuntimeException("Stub!")
+
+ override fun documentHasImages(response: Message): Unit = throw RuntimeException("Stub!")
+
+ override fun setWebViewClient(client: WebViewClient) {
+ viewClient = client
+ }
+
+ override fun getWebViewClient(): WebViewClient = viewClient
+
+ override fun getWebViewRenderProcess(): WebViewRenderProcess? = throw RuntimeException("Stub!")
+
+ override fun setWebViewRenderProcessClient(
+ executor: Executor?,
+ client: WebViewRenderProcessClient?,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun getWebViewRenderProcessClient(): WebViewRenderProcessClient? = throw RuntimeException("Stub!")
+
+ override fun setDownloadListener(listener: DownloadListener): Unit = throw RuntimeException("Stub!")
+
+ override fun setWebChromeClient(client: WebChromeClient) {
+ chromeClient = client
+ }
+
+ override fun getWebChromeClient(): WebChromeClient = chromeClient
+
+ override fun setPictureListener(listener: PictureListener): Unit = throw RuntimeException("Stub!")
+
+ @Serializable
+ private data class FunctionCall(
+ val interfaceName: String,
+ val functionName: String,
+ val args: Array,
+ )
+
+ private data class FunctionMapping(
+ val interfaceName: String,
+ val functionName: String,
+ val obj: Any,
+ val fn: KFunction<*>,
+ ) {
+ fun toNice(): String = "$interfaceName.$functionName"
+ }
+
+ override fun addJavascriptInterface(
+ obj: Any,
+ interfaceName: String,
+ ) {
+ val cls = obj::class
+ mappings.addAll(
+ cls.declaredMemberFunctions.map {
+ val map = FunctionMapping(interfaceName, it.name, obj, it)
+ Log.v(TAG, "Exposing: " + map.toNice())
+ map
+ },
+ )
+ }
+
+ override fun removeJavascriptInterface(interfaceName: String): Unit = throw RuntimeException("Stub!")
+
+ override fun createWebMessageChannel(): Array = throw RuntimeException("Stub!")
+
+ override fun postMessageToMainFrame(
+ message: WebMessage,
+ targetOrigin: Uri,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun getSettings(): WebSettings = settings
+
+ override fun setMapTrackballToArrowKeys(setMap: Boolean): Unit = throw RuntimeException("Stub!")
+
+ override fun flingScroll(
+ vx: Int,
+ vy: Int,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun getZoomControls(): View = throw RuntimeException("Stub!")
+
+ override fun canZoomIn(): Boolean = throw RuntimeException("Stub!")
+
+ override fun canZoomOut(): Boolean = throw RuntimeException("Stub!")
+
+ override fun zoomBy(zoomFactor: Float): Boolean = throw RuntimeException("Stub!")
+
+ override fun zoomIn(): Boolean = throw RuntimeException("Stub!")
+
+ override fun zoomOut(): Boolean = throw RuntimeException("Stub!")
+
+ override fun dumpViewHierarchyWithProperties(
+ out: BufferedWriter,
+ level: Int,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun findHierarchyView(
+ className: String,
+ hashCode: Int,
+ ): View = throw RuntimeException("Stub!")
+
+ override fun setRendererPriorityPolicy(
+ rendererRequestedPriority: Int,
+ waivedWhenNotVisible: Boolean,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun getRendererRequestedPriority(): Int = throw RuntimeException("Stub!")
+
+ override fun getRendererPriorityWaivedWhenNotVisible(): Boolean = throw RuntimeException("Stub!")
+
+ @SuppressWarnings("unused")
+ override fun setTextClassifier(textClassifier: TextClassifier?) {}
+
+ override fun getTextClassifier(): TextClassifier = TextClassifier.NO_OP
+
+ // -------------------------------------------------------------------------
+ // Provider internal methods
+ // -------------------------------------------------------------------------
+
+ override fun getViewDelegate(): ViewDelegate = throw RuntimeException("Stub!")
+
+ override fun getScrollDelegate(): ScrollDelegate = throw RuntimeException("Stub!")
+
+ override fun notifyFindDialogDismissed(): Unit = throw RuntimeException("Stub!")
+
+ // -------------------------------------------------------------------------
+ // View / ViewGroup delegation methods
+ // -------------------------------------------------------------------------
+
+ class KcefViewDelegate : ViewDelegate {
+ override fun shouldDelayChildPressedState(): Boolean = throw RuntimeException("Stub!")
+
+ override fun onProvideVirtualStructure(structure: android.view.ViewStructure): Unit = throw RuntimeException("Stub!")
+
+ override fun onProvideAutofillVirtualStructure(
+ @SuppressWarnings("unused") structure: android.view.ViewStructure,
+ @SuppressWarnings("unused") flags: Int,
+ ) {}
+
+ override fun autofill(
+ @SuppressWarnings("unused") values: SparseArray,
+ ) {}
+
+ override fun isVisibleToUserForAutofill(
+ @SuppressWarnings("unused") virtualId: Int,
+ ): Boolean {
+ return true // true is the default value returned by View.isVisibleToUserForAutofill()
+ }
+
+ override fun onProvideContentCaptureStructure(
+ @SuppressWarnings("unused") structure: android.view.ViewStructure,
+ @SuppressWarnings("unused") flags: Int,
+ ) {}
+
+ override fun getAccessibilityNodeProvider(): AccessibilityNodeProvider = throw RuntimeException("Stub!")
+
+ override fun onInitializeAccessibilityNodeInfo(info: AccessibilityNodeInfo): Unit = throw RuntimeException("Stub!")
+
+ override fun onInitializeAccessibilityEvent(event: AccessibilityEvent): Unit = throw RuntimeException("Stub!")
+
+ override fun performAccessibilityAction(
+ action: Int,
+ arguments: Bundle,
+ ): Boolean = throw RuntimeException("Stub!")
+
+ override fun setOverScrollMode(mode: Int): Unit = throw RuntimeException("Stub!")
+
+ override fun setScrollBarStyle(style: Int): Unit = throw RuntimeException("Stub!")
+
+ override fun onDrawVerticalScrollBar(
+ canvas: Canvas,
+ scrollBar: Drawable,
+ l: Int,
+ t: Int,
+ r: Int,
+ b: Int,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun onOverScrolled(
+ scrollX: Int,
+ scrollY: Int,
+ clampedX: Boolean,
+ clampedY: Boolean,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun onWindowVisibilityChanged(visibility: Int): Unit = throw RuntimeException("Stub!")
+
+ override fun onDraw(canvas: Canvas): Unit = throw RuntimeException("Stub!")
+
+ override fun setLayoutParams(layoutParams: LayoutParams): Unit = throw RuntimeException("Stub!")
+
+ override fun performLongClick(): Boolean = throw RuntimeException("Stub!")
+
+ override fun onConfigurationChanged(newConfig: Configuration): Unit = throw RuntimeException("Stub!")
+
+ override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection = throw RuntimeException("Stub!")
+
+ override fun onDragEvent(event: DragEvent): Boolean = throw RuntimeException("Stub!")
+
+ override fun onKeyMultiple(
+ keyCode: Int,
+ repeatCount: Int,
+ event: KeyEvent,
+ ): Boolean = throw RuntimeException("Stub!")
+
+ override fun onKeyDown(
+ keyCode: Int,
+ event: KeyEvent,
+ ): Boolean = throw RuntimeException("Stub!")
+
+ override fun onKeyUp(
+ keyCode: Int,
+ event: KeyEvent,
+ ): Boolean = throw RuntimeException("Stub!")
+
+ override fun onAttachedToWindow(): Unit = throw RuntimeException("Stub!")
+
+ override fun onDetachedFromWindow(): Unit = throw RuntimeException("Stub!")
+
+ override fun onMovedToDisplay(
+ displayId: Int,
+ config: Configuration,
+ ) {}
+
+ override fun onVisibilityChanged(
+ changedView: View,
+ visibility: Int,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun onWindowFocusChanged(hasWindowFocus: Boolean): Unit = throw RuntimeException("Stub!")
+
+ override fun onFocusChanged(
+ focused: Boolean,
+ direction: Int,
+ previouslyFocusedRect: Rect,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun setFrame(
+ left: Int,
+ top: Int,
+ right: Int,
+ bottom: Int,
+ ): Boolean = throw RuntimeException("Stub!")
+
+ override fun onSizeChanged(
+ w: Int,
+ h: Int,
+ ow: Int,
+ oh: Int,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun onScrollChanged(
+ l: Int,
+ t: Int,
+ oldl: Int,
+ oldt: Int,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean = throw RuntimeException("Stub!")
+
+ override fun onTouchEvent(ev: MotionEvent): Boolean = throw RuntimeException("Stub!")
+
+ override fun onHoverEvent(event: MotionEvent): Boolean = throw RuntimeException("Stub!")
+
+ override fun onGenericMotionEvent(event: MotionEvent): Boolean = throw RuntimeException("Stub!")
+
+ override fun onTrackballEvent(ev: MotionEvent): Boolean = throw RuntimeException("Stub!")
+
+ override fun requestFocus(
+ direction: Int,
+ previouslyFocusedRect: Rect,
+ ): Boolean = throw RuntimeException("Stub!")
+
+ override fun onMeasure(
+ widthMeasureSpec: Int,
+ heightMeasureSpec: Int,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun requestChildRectangleOnScreen(
+ child: View,
+ rect: Rect,
+ immediate: Boolean,
+ ): Boolean = throw RuntimeException("Stub!")
+
+ override fun setBackgroundColor(color: Int): Unit = throw RuntimeException("Stub!")
+
+ override fun setLayerType(
+ layerType: Int,
+ paint: Paint,
+ ) {
+ // ignore
+ }
+
+ override fun preDispatchDraw(canvas: Canvas): Unit = throw RuntimeException("Stub!")
+
+ override fun onStartTemporaryDetach(): Unit = throw RuntimeException("Stub!")
+
+ override fun onFinishTemporaryDetach(): Unit = throw RuntimeException("Stub!")
+
+ override fun onActivityResult(
+ requestCode: Int,
+ resultCode: Int,
+ data: Intent,
+ ): Unit = throw RuntimeException("Stub!")
+
+ override fun getHandler(originalHandler: Handler): Handler = throw RuntimeException("Stub!")
+
+ override fun findFocus(originalFocusedView: View): View = throw RuntimeException("Stub!")
+
+ @SuppressWarnings("unused")
+ override fun onCheckIsTextEditor(): Boolean = false
+
+ @SuppressWarnings("unused")
+ override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets? = null
+
+ @SuppressWarnings("unused")
+ override fun onResolvePointerIcon(
+ event: MotionEvent,
+ pointerIndex: Int,
+ ): PointerIcon? = null
+ }
+
+ class KcefScrollDelegate : ScrollDelegate {
+ override fun computeHorizontalScrollRange(): Int = throw RuntimeException("Stub!")
+
+ override fun computeHorizontalScrollOffset(): Int = throw RuntimeException("Stub!")
+
+ override fun computeVerticalScrollRange(): Int = throw RuntimeException("Stub!")
+
+ override fun computeVerticalScrollOffset(): Int = throw RuntimeException("Stub!")
+
+ override fun computeVerticalScrollExtent(): Int = throw RuntimeException("Stub!")
+
+ override fun computeScroll(): Unit = throw RuntimeException("Stub!")
+ }
+
+ private fun createContext(
+ additionalHttpHeaders: Map? = null,
+ postData: ByteArray? = null,
+ ): CefRequestContext =
+ CefRequestContext.createContext {
+ browser,
+ frame,
+ request,
+ isNavigation,
+ isDownload,
+ requestInitiator,
+ disableDefaultHandling,
+ ->
+ KCEFResourceRequestHandler.globalHandler(
+ browser,
+ frame,
+ request.apply {
+ if (!additionalHttpHeaders.isNullOrEmpty()) {
+ additionalHttpHeaders.forEach {
+ setHeaderByName(it.key, it.value, true)
+ }
+ }
+
+ if (postData != null) {
+ this.postData =
+ CefPostData.create().apply {
+ addElement(
+ CefPostDataElement.create().apply {
+ setToBytes(postData.size, postData)
+ },
+ )
+ }
+ }
+ },
+ isNavigation,
+ isDownload,
+ requestInitiator,
+ disableDefaultHandling,
+ )
+ }
+}
diff --git a/README.md b/README.md
index 01cf2f59..2c16f615 100644
--- a/README.md
+++ b/README.md
@@ -95,6 +95,25 @@ Download the latest `linux-x64`(x86_64) release from [the releases section](http
`tar xvf` the downloaded file and double-click on one of the launcher scripts or run them using the terminal.
+#### WebView support
+
+WebView support is implemented via [KCEF](https://github.com/DATL4G/KCEF).
+This is optional, and is only necessary to support some extensions.
+
+To have a functional WebView, several dependencies are required; aside from X11 libraries necessary for rendering Chromium, some JNI bindings are necessary: gluegen and jogl (found in Ubuntu as `libgluegen2-jni` and `libjogl2-jni`).
+Note that on some systems (e.g. Ubuntu), the JNI libraries are not automatically found, see below.
+
+A KCEF server is launched on startup, which loads the X11 libraries.
+If those are missing, you should see "Could not load 'jcef' library".
+If so, use `ldd ~/.local/share/Tachidesk/bin/kcef/libjcef.so | grep not` to figure out which libraries are not found on your system.
+
+The JNI bindings are only loaded when a browser is actually launched.
+This is done by extensions that rely on WebView, not by Suwayomi itself.
+If there is a problem loading the JNI libraries, you should see a message indicating the library and the search path.
+This search path includes the current working directory, if you do not want to modify system directories.
+
+Refer to the [Dockerfile](https://github.com/Suwayomi/Suwayomi-Server-docker/blob/main/Dockerfile) for more details.
+
## Other methods of getting Suwayomi
### Docker
Check our Official Docker release [Suwayomi Container](https://github.com/orgs/Suwayomi/packages/container/package/tachidesk) for running Suwayomi Server in a docker container. Source code for our container is available at [docker-tachidesk](https://github.com/Suwayomi/docker-tachidesk), an example compose file can also be found there. By default, the server will be running on http://localhost:4567 open this url in your browser.
diff --git a/build.gradle.kts b/build.gradle.kts
index fabe5f12..932a3914 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -23,6 +23,7 @@ allprojects {
google()
maven("https://github.com/Suwayomi/Suwayomi-Server/raw/android-jar/")
maven("https://jitpack.io")
+ maven("https://jogamp.org/deployment/maven")
}
}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 604bfc27..dde6bb9e 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -146,6 +146,9 @@ cron4j = "it.sauronsoftware.cron4j:cron4j:2.2.5"
# cron-utils
cronUtils = "com.cronutils:cron-utils:9.2.1"
+# Webview
+kcef = "dev.datlag:kcef:2024.04.20.4"
+
# lint - used for renovate to update ktlint version
ktlint = { module = "com.pinterest.ktlint:ktlint-cli", version.ref = "ktlint" }
@@ -194,7 +197,8 @@ shared = [
"dex2jar-translator",
"dex2jar-tools",
"apk-parser",
- "jackson-annotations"
+ "jackson-annotations",
+ "kcef"
]
sharedTest = [
@@ -244,4 +248,4 @@ twelvemonkeys = [
"twelvemonkeys-imageio-metadata",
"twelvemonkeys-imageio-jpeg",
"twelvemonkeys-imageio-webp",
-]
\ No newline at end of file
+]
diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt
index 6dab5215..3a6c7255 100644
--- a/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt
+++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt
@@ -16,6 +16,7 @@ import io.github.oshai.kotlinlogging.KotlinLogging
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@@ -54,6 +55,7 @@ class NetworkHelper(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
)
+ val userAgentFlow = userAgent.asStateFlow()
fun defaultUserAgentProvider(): String = userAgent.value
diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt
index 6b4cc021..28bb7163 100644
--- a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt
+++ b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt
@@ -117,6 +117,14 @@ class ServerConfig(
// extensions
val extensionRepos: MutableStateFlow> by OverrideConfigValues(StringConfigAdapter)
+ // playwright webview
+ val playwrightBrowser: MutableStateFlow by OverrideConfigValue(StringConfigAdapter)
+ val playwrightWsEndpoint: MutableStateFlow by OverrideConfigValue(StringConfigAdapter)
+ val playwrightSandbox: MutableStateFlow by OverrideConfigValue(BooleanConfigAdapter)
+
+ // webview
+ val webviewImpl: MutableStateFlow by OverrideConfigValue(StringConfigAdapter)
+
// requests
val maxSourcesInParallel: MutableStateFlow by OverrideConfigValue(IntConfigAdapter)
diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt
index 81a8d0e7..dee78a99 100644
--- a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt
+++ b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt
@@ -7,8 +7,10 @@ package suwayomi.tachidesk.server
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+import android.os.Looper
import ch.qos.logback.classic.Level
import com.typesafe.config.ConfigRenderOptions
+import dev.datlag.kcef.KCEF
import eu.kanade.tachiyomi.App
import eu.kanade.tachiyomi.createAppModule
import eu.kanade.tachiyomi.network.NetworkHelper
@@ -16,9 +18,14 @@ import eu.kanade.tachiyomi.source.local.LocalSource
import io.github.oshai.kotlinlogging.KotlinLogging
import io.javalin.json.JavalinJackson
import io.javalin.json.JsonMapper
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.koin.core.context.startKoin
import org.koin.core.module.Module
@@ -50,6 +57,10 @@ import java.net.Authenticator
import java.net.PasswordAuthentication
import java.security.Security
import java.util.Locale
+import kotlin.io.path.Path
+import kotlin.io.path.createDirectories
+import kotlin.io.path.div
+import kotlin.math.roundToInt
private val logger = KotlinLogging.logger {}
@@ -70,6 +81,15 @@ class ApplicationDirs(
val mangaDownloadsRoot get() = "$downloadsRoot/mangas"
}
+@Suppress("DEPRECATION")
+class LooperThread : Thread() {
+ override fun run() {
+ logger.info { "Starting Android Main Loop" }
+ Looper.prepareMainLooper()
+ Looper.loop()
+ }
+}
+
data class ProxySettings(
val proxyEnabled: Boolean,
val socksProxyVersion: Int,
@@ -100,11 +120,15 @@ fun serverModule(applicationDirs: ApplicationDirs): Module =
single { JavalinJackson() }
}
+@OptIn(DelicateCoroutinesApi::class)
fun applicationSetup() {
Thread.setDefaultUncaughtExceptionHandler { _, throwable ->
KotlinLogging.logger { }.error(throwable) { "unhandled exception" }
}
+ val mainLoop = LooperThread()
+ mainLoop.start()
+
// register Tachidesk's config which is dubbed "ServerConfig"
GlobalConfigManager.registerModule(
ServerConfig.register { GlobalConfigManager.config },
@@ -187,7 +211,12 @@ fun applicationSetup() {
androidCompat.startApp(app)
// Initialize NetworkHelper early
- Injekt.get()
+ Injekt
+ .get()
+ .userAgentFlow
+ .onEach {
+ System.setProperty("http.agent", it)
+ }.launchIn(GlobalScope)
// create or update conf file if doesn't exist
try {
@@ -312,4 +341,29 @@ fun applicationSetup() {
// start DownloadManager and restore + resume downloads
DownloadManager.restoreAndResumeDownloads()
+
+ GlobalScope.launch {
+ val logger = KotlinLogging.logger("KCEF")
+ KCEF.init(
+ builder = {
+ progress {
+ var lastNum = -1
+ onDownloading {
+ val num = it.roundToInt()
+ if (num > lastNum) {
+ lastNum = num
+ logger.info { "KCEF download progress: $num%" }
+ }
+ }
+ }
+ download { github() }
+ val kcefDir = Path(applicationDirs.dataRoot) / "bin/kcef"
+ kcefDir.createDirectories()
+ installDir(kcefDir.toFile())
+ },
+ onError = {
+ it?.printStackTrace()
+ },
+ )
+ }
}