diff options
8 files changed, 70 insertions, 0 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 1a34781f0102..9ec1c3aaa99e 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -57123,6 +57123,7 @@ package android.view.contentcapture { method public void close(); method @NonNull public final android.view.contentcapture.ContentCaptureSession createContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext); method public final void destroy(); + method @FlaggedApi("android.view.contentcapture.flags.ccapi_baklava_enabled") public void flush(); method @Nullable public final android.view.contentcapture.ContentCaptureContext getContentCaptureContext(); method @NonNull public final android.view.contentcapture.ContentCaptureSessionId getContentCaptureSessionId(); method @NonNull public android.view.autofill.AutofillId newAutofillId(@NonNull android.view.autofill.AutofillId, long); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index d7010ae54072..3fba18550417 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -19249,6 +19249,7 @@ package android.view.contentcapture { method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureEvent> CREATOR; field public static final int TYPE_CONTEXT_UPDATED = 6; // 0x6 + field @FlaggedApi("android.view.contentcapture.flags.ccapi_baklava_enabled") public static final int TYPE_SESSION_FLUSH = 11; // 0xb field public static final int TYPE_SESSION_PAUSED = 8; // 0x8 field public static final int TYPE_SESSION_RESUMED = 7; // 0x7 field public static final int TYPE_VIEW_APPEARED = 1; // 0x1 diff --git a/core/java/android/view/contentcapture/ChildContentCaptureSession.java b/core/java/android/view/contentcapture/ChildContentCaptureSession.java index 70c899f1efc7..8baa55f8e377 100644 --- a/core/java/android/view/contentcapture/ChildContentCaptureSession.java +++ b/core/java/android/view/contentcapture/ChildContentCaptureSession.java @@ -142,6 +142,11 @@ final class ChildContentCaptureSession extends ContentCaptureSession { } @Override + void internalNotifySessionFlushEvent(int sessionId) { + getMainCaptureSession().internalNotifySessionFlushEvent(sessionId); + } + + @Override boolean isContentCaptureEnabled() { return getMainCaptureSession().isContentCaptureEnabled(); } diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java index db4ac5de0b49..efd39163c3b8 100644 --- a/core/java/android/view/contentcapture/ContentCaptureEvent.java +++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java @@ -18,7 +18,9 @@ package android.view.contentcapture; import static android.view.contentcapture.ContentCaptureHelper.getSanitizedString; import static android.view.contentcapture.ContentCaptureManager.DEBUG; import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID; +import static android.view.contentcapture.flags.Flags.FLAG_CCAPI_BAKLAVA_ENABLED; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -137,6 +139,12 @@ public final class ContentCaptureEvent implements Parcelable { */ public static final int TYPE_WINDOW_BOUNDS_CHANGED = 10; + /** + * Called to flush a semantics meaningful view changes status to Intelligence Service. + */ + @FlaggedApi(FLAG_CCAPI_BAKLAVA_ENABLED) + public static final int TYPE_SESSION_FLUSH = 11; + /** @hide */ @IntDef(prefix = { "TYPE_" }, value = { TYPE_VIEW_APPEARED, @@ -149,6 +157,7 @@ public final class ContentCaptureEvent implements Parcelable { TYPE_SESSION_RESUMED, TYPE_VIEW_INSETS_CHANGED, TYPE_WINDOW_BOUNDS_CHANGED, + TYPE_SESSION_FLUSH, }) @Retention(RetentionPolicy.SOURCE) public @interface EventType{} @@ -697,6 +706,8 @@ public final class ContentCaptureEvent implements Parcelable { return "VIEW_INSETS_CHANGED"; case TYPE_WINDOW_BOUNDS_CHANGED: return "TYPE_WINDOW_BOUNDS_CHANGED"; + case TYPE_SESSION_FLUSH: + return "TYPE_SESSION_FLUSH"; default: return "UKNOWN_TYPE: " + type; } diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java index 0ca36ba28e3a..9aeec20ec9b7 100644 --- a/core/java/android/view/contentcapture/ContentCaptureSession.java +++ b/core/java/android/view/contentcapture/ContentCaptureSession.java @@ -19,8 +19,10 @@ import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE; import static android.view.contentcapture.ContentCaptureHelper.sDebug; import static android.view.contentcapture.ContentCaptureHelper.sVerbose; import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID; +import static android.view.contentcapture.flags.Flags.FLAG_CCAPI_BAKLAVA_ENABLED; import android.annotation.CallSuper; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -548,6 +550,35 @@ public abstract class ContentCaptureSession implements AutoCloseable { abstract void internalNotifyViewInsetsChanged(int sessionId, @NonNull Insets viewInsets); + /** + * Flushes an internal buffer of UI events and signals System Intelligence (SI) that a + * semantically meaningful state has been reached. SI uses this signal to potentially + * rebuild the view hierarchy and understand the current state of the UI. + * + * <p>UI events are often batched together for performance reasons. A semantic batch + * represents a series of events that, when applied sequentially, result in a + * meaningful and complete UI state. + * + * <p>It is crucial to call {@code flush()} after completing a semantic batch to ensure + * SI can accurately reconstruct the view hierarchy. + * + * <p><b>Premature Flushing:</b> Calling {@code flush()} within a semantic batch may + * lead to SI failing to rebuild the view hierarchy correctly. This could manifest as + * incorrect ordering of sibling nodes. + * + * <p><b>Delayed Flushing:</b> While not immediately flushing after a semantic batch is + * generally safe, it's recommended to do so as soon as possible. In the worst-case + * scenario where a {@code flush()} is never called, SI will attempt to process the + * events after a short delay based on view appearance and disappearance events. + */ + @FlaggedApi(FLAG_CCAPI_BAKLAVA_ENABLED) + public void flush() { + internalNotifySessionFlushEvent(mId); + } + + /** @hide */ + abstract void internalNotifySessionFlushEvent(int sessionId); + /** @hide */ public void notifyViewTreeEvent(boolean started) { internalNotifyViewTreeEvent(mId, started); diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java index eb827dd5258d..2fb78c038ca2 100644 --- a/core/java/android/view/contentcapture/MainContentCaptureSession.java +++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java @@ -17,6 +17,7 @@ package android.view.contentcapture; import static android.view.contentcapture.ContentCaptureEvent.TYPE_CONTEXT_UPDATED; import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_FINISHED; +import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_FLUSH; import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_PAUSED; import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_RESUMED; import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_STARTED; @@ -623,6 +624,8 @@ public final class MainContentCaptureSession extends ContentCaptureSession { @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) @Override public void flush(@FlushReason int reason) { + // TODO: b/380381249 renaming the internal APIs to prevent confusions between this and the + // public API. runOnContentCaptureThread(() -> flushImpl(reason)); } @@ -890,6 +893,12 @@ public final class MainContentCaptureSession extends ContentCaptureSession { enqueueEvent(event); } + @Override + void internalNotifySessionFlushEvent(int sessionId) { + final ContentCaptureEvent event = new ContentCaptureEvent(sessionId, TYPE_SESSION_FLUSH); + enqueueEvent(event, FORCE_FLUSH); + } + private List<ContentCaptureEvent> clearBufferEvents() { final ArrayList<ContentCaptureEvent> bufferEvents = new ArrayList<>(); ContentCaptureEvent event; diff --git a/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig b/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig index 416a877d87ab..20d193ea2351 100644 --- a/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig +++ b/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig @@ -7,3 +7,10 @@ flag { description: "Feature flag for running content capture tasks on background thread" bug: "309411951" } + +flag { + name: "ccapi_baklava_enabled" + namespace: "machine_learning" + description: "Feature flag for baklava content capture API" + bug: "309411951" +} diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java index 5a4561d7c6ea..f87b6994900f 100644 --- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java +++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java @@ -266,6 +266,11 @@ public class ContentCaptureSessionTest { } @Override + void internalNotifySessionFlushEvent(int sessionId) { + throw new UnsupportedOperationException("should not have been called"); + } + + @Override void internalNotifyChildSessionStarted(int parentSessionId, int childSessionId, @NonNull ContentCaptureContext clientContext) { throw new UnsupportedOperationException("should not have been called"); |