diff options
| -rw-r--r-- | api/current.txt | 11 | ||||
| -rw-r--r-- | api/system-current.txt | 1 | ||||
| -rw-r--r-- | api/test-current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/service/contentcapture/ContentCaptureService.java | 27 | ||||
| -rw-r--r-- | core/java/android/view/contentcapture/ContentCaptureCondition.java | 106 | ||||
| -rw-r--r-- | core/java/android/view/contentcapture/ContentCaptureManager.java | 15 |
6 files changed, 161 insertions, 0 deletions
diff --git a/api/current.txt b/api/current.txt index 08332efb72ed..2a263681d624 100644 --- a/api/current.txt +++ b/api/current.txt @@ -53047,6 +53047,16 @@ package android.view.autofill { package android.view.contentcapture { + public final class ContentCaptureCondition implements android.os.Parcelable { + ctor public ContentCaptureCondition(@NonNull android.content.LocusId, int); + method public int describeContents(); + method public int getFlags(); + method @NonNull public android.content.LocusId getLocusId(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureCondition> CREATOR; + field public static final int FLAG_IS_REGEX = 2; // 0x2 + } + public final class ContentCaptureContext implements android.os.Parcelable { method public int describeContents(); method @NonNull public static android.view.contentcapture.ContentCaptureContext forLocusId(@NonNull String); @@ -53063,6 +53073,7 @@ package android.view.contentcapture { } public final class ContentCaptureManager { + method @Nullable public java.util.Set<android.view.contentcapture.ContentCaptureCondition> getContentCaptureConditions(); method @Nullable public android.content.ComponentName getServiceComponentName(); method public boolean isContentCaptureEnabled(); method public void removeUserData(@NonNull android.view.contentcapture.UserDataRemovalRequest); diff --git a/api/system-current.txt b/api/system-current.txt index 5e1d63f5957f..23cecf4890b5 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6448,6 +6448,7 @@ package android.service.contentcapture { method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId); method public void onDisconnected(); method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest); + method public final void setContentCaptureConditions(@NonNull String, @Nullable java.util.Set<android.view.contentcapture.ContentCaptureCondition>); method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>); field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService"; field public static final String SERVICE_META_DATA = "android.content_capture"; diff --git a/api/test-current.txt b/api/test-current.txt index 9817a9747ff7..6c0b92853673 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -2457,6 +2457,7 @@ package android.service.contentcapture { method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId); method public void onDisconnected(); method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest); + method public final void setContentCaptureConditions(@NonNull String, @Nullable java.util.Set<android.view.contentcapture.ContentCaptureCondition>); method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>); field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService"; field public static final String SERVICE_META_DATA = "android.content_capture"; diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java index fb07abaa34a1..7a35b9e8fa74 100644 --- a/core/java/android/service/contentcapture/ContentCaptureService.java +++ b/core/java/android/service/contentcapture/ContentCaptureService.java @@ -39,6 +39,7 @@ import android.service.autofill.AutofillService; import android.util.ArrayMap; import android.util.Log; import android.util.Slog; +import android.view.contentcapture.ContentCaptureCondition; import android.view.contentcapture.ContentCaptureContext; import android.view.contentcapture.ContentCaptureEvent; import android.view.contentcapture.ContentCaptureManager; @@ -216,6 +217,32 @@ public abstract class ContentCaptureService extends Service { } } + /** + * Explicitly sets the conditions for which content capture should be available by an app. + * + * <p>Typically used to restrict content capture to a few websites on browser apps. Example: + * + * <code> + * ArraySet<ContentCaptureCondition> conditions = new ArraySet<>(1); + * conditions.add(new ContentCaptureCondition(new LocusId("^https://.*\\.example\\.com$"), + * ContentCaptureCondition.FLAG_IS_REGEX)); + * service.setContentCaptureConditions("com.example.browser_app", conditions); + * + * </code> + * + * <p>NOTE: </p> this method doesn't automatically disable content capture for the given + * conditions; it's up to the {@code packageName} implementation to call + * {@link ContentCaptureManager#getContentCaptureConditions()} and disable it accordingly. + * + * @param packageName name of the packages where the restrictions are set. + * @param conditions list of conditions, or {@code null} to reset the conditions for the + * package. + */ + public final void setContentCaptureConditions(@NonNull String packageName, + @Nullable Set<ContentCaptureCondition> conditions) { + // TODO(b/129267994): implement + } + private <T> ArrayList<T> toList(@Nullable Set<T> set) { return set == null ? null : new ArrayList<T>(set); } diff --git a/core/java/android/view/contentcapture/ContentCaptureCondition.java b/core/java/android/view/contentcapture/ContentCaptureCondition.java new file mode 100644 index 000000000000..ed872578d069 --- /dev/null +++ b/core/java/android/view/contentcapture/ContentCaptureCondition.java @@ -0,0 +1,106 @@ +/* + * 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.view.contentcapture; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.content.LocusId; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Defines a condition for when content capture should be allowed. + * + * <p>See {@link ContentCaptureManager#getContentCaptureConditions()} for more. + */ +public final class ContentCaptureCondition implements Parcelable { + + /** + * When set, package should use the {@link LocusId#getId()} as a regular expression. + */ + public static final int FLAG_IS_REGEX = 0x2; + + /** @hide */ + @IntDef(prefix = { "FLAG" }, flag = true, value = { + FLAG_IS_REGEX + }) + @Retention(RetentionPolicy.SOURCE) + @interface Flags {} + + private final @NonNull LocusId mLocusId; + private final @Flags int mFlags; + + /** + * Default constructor. + * + * @param locusId id of the condition, as defined by + * {@link ContentCaptureContext#getLocusId()}. + * @param flags either {@link ContentCaptureCondition#FLAG_IS_REGEX} or {@code 0}. + */ + public ContentCaptureCondition(@NonNull LocusId locusId, @Flags int flags) { + this.mLocusId = Preconditions.checkNotNull(locusId); + this.mFlags = flags; + // TODO(b/129267994): check flags, add test case for null and invalid flags + } + + /** + * Gets the {@code LocusId} per se. + */ + @NonNull + public LocusId getLocusId() { + return mLocusId; + } + + /** + * Gets the flags associates with this condition. + * + * @return either {@link ContentCaptureCondition#FLAG_IS_REGEX} or {@code 0}. + */ + public @Flags int getFlags() { + return mFlags; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel parcel, int flags) { + parcel.writeParcelable(mLocusId, flags); + parcel.writeInt(mFlags); + } + + public static final @NonNull Parcelable.Creator<ContentCaptureCondition> CREATOR = + new Parcelable.Creator<ContentCaptureCondition>() { + + @Override + public ContentCaptureCondition createFromParcel(@NonNull Parcel parcel) { + return new ContentCaptureCondition(parcel.readParcelable(null), + parcel.readInt()); + } + + @Override + public ContentCaptureCondition[] newArray(int size) { + return new ContentCaptureCondition[size]; + } + }; +} diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java index 9e546a80dfd3..817b13011402 100644 --- a/core/java/android/view/contentcapture/ContentCaptureManager.java +++ b/core/java/android/view/contentcapture/ContentCaptureManager.java @@ -43,6 +43,7 @@ import com.android.internal.util.SyncResultReceiver; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Set; /** * TODO(b/123577059): add javadocs / mention it can be null @@ -362,6 +363,20 @@ public final class ContentCaptureManager { } /** + * Gets the list of conditions for when content capture should be allowed. + * + * <p>This method is typically used by web browsers so they don't generate unnecessary content + * capture events for websites the content capture service is not interested on. + * + * @return list of conditions, or {@code null} if the service didn't set any restriction + * (in which case content capture events should always be generated). + */ + @Nullable + public Set<ContentCaptureCondition> getContentCaptureConditions() { + return null; // TODO(b/129267994): implement + } + + /** * Called by apps to explicitly enable or disable content capture. * * <p><b>Note: </b> this call is not persisted accross reboots, so apps should typically call |