| /* |
| * Copyright (C) 2017 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.autofill; |
| |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.annotation.TestApi; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.view.View; |
| |
| /** |
| * A unique identifier for an autofill node inside an {@link android.app.Activity}. |
| */ |
| public final class AutofillId implements Parcelable { |
| |
| /** @hide */ |
| public static final int NO_SESSION = 0; |
| |
| private static final int FLAG_IS_VIRTUAL_INT = 0x1; |
| private static final int FLAG_IS_VIRTUAL_LONG = 0x2; |
| private static final int FLAG_HAS_SESSION = 0x4; |
| |
| private final int mViewId; |
| private int mFlags; |
| private final int mVirtualIntId; |
| private final long mVirtualLongId; |
| private int mSessionId; |
| |
| /** @hide */ |
| @TestApi |
| public AutofillId(int id) { |
| this(/* flags= */ 0, id, View.NO_ID, NO_SESSION); |
| } |
| |
| /** @hide */ |
| @TestApi |
| public AutofillId(@NonNull AutofillId hostId, int virtualChildId) { |
| this(FLAG_IS_VIRTUAL_INT, hostId.mViewId, virtualChildId, NO_SESSION); |
| } |
| |
| /** @hide */ |
| @TestApi |
| public AutofillId(int hostId, int virtualChildId) { |
| this(FLAG_IS_VIRTUAL_INT, hostId, virtualChildId, NO_SESSION); |
| } |
| |
| /** @hide */ |
| @TestApi |
| public AutofillId(@NonNull AutofillId hostId, long virtualChildId, int sessionId) { |
| this(FLAG_IS_VIRTUAL_LONG | FLAG_HAS_SESSION, hostId.mViewId, virtualChildId, sessionId); |
| } |
| |
| private AutofillId(int flags, int parentId, long virtualChildId, int sessionId) { |
| mFlags = flags; |
| mViewId = parentId; |
| mVirtualIntId = ((flags & FLAG_IS_VIRTUAL_INT) != 0) ? (int) virtualChildId : View.NO_ID; |
| mVirtualLongId = ((flags & FLAG_IS_VIRTUAL_LONG) != 0) ? virtualChildId : View.NO_ID; |
| mSessionId = sessionId; |
| } |
| |
| /** @hide */ |
| @NonNull |
| @TestApi |
| public static AutofillId withoutSession(@NonNull AutofillId id) { |
| final int flags = id.mFlags & ~FLAG_HAS_SESSION; |
| final long virtualChildId = |
| ((id.mFlags & FLAG_IS_VIRTUAL_LONG) != 0) ? id.mVirtualLongId |
| : id.mVirtualIntId; |
| return new AutofillId(flags, id.mViewId, virtualChildId, NO_SESSION); |
| } |
| |
| /** @hide */ |
| public int getViewId() { |
| return mViewId; |
| } |
| |
| /** |
| * Gets the virtual child id. |
| * |
| * <p>Should only be used on subsystems where such id is represented by an {@code int} |
| * (Assist and Autofill). |
| * |
| * @hide |
| */ |
| public int getVirtualChildIntId() { |
| return mVirtualIntId; |
| } |
| |
| /** |
| * Gets the virtual child id. |
| * |
| * <p>Should only be used on subsystems where such id is represented by a {@code long} |
| * (ContentCapture). |
| * |
| * @hide |
| */ |
| public long getVirtualChildLongId() { |
| return mVirtualLongId; |
| } |
| |
| /** |
| * Checks whether this node represents a virtual child, whose id is represented by an |
| * {@code int}. |
| * |
| * <p>Should only be used on subsystems where such id is represented by an {@code int} |
| * (Assist and Autofill). |
| * |
| * @hide |
| */ |
| public boolean isVirtualInt() { |
| return (mFlags & FLAG_IS_VIRTUAL_INT) != 0; |
| } |
| |
| /** |
| * Checks whether this node represents a virtual child, whose id is represented by an |
| * {@code long}. |
| * |
| * <p>Should only be used on subsystems where such id is represented by a {@code long} |
| * (ContentCapture). |
| * |
| * @hide |
| */ |
| public boolean isVirtualLong() { |
| return (mFlags & FLAG_IS_VIRTUAL_LONG) != 0; |
| } |
| |
| /** |
| * Checks whether this node represents a non-virtual child. |
| * |
| * @hide |
| */ |
| public boolean isNonVirtual() { |
| return !isVirtualInt() && !isVirtualLong(); |
| } |
| |
| /** @hide */ |
| public boolean hasSession() { |
| return (mFlags & FLAG_HAS_SESSION) != 0; |
| } |
| |
| /** @hide */ |
| public int getSessionId() { |
| return mSessionId; |
| } |
| |
| /** @hide */ |
| public void setSessionId(int sessionId) { |
| mFlags |= FLAG_HAS_SESSION; |
| mSessionId = sessionId; |
| } |
| |
| /** @hide */ |
| public void resetSessionId() { |
| mFlags &= ~FLAG_HAS_SESSION; |
| mSessionId = NO_SESSION; |
| } |
| |
| ///////////////////////////////// |
| // Object "contract" methods. // |
| ///////////////////////////////// |
| |
| @Override |
| public int hashCode() { |
| final int prime = 31; |
| int result = 1; |
| result = prime * result + mViewId; |
| result = prime * result + mVirtualIntId; |
| result = prime * result + (int) (mVirtualLongId ^ (mVirtualLongId >>> 32)); |
| result = prime * result + mSessionId; |
| return result; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) return true; |
| if (obj == null) return false; |
| if (getClass() != obj.getClass()) return false; |
| final AutofillId other = (AutofillId) obj; |
| if (mViewId != other.mViewId) return false; |
| if (mVirtualIntId != other.mVirtualIntId) return false; |
| if (mVirtualLongId != other.mVirtualLongId) return false; |
| if (mSessionId != other.mSessionId) return false; |
| return true; |
| } |
| |
| /** @hide */ |
| @TestApi |
| public boolean equalsIgnoreSession(@Nullable AutofillId other) { |
| if (this == other) return true; |
| if (other == null) return false; |
| if (mViewId != other.mViewId) return false; |
| if (mVirtualIntId != other.mVirtualIntId) return false; |
| if (mVirtualLongId != other.mVirtualLongId) return false; |
| return true; |
| } |
| |
| @Override |
| public String toString() { |
| final StringBuilder builder = new StringBuilder().append(mViewId); |
| if (isVirtualInt()) { |
| builder.append(':').append(mVirtualIntId); |
| } else if (isVirtualLong()) { |
| builder.append(':').append(mVirtualLongId); |
| } |
| |
| if (hasSession()) { |
| builder.append('@').append(mSessionId); |
| } |
| return builder.toString(); |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(Parcel parcel, int flags) { |
| parcel.writeInt(mViewId); |
| parcel.writeInt(mFlags); |
| if (hasSession()) { |
| parcel.writeInt(mSessionId); |
| } |
| if (isVirtualInt()) { |
| parcel.writeInt(mVirtualIntId); |
| } else if (isVirtualLong()) { |
| parcel.writeLong(mVirtualLongId); |
| } |
| } |
| |
| public static final @android.annotation.NonNull Parcelable.Creator<AutofillId> CREATOR = |
| new Parcelable.Creator<AutofillId>() { |
| @Override |
| public AutofillId createFromParcel(Parcel source) { |
| final int viewId = source.readInt(); |
| final int flags = source.readInt(); |
| final int sessionId = (flags & FLAG_HAS_SESSION) != 0 ? source.readInt() : NO_SESSION; |
| if ((flags & FLAG_IS_VIRTUAL_INT) != 0) { |
| return new AutofillId(flags, viewId, source.readInt(), sessionId); |
| } |
| if ((flags & FLAG_IS_VIRTUAL_LONG) != 0) { |
| return new AutofillId(flags, viewId, source.readLong(), sessionId); |
| } |
| return new AutofillId(flags, viewId, View.NO_ID, sessionId); |
| } |
| |
| @Override |
| public AutofillId[] newArray(int size) { |
| return new AutofillId[size]; |
| } |
| }; |
| } |