Merge "Changes on the ContentCaptureContext APIs."
This commit is contained in:
committed by
Android (Google) Code Review
commit
f7612ac846
@@ -10284,6 +10284,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";
|
||||
@@ -10368,6 +10369,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";
|
||||
@@ -10620,6 +10622,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);
|
||||
@@ -53471,16 +53481,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 {
|
||||
@@ -53513,8 +53524,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;
|
||||
@@ -53522,13 +53533,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();
|
||||
}
|
||||
|
||||
|
||||
@@ -9379,14 +9379,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
|
||||
}
|
||||
|
||||
@@ -2728,14 +2728,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
|
||||
}
|
||||
|
||||
@@ -4344,6 +4344,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()).
|
||||
@@ -5542,6 +5554,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).
|
||||
|
||||
115
core/java/android/content/LocusId.java
Normal file
115
core/java/android/content/LocusId.java
Normal file
@@ -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];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,14 +211,39 @@ public final class ContentCaptureContext implements Parcelable {
|
||||
return mFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Creates a new builder.
|
||||
*
|
||||
* <p>The context must have an id, which is usually one of the following:
|
||||
*
|
||||
* <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).
|
||||
*
|
||||
* @param id id associated with this context.
|
||||
*/
|
||||
// TODO(b/123577059): make sure this is well documented and understandable
|
||||
public Builder(@NonNull LocusId id) {
|
||||
mId = Preconditions.checkNotNull(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets extra options associated with this context.
|
||||
@@ -261,51 +262,15 @@ public final class ContentCaptureContext implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Uri} associated with this context.
|
||||
*
|
||||
* <p>See {@link View#setContentCaptureSession(ContentCaptureSession)} for an example.
|
||||
*
|
||||
* @param uri URI associated with this context.
|
||||
* @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);
|
||||
throwIfDestroyed();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user