diff options
| -rw-r--r-- | api/current.txt | 25 | ||||
| -rw-r--r-- | api/system-current.txt | 3 | ||||
| -rw-r--r-- | api/test-current.txt | 3 | ||||
| -rw-r--r-- | core/java/android/content/Intent.java | 21 | ||||
| -rw-r--r-- | core/java/android/content/LocusId.java | 115 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 21 | ||||
| -rw-r--r-- | core/java/android/view/contentcapture/ContentCaptureContext.java | 161 | ||||
| -rw-r--r-- | core/java/android/view/contentcapture/UserDataRemovalRequest.java | 78 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java | 13 |
9 files changed, 273 insertions, 167 deletions
diff --git a/api/current.txt b/api/current.txt index fe86cbe48375..f6fe771b7716 100644 --- a/api/current.txt +++ b/api/current.txt @@ -10302,6 +10302,7 @@ package android.content { field public static final String ACTION_USER_PRESENT = "android.intent.action.USER_PRESENT"; field public static final String ACTION_USER_UNLOCKED = "android.intent.action.USER_UNLOCKED"; field public static final String ACTION_VIEW = "android.intent.action.VIEW"; + field public static final String ACTION_VIEW_LOCUS = "android.intent.action.VIEW_LOCUS"; field public static final String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND"; field @Deprecated public static final String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED"; field public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH"; @@ -10386,6 +10387,7 @@ package android.content { field public static final String EXTRA_INTENT = "android.intent.extra.INTENT"; field public static final String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT"; field public static final String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY"; + field public static final String EXTRA_LOCUS_ID = "android.intent.extra.LOCUS_ID"; field public static final String EXTRA_MIME_TYPES = "android.intent.extra.MIME_TYPES"; field public static final String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE"; field public static final String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI"; @@ -10638,6 +10640,14 @@ package android.content { method @Deprecated public void onLoadComplete(android.content.Loader<D>, D); } + public final class LocusId implements android.os.Parcelable { + ctor public LocusId(@NonNull android.net.Uri); + method public int describeContents(); + method @NonNull public android.net.Uri getUri(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.content.LocusId> CREATOR; + } + public class MutableContextWrapper extends android.content.ContextWrapper { ctor public MutableContextWrapper(android.content.Context); method public void setBaseContext(android.content.Context); @@ -53500,16 +53510,17 @@ package android.view.contentcapture { public final class ContentCaptureContext implements android.os.Parcelable { method public int describeContents(); + method public static android.view.contentcapture.ContentCaptureContext forLocusId(@NonNull android.net.Uri); + method @Nullable public android.os.Bundle getExtras(); + method @NonNull public android.content.LocusId getLocusId(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureContext> CREATOR; } public static final class ContentCaptureContext.Builder { - ctor public ContentCaptureContext.Builder(); + ctor public ContentCaptureContext.Builder(@NonNull android.content.LocusId); method public android.view.contentcapture.ContentCaptureContext build(); - method @NonNull public android.view.contentcapture.ContentCaptureContext.Builder setAction(@NonNull String); method @NonNull public android.view.contentcapture.ContentCaptureContext.Builder setExtras(@NonNull android.os.Bundle); - method @NonNull public android.view.contentcapture.ContentCaptureContext.Builder setUri(@NonNull android.net.Uri); } public final class ContentCaptureManager { @@ -53542,8 +53553,8 @@ package android.view.contentcapture { public final class UserDataRemovalRequest implements android.os.Parcelable { method public int describeContents(); + method @NonNull public java.util.List<android.view.contentcapture.UserDataRemovalRequest.LocusIdRequest> getLocusIdRequests(); method @NonNull public String getPackageName(); - method @NonNull public java.util.List<android.view.contentcapture.UserDataRemovalRequest.UriRequest> getUriRequests(); method public boolean isForEverything(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.view.contentcapture.UserDataRemovalRequest> CREATOR; @@ -53551,13 +53562,13 @@ package android.view.contentcapture { public static final class UserDataRemovalRequest.Builder { ctor public UserDataRemovalRequest.Builder(); - method public android.view.contentcapture.UserDataRemovalRequest.Builder addUri(@NonNull android.net.Uri, boolean); + method public android.view.contentcapture.UserDataRemovalRequest.Builder addLocusId(@NonNull android.content.LocusId, boolean); method @NonNull public android.view.contentcapture.UserDataRemovalRequest build(); method @NonNull public android.view.contentcapture.UserDataRemovalRequest.Builder forEverything(); } - public final class UserDataRemovalRequest.UriRequest { - method @NonNull public android.net.Uri getUri(); + public final class UserDataRemovalRequest.LocusIdRequest { + method @NonNull public android.content.LocusId getLocusId(); method @NonNull public boolean isRecursive(); } diff --git a/api/system-current.txt b/api/system-current.txt index 50a2553d7f1a..6e3050ffb9a3 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -9326,14 +9326,11 @@ package android.view.autofill { package android.view.contentcapture { public final class ContentCaptureContext implements android.os.Parcelable { - method @Nullable public String getAction(); method @Nullable public android.content.ComponentName getActivityComponent(); method public int getDisplayId(); - method @Nullable public android.os.Bundle getExtras(); method public int getFlags(); method @Nullable public android.view.contentcapture.ContentCaptureSessionId getParentSessionId(); method public int getTaskId(); - method @Nullable public android.net.Uri getUri(); field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1 field public static final int FLAG_DISABLED_BY_FLAG_SECURE = 2; // 0x2 } diff --git a/api/test-current.txt b/api/test-current.txt index 16098c1a80fa..6cf6cd85b1ec 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -2714,14 +2714,11 @@ package android.view.autofill { package android.view.contentcapture { public final class ContentCaptureContext implements android.os.Parcelable { - method @Nullable public String getAction(); method @Nullable public android.content.ComponentName getActivityComponent(); method public int getDisplayId(); - method @Nullable public android.os.Bundle getExtras(); method public int getFlags(); method @Nullable public android.view.contentcapture.ContentCaptureSessionId getParentSessionId(); method public int getTaskId(); - method @Nullable public android.net.Uri getUri(); field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1 field public static final int FLAG_DISABLED_BY_FLAG_SECURE = 2; // 0x2 } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index a5e7e95f0874..fda908569562 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -4336,6 +4336,18 @@ public class Intent implements Parcelable, Cloneable { "android.intent.action.DEVICE_CUSTOMIZATION_READY"; + /** + * Activity Action: Display an activity state associated with an unique {@link LocusId}. + * + * <p>For example, a chat app could use the context to resume a conversation between 2 users. + * + * <p>Input: {@link #EXTRA_LOCUS_ID} specifies the unique identifier of the locus in the + * app domain. Should be stable across reboots and backup / restore. + * <p>Output: nothing. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_VIEW_LOCUS = "android.intent.action.VIEW_LOCUS"; + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Standard intent categories (see addCategory()). @@ -5534,6 +5546,15 @@ public class Intent implements Parcelable, Cloneable { */ public static final int EXTRA_MEDIA_RESOURCE_TYPE_AUDIO_CODEC = 1; + /** + * Intent extra: ID of the context used on {@link #ACTION_VIEW_LOCUS}. + * + * <p> + * Type: {@link LocusId} + * </p> + */ + public static final String EXTRA_LOCUS_ID = "android.intent.extra.LOCUS_ID"; + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Intent flags (see mFlags variable). diff --git a/core/java/android/content/LocusId.java b/core/java/android/content/LocusId.java new file mode 100644 index 000000000000..9548f9c32d90 --- /dev/null +++ b/core/java/android/content/LocusId.java @@ -0,0 +1,115 @@ +/* + * 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.content; + +import android.annotation.NonNull; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; + +import java.io.PrintWriter; + +/** + * Identifier for an unique state in the application. + * + * <p>Should be stable across reboots and backup / restore. + * + * <p>For example, a chat app could use the context to resume a conversation between 2 users. + */ +// TODO(b/123577059): make sure this is well documented and understandable +public final class LocusId implements Parcelable { + + private final Uri mUri; + + /** + * Default constructor. + */ + public LocusId(@NonNull Uri uri) { + mUri = Preconditions.checkNotNull(uri); + } + + /** + * Gets the {@code uri} associated with the locus. + */ + @NonNull + public Uri getUri() { + return mUri; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((mUri == null) ? 0 : mUri.hashCode()); + 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 LocusId other = (LocusId) obj; + if (mUri == null) { + if (other.mUri != null) return false; + } else { + if (!mUri.equals(other.mUri)) return false; + } + return true; + } + + @Override + public String toString() { + return "LocusId[uri=" + getSanitizedUri() + "]"; + } + + /** @hide */ + public void dump(@NonNull PrintWriter pw) { + pw.print("uri:"); pw.println(getSanitizedUri()); + } + + private String getSanitizedUri() { + final int size = mUri.toString().length(); + return size + "_chars"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(mUri, flags); + } + + public static final Parcelable.Creator<LocusId> CREATOR = + new Parcelable.Creator<LocusId>() { + + @Override + public LocusId createFromParcel(Parcel source) { + final Uri uri = source.readParcelable(null); + return new LocusId(uri); + } + + @Override + public LocusId[] newArray(int size) { + return new LocusId[size]; + } + }; +} diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 2b440dc80cfd..a78f2b073a3a 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -9463,17 +9463,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * the Content Capture events associated with this view or its view hierarchy (if it's a * {@link ViewGroup}). * + * <p>For example, if your activity is associated with a web domain, first you would need to + * set the context for the main DOM: + * + * <pre> + * ContentCaptureSession mainSession = rootView.getContentCaptureSession(); + * mainSession.setContentCaptureContext(ContentCaptureContext.forLocusId(Uri.parse(myUrl)); + * <pre> + * + * <p>Then if the page had an {@code IFRAME}, you would create a new session for it: + * * <p>For example, if your activity is associated with a web domain, you could create a session * {@code onCreate()} and associate it with the root view of the activity: * * <pre> - * ContentCaptureSession oldSession = rootView.getContentCaptureSession(); - * if (oldSession != null) { - * ContentCaptureSession newSession = oldSession.createContentCaptureSession(new - * ContentCaptureContext.Builder().setUri(myUrl).build()); - * rootView.setContentCaptureSession(newSession); - * } - * </pre> + * ContentCaptureSession iframeSession = mainSession.createContentCaptureSession( + * ContentCaptureContext.forLocusId(Uri.parse(iframeUrl))); + * iframeView.setContentCaptureSession(iframeSession); + * <pre> * * @param contentCaptureSession a session created by * {@link ContentCaptureSession#createContentCaptureSession( diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java index 6a9759db78a0..8bb4d210ad44 100644 --- a/core/java/android/view/contentcapture/ContentCaptureContext.java +++ b/core/java/android/view/contentcapture/ContentCaptureContext.java @@ -23,7 +23,7 @@ import android.annotation.TestApi; import android.app.TaskInfo; import android.content.ComponentName; import android.content.Context; -import android.content.Intent; +import android.content.LocusId; import android.net.Uri; import android.os.Bundle; import android.os.Parcel; @@ -88,8 +88,7 @@ public final class ContentCaptureContext implements Parcelable { // Fields below are set by app on Builder private final @Nullable Bundle mExtras; - private final @Nullable Uri mUri; - private final @Nullable String mAction; + private final @Nullable LocusId mId; // Fields below are set by server when the session starts private final @Nullable ComponentName mComponentName; @@ -106,13 +105,11 @@ public final class ContentCaptureContext implements Parcelable { if (clientContext != null) { mHasClientContext = true; mExtras = clientContext.mExtras; - mUri = clientContext.mUri; - mAction = clientContext.mAction; + mId = clientContext.mId; } else { mHasClientContext = false; mExtras = null; - mUri = null; - mAction = null; + mId = null; } mComponentName = Preconditions.checkNotNull(componentName); mTaskId = taskId; @@ -123,8 +120,7 @@ public final class ContentCaptureContext implements Parcelable { private ContentCaptureContext(@NonNull Builder builder) { mHasClientContext = true; mExtras = builder.mExtras; - mUri = builder.mUri; - mAction = builder.mAction; + mId = builder.mId; mComponentName = null; mTaskId = mFlags = 0; @@ -135,38 +131,18 @@ public final class ContentCaptureContext implements Parcelable { * Gets the (optional) extras set by the app (through {@link Builder#setExtras(Bundle)}). * * <p>It can be used to provide vendor-specific data that can be modified and examined. - * - * @hide */ - @SystemApi - @TestApi @Nullable public Bundle getExtras() { return mExtras; } /** - * Gets the (optional) URI set by the app (through {@link Builder#setUri(Uri)}). - * - * @hide + * Gets the context id. */ - @SystemApi - @TestApi - @Nullable - public Uri getUri() { - return mUri; - } - - /** - * Gets the (optional) action set by the app (through {@link Builder#setAction(String)}). - * - * @hide - */ - @SystemApi - @TestApi - @Nullable - public String getAction() { - return mAction; + @NonNull + public LocusId getLocusId() { + return mId; } /** @@ -236,60 +212,52 @@ public final class ContentCaptureContext implements Parcelable { } /** + * Helper that creates a {@link ContentCaptureContext} associated with the given {@code uri}. + */ + public static ContentCaptureContext forLocusId(@NonNull Uri uri) { + return new Builder(new LocusId(uri)).build(); + } + + /** * Builder for {@link ContentCaptureContext} objects. */ public static final class Builder { private Bundle mExtras; - private Uri mUri; + private final LocusId mId; private boolean mDestroyed; - private String mAction; /** - * Sets extra options associated with this context. + * Creates a new builder. * - * <p>It can be used to provide vendor-specific data that can be modified and examined. + * <p>The context must have an id, which is usually one of the following: * - * @param extras extra options. - * @return this builder. + * <ul> + * <li>A URL representing a web page (or {@code IFRAME}) that's being rendered by the + * activity (See {@link View#setContentCaptureSession(ContentCaptureSession)} for an + * example). + * <li>A unique identifier of the application state (for example, a conversation between + * 2 users in a chat app). * - * @throws IllegalStateException if {@link #build()} was already called. + * @param id id associated with this context. */ - @NonNull - public Builder setExtras(@NonNull Bundle extras) { - mExtras = Preconditions.checkNotNull(extras); - throwIfDestroyed(); - return this; + // TODO(b/123577059): make sure this is well documented and understandable + public Builder(@NonNull LocusId id) { + mId = Preconditions.checkNotNull(id); } /** - * Sets the {@link Uri} associated with this context. + * Sets extra options associated with this context. * - * <p>See {@link View#setContentCaptureSession(ContentCaptureSession)} for an example. + * <p>It can be used to provide vendor-specific data that can be modified and examined. * - * @param uri URI associated with this context. + * @param extras extra options. * @return this builder. * * @throws IllegalStateException if {@link #build()} was already called. */ @NonNull - public Builder setUri(@NonNull Uri uri) { - mUri = Preconditions.checkNotNull(uri); - throwIfDestroyed(); - return this; - } - - /** - * Sets an {@link Intent#getAction() intent action} associated with this context. - * - * @param action intent action - * - * @return this builder - * - * @throws IllegalStateException if {@link #build()} was already called. - */ - @NonNull - public Builder setAction(@NonNull String action) { - mAction = Preconditions.checkNotNull(action); + public Builder setExtras(@NonNull Bundle extras) { + mExtras = Preconditions.checkNotNull(extras); throwIfDestroyed(); return this; } @@ -297,15 +265,12 @@ public final class ContentCaptureContext implements Parcelable { /** * Builds the {@link ContentCaptureContext}. * - * @throws IllegalStateException if {@link #build()} was already called or no call to either - * {@link #setExtras(Bundle)}, {@link #setAction(String)}, or {@link #setUri(Uri)} was made. + * @throws IllegalStateException if {@link #build()} was already called. * * @return the built {@code ContentCaptureContext} */ public ContentCaptureContext build() { throwIfDestroyed(); - Preconditions.checkState(mExtras != null || mUri != null || mAction != null, - "Must call setUri() or setExtras() or setUri() before calling build()"); mDestroyed = true; return new ContentCaptureContext(this); } @@ -320,7 +285,12 @@ public final class ContentCaptureContext implements Parcelable { */ // TODO(b/111276913): dump to proto as well public void dump(PrintWriter pw) { - pw.print("comp="); pw.print(ComponentName.flattenToShortString(mComponentName)); + if (mComponentName != null) { + pw.print("activity="); pw.print(mComponentName.flattenToShortString()); + } + if (mId != null) { + pw.print(", id="); mId.dump(pw); + } pw.print(", taskId="); pw.print(mTaskId); pw.print(", displayId="); pw.print(mDisplayId); if (mParentSessionId != null) { @@ -333,38 +303,31 @@ public final class ContentCaptureContext implements Parcelable { // NOTE: cannot dump because it could contain PII pw.print(", hasExtras"); } - if (mUri != null) { - // NOTE: cannot dump because it could contain PII - pw.print(", hasUri"); - } - if (mAction != null) { - // NOTE: cannot dump because it could contain PII - pw.print(", hasAction"); - } + } + + private boolean fromServer() { + return mComponentName != null; } @Override public String toString() { - final StringBuilder builder = new StringBuilder("Context[act=") - .append(ComponentName.flattenToShortString(mComponentName)) + final StringBuilder builder = new StringBuilder("Context["); + + if (fromServer()) { + builder.append("act=").append(ComponentName.flattenToShortString(mComponentName)) .append(", taskId=").append(mTaskId) .append(", displayId=").append(mDisplayId) .append(", flags=").append(mFlags); + } else { + builder.append("id=").append(mId); + if (mExtras != null) { + // NOTE: cannot print because it could contain PII + builder.append(", hasExtras"); + } + } if (mParentSessionId != null) { builder.append(", parentId=").append(mParentSessionId); } - if (mExtras != null) { - // NOTE: cannot print because it could contain PII - builder.append(", hasExtras"); - } - if (mUri != null) { - // NOTE: cannot print because it could contain PII - builder.append(", hasUri"); - } - if (mAction != null) { - // NOTE: cannot print because it could contain PII - builder.append(", hasAction"); - } return builder.append(']').toString(); } @@ -377,12 +340,11 @@ public final class ContentCaptureContext implements Parcelable { public void writeToParcel(Parcel parcel, int flags) { parcel.writeInt(mHasClientContext ? 1 : 0); if (mHasClientContext) { - parcel.writeParcelable(mUri, flags); - parcel.writeString(mAction); + parcel.writeParcelable(mId, flags); parcel.writeBundle(mExtras); } parcel.writeParcelable(mComponentName, flags); - if (mComponentName != null) { + if (fromServer()) { parcel.writeInt(mTaskId); parcel.writeInt(mDisplayId); parcel.writeInt(mFlags); @@ -399,12 +361,9 @@ public final class ContentCaptureContext implements Parcelable { final ContentCaptureContext clientContext; if (hasClientContext) { // Must reconstruct the client context using the Builder API - final Builder builder = new Builder(); - final Uri uri = parcel.readParcelable(null); - final String action = parcel.readString(); + final LocusId id = parcel.readParcelable(null); final Bundle extras = parcel.readBundle(); - if (uri != null) builder.setUri(uri); - if (action != null) builder.setAction(action); + final Builder builder = new Builder(id); if (extras != null) builder.setExtras(extras); clientContext = new ContentCaptureContext(builder); } else { diff --git a/core/java/android/view/contentcapture/UserDataRemovalRequest.java b/core/java/android/view/contentcapture/UserDataRemovalRequest.java index 8fedcd54b1fc..7d66af92e9f6 100644 --- a/core/java/android/view/contentcapture/UserDataRemovalRequest.java +++ b/core/java/android/view/contentcapture/UserDataRemovalRequest.java @@ -17,7 +17,7 @@ package android.view.contentcapture; import android.annotation.NonNull; import android.app.ActivityThread; -import android.net.Uri; +import android.content.LocusId; import android.os.Parcel; import android.os.Parcelable; import android.util.IntArray; @@ -36,16 +36,16 @@ public final class UserDataRemovalRequest implements Parcelable { private final String mPackageName; private final boolean mForEverything; - private ArrayList<UriRequest> mUriRequests; + private ArrayList<LocusIdRequest> mLocusIdRequests; private UserDataRemovalRequest(@NonNull Builder builder) { mPackageName = ActivityThread.currentActivityThread().getApplication().getPackageName(); mForEverything = builder.mForEverything; - if (builder.mUris != null) { - final int size = builder.mUris.size(); - mUriRequests = new ArrayList<>(size); + if (builder.mLocusIds != null) { + final int size = builder.mLocusIds.size(); + mLocusIdRequests = new ArrayList<>(size); for (int i = 0; i < size; i++) { - mUriRequests.add(new UriRequest(builder.mUris.get(i), + mLocusIdRequests.add(new LocusIdRequest(builder.mLocusIds.get(i), builder.mRecursive.get(i) == 1)); } } @@ -56,9 +56,9 @@ public final class UserDataRemovalRequest implements Parcelable { mForEverything = parcel.readBoolean(); if (!mForEverything) { final int size = parcel.readInt(); - mUriRequests = new ArrayList<>(size); + mLocusIdRequests = new ArrayList<>(size); for (int i = 0; i < size; i++) { - mUriRequests.add(new UriRequest((Uri) parcel.readValue(null), + mLocusIdRequests.add(new LocusIdRequest((LocusId) parcel.readValue(null), parcel.readBoolean())); } } @@ -80,11 +80,11 @@ public final class UserDataRemovalRequest implements Parcelable { } /** - * Gets the list of {@code Uri}s the apps is requesting to remove. + * Gets the list of {@code LousId}s the apps is requesting to remove. */ @NonNull - public List<UriRequest> getUriRequests() { - return mUriRequests; + public List<LocusIdRequest> getLocusIdRequests() { + return mLocusIdRequests; } /** @@ -93,7 +93,7 @@ public final class UserDataRemovalRequest implements Parcelable { public static final class Builder { private boolean mForEverything; - private ArrayList<Uri> mUris; + private ArrayList<LocusId> mLocusIds; private IntArray mRecursive; private boolean mDestroyed; @@ -106,36 +106,32 @@ public final class UserDataRemovalRequest implements Parcelable { @NonNull public Builder forEverything() { throwIfDestroyed(); - if (mUris != null) { - throw new IllegalStateException("Already added Uris"); - } + Preconditions.checkState(mLocusIds == null, "Already added LocusIds"); mForEverything = true; return this; } /** - * Request service to remove data associated with a given {@link Uri}. + * Request service to remove data associated with a given {@link LocusId}. * - * @param uri URI being requested to be removed. - * @param recursive whether it should remove the data associated with just the URI or its - * tree of descendants. + * @param locusId the {@link LocusId} being requested to be removed. + * @param recursive whether it should remove the data associated with just the + * {@code LocusId} or its tree of descendants. * * @return this builder */ - public Builder addUri(@NonNull Uri uri, boolean recursive) { + public Builder addLocusId(@NonNull LocusId locusId, boolean recursive) { throwIfDestroyed(); - if (mForEverything) { - throw new IllegalStateException("Already is for everything"); - } - Preconditions.checkNotNull(uri); + Preconditions.checkState(!mForEverything, "Already is for everything"); + Preconditions.checkNotNull(locusId); - if (mUris == null) { - mUris = new ArrayList<>(); + if (mLocusIds == null) { + mLocusIds = new ArrayList<>(); mRecursive = new IntArray(); } - mUris.add(uri); + mLocusIds.add(locusId); mRecursive.add(recursive ? 1 : 0); return this; } @@ -147,7 +143,7 @@ public final class UserDataRemovalRequest implements Parcelable { public UserDataRemovalRequest build() { throwIfDestroyed(); - Preconditions.checkState(mForEverything || mUris != null); + Preconditions.checkState(mForEverything || mLocusIds != null); mDestroyed = true; return new UserDataRemovalRequest(this); @@ -168,11 +164,11 @@ public final class UserDataRemovalRequest implements Parcelable { parcel.writeString(mPackageName); parcel.writeBoolean(mForEverything); if (!mForEverything) { - final int size = mUriRequests.size(); + final int size = mLocusIdRequests.size(); parcel.writeInt(size); for (int i = 0; i < size; i++) { - final UriRequest request = mUriRequests.get(i); - parcel.writeValue(request.getUri()); + final LocusIdRequest request = mLocusIdRequests.get(i); + parcel.writeValue(request.getLocusId()); parcel.writeBoolean(request.isRecursive()); } } @@ -193,28 +189,28 @@ public final class UserDataRemovalRequest implements Parcelable { }; /** - * Representation of a request to remove data associated with an {@link Uri}. + * Representation of a request to remove data associated with a {@link LocusId}. */ - public final class UriRequest { - private final @NonNull Uri mUri; + public final class LocusIdRequest { + private final @NonNull LocusId mLocusId; private final boolean mRecursive; - private UriRequest(@NonNull Uri uri, boolean recursive) { - this.mUri = uri; + private LocusIdRequest(@NonNull LocusId locusId, boolean recursive) { + this.mLocusId = locusId; this.mRecursive = recursive; } /** - * Gets the URI per se. + * Gets the {@code LocusId} per se. */ @NonNull - public Uri getUri() { - return mUri; + public LocusId getLocusId() { + return mLocusId; } /** - * Checks whether the request is to remove just the data associated with the URI per se, or - * also its descendants. + * Checks whether the request is to remove just the data associated with the {@link LocusId} + * per se, or also its descendants. */ @NonNull public boolean isRecursive() { diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java index a97c3fa362eb..a5ac2707b620 100644 --- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java +++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java @@ -24,6 +24,8 @@ import static com.google.common.truth.Truth.assertThat; import static org.testng.Assert.assertThrows; +import android.content.LocusId; +import android.net.Uri; import android.os.Parcel; import android.os.SystemClock; import android.view.autofill.AutofillId; @@ -45,9 +47,11 @@ public class ContentCaptureEventTest { private static final long MY_EPOCH = SystemClock.uptimeMillis(); + private static final LocusId ID = new LocusId(Uri.parse("WHATEVER")); + // Not using @Mock because it's final - no need to be fancy here.... - private final ContentCaptureContext mClientContext = new ContentCaptureContext.Builder() - .setAction("WHATEVER").build(); + private final ContentCaptureContext mClientContext = + new ContentCaptureContext.Builder(ID).build(); @Test public void testSetAutofillId_null() { @@ -177,7 +181,7 @@ public class ContentCaptureEventTest { assertThat(event.getViewNode()).isNull(); final ContentCaptureContext clientContext = event.getContentCaptureContext(); assertThat(clientContext).isNotNull(); - assertThat(clientContext.getAction()).isEqualTo("WHATEVER"); + assertThat(clientContext.getLocusId()).isEqualTo(ID); } @Test @@ -210,7 +214,6 @@ public class ContentCaptureEventTest { assertThat(event.getContentCaptureContext()).isNull(); } - @Test public void testContextUpdated_directly() { final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_CONTEXT_UPDATED) @@ -239,7 +242,7 @@ public class ContentCaptureEventTest { assertThat(event.getViewNode()).isNull(); final ContentCaptureContext clientContext = event.getContentCaptureContext(); assertThat(clientContext).isNotNull(); - assertThat(clientContext.getAction()).isEqualTo("WHATEVER"); + assertThat(clientContext.getLocusId()).isEqualTo(ID); } // TODO(b/123036895): add test for all events type (right now we're just testing the 3 types |