diff --git a/core/api/system-current.txt b/core/api/system-current.txt index dd9031a8af8e8..1872280d58508 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -14457,6 +14457,7 @@ package android.view.contentcapture { public final class ContentCaptureEvent implements android.os.Parcelable { method public int describeContents(); + method @Nullable public android.graphics.Rect getBounds(); method @Nullable public android.view.contentcapture.ContentCaptureContext getContentCaptureContext(); method public long getEventTime(); method @Nullable public android.view.autofill.AutofillId getId(); @@ -14476,6 +14477,7 @@ package android.view.contentcapture { field public static final int TYPE_VIEW_TEXT_CHANGED = 3; // 0x3 field public static final int TYPE_VIEW_TREE_APPEARED = 5; // 0x5 field public static final int TYPE_VIEW_TREE_APPEARING = 4; // 0x4 + field public static final int TYPE_WINDOW_BOUNDS_CHANGED = 10; // 0xa } public final class ContentCaptureManager { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 4c36fc939c34c..b54b251de80f1 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -4273,6 +4273,14 @@ public final class ViewRootImpl implements ViewParent, try { if (!isContentCaptureEnabled()) return; + // Initial dispatch of window bounds to content capture + if (mAttachInfo.mContentCaptureManager != null) { + MainContentCaptureSession session = + mAttachInfo.mContentCaptureManager.getMainContentCaptureSession(); + session.notifyWindowBoundsChanged(session.getId(), + getConfiguration().windowConfiguration.getBounds()); + } + // Content capture is a go! rootView.dispatchInitialProvideContentCaptureStructure(); } finally { @@ -7804,6 +7812,14 @@ public final class ViewRootImpl implements ViewParent, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber, mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets, mTempControls, mSurfaceSize); + + if (mAttachInfo.mContentCaptureManager != null) { + MainContentCaptureSession mainSession = mAttachInfo.mContentCaptureManager + .getMainContentCaptureSession(); + mainSession.notifyWindowBoundsChanged(mainSession.getId(), + getConfiguration().windowConfiguration.getBounds()); + } + mPendingBackDropFrame.set(mTmpFrames.backdropFrame); if (mSurfaceControl.isValid()) { if (!useBLAST()) { diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java index ce6d034c585ec..4b2d3a97bed2d 100644 --- a/core/java/android/view/contentcapture/ContentCaptureEvent.java +++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java @@ -24,6 +24,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.graphics.Insets; +import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; import android.text.Selection; @@ -122,6 +123,12 @@ public final class ContentCaptureEvent implements Parcelable { */ public static final int TYPE_VIEW_INSETS_CHANGED = 9; + /** + * Called before {@link #TYPE_VIEW_TREE_APPEARING}, or after the size of the window containing + * the views changed. + */ + public static final int TYPE_WINDOW_BOUNDS_CHANGED = 10; + /** @hide */ @IntDef(prefix = { "TYPE_" }, value = { TYPE_VIEW_APPEARED, @@ -132,7 +139,8 @@ public final class ContentCaptureEvent implements Parcelable { TYPE_CONTEXT_UPDATED, TYPE_SESSION_PAUSED, TYPE_SESSION_RESUMED, - TYPE_VIEW_INSETS_CHANGED + TYPE_VIEW_INSETS_CHANGED, + TYPE_WINDOW_BOUNDS_CHANGED, }) @Retention(RetentionPolicy.SOURCE) public @interface EventType{} @@ -150,6 +158,7 @@ public final class ContentCaptureEvent implements Parcelable { private int mParentSessionId = NO_SESSION_ID; private @Nullable ContentCaptureContext mClientContext; private @Nullable Insets mInsets; + private @Nullable Rect mBounds; private int mComposingStart = MAX_INVALID_VALUE; private int mComposingEnd = MAX_INVALID_VALUE; @@ -346,6 +355,13 @@ public final class ContentCaptureEvent implements Parcelable { return this; } + /** @hide */ + @NonNull + public ContentCaptureEvent setBounds(@NonNull Rect bounds) { + mBounds = bounds; + return this; + } + /** * Gets the type of the event. * @@ -418,6 +434,16 @@ public final class ContentCaptureEvent implements Parcelable { return mInsets; } + /** + * Gets the {@link Rect} bounds of the window associated with the event. Valid bounds will only + * be returned if the type of the event is {@link #TYPE_WINDOW_BOUNDS_CHANGED}, otherwise they + * will be null. + */ + @Nullable + public Rect getBounds() { + return mBounds; + } + /** * Merges event of the same type, either {@link #TYPE_VIEW_TEXT_CHANGED} * or {@link #TYPE_VIEW_DISAPPEARED}. @@ -489,6 +515,9 @@ public final class ContentCaptureEvent implements Parcelable { if (mInsets != null) { pw.print(", insets="); pw.println(mInsets); } + if (mBounds != null) { + pw.print(", bounds="); pw.println(mBounds); + } if (mComposingStart > MAX_INVALID_VALUE) { pw.print(", composing("); pw.print(mComposingStart); pw.print(", "); pw.print(mComposingEnd); pw.print(")"); @@ -533,6 +562,9 @@ public final class ContentCaptureEvent implements Parcelable { if (mInsets != null) { string.append(", insets=").append(mInsets); } + if (mBounds != null) { + string.append(", bounds=").append(mBounds); + } if (mComposingStart > MAX_INVALID_VALUE) { string.append(", composing=[") .append(mComposingStart).append(",").append(mComposingEnd).append("]"); @@ -568,6 +600,9 @@ public final class ContentCaptureEvent implements Parcelable { if (mType == TYPE_VIEW_INSETS_CHANGED) { parcel.writeParcelable(mInsets, flags); } + if (mType == TYPE_WINDOW_BOUNDS_CHANGED) { + parcel.writeParcelable(mBounds, flags); + } if (mType == TYPE_VIEW_TEXT_CHANGED) { parcel.writeInt(mComposingStart); parcel.writeInt(mComposingEnd); @@ -608,6 +643,9 @@ public final class ContentCaptureEvent implements Parcelable { if (type == TYPE_VIEW_INSETS_CHANGED) { event.setInsets(parcel.readParcelable(null)); } + if (type == TYPE_WINDOW_BOUNDS_CHANGED) { + event.setBounds(parcel.readParcelable(null)); + } if (type == TYPE_VIEW_TEXT_CHANGED) { event.setComposingIndex(parcel.readInt(), parcel.readInt()); event.restoreComposingSpan(); @@ -649,6 +687,8 @@ public final class ContentCaptureEvent implements Parcelable { return "CONTEXT_UPDATED"; case TYPE_VIEW_INSETS_CHANGED: return "VIEW_INSETS_CHANGED"; + case TYPE_WINDOW_BOUNDS_CHANGED: + return "TYPE_WINDOW_BOUNDS_CHANGED"; default: return "UKNOWN_TYPE: " + type; } diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java index 4cf553207b6eb..98ef4e7ae6fae 100644 --- a/core/java/android/view/contentcapture/MainContentCaptureSession.java +++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java @@ -26,6 +26,7 @@ import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_INSETS_C import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED; import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_TREE_APPEARED; import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_TREE_APPEARING; +import static android.view.contentcapture.ContentCaptureEvent.TYPE_WINDOW_BOUNDS_CHANGED; import static android.view.contentcapture.ContentCaptureHelper.getSanitizedString; import static android.view.contentcapture.ContentCaptureHelper.sDebug; import static android.view.contentcapture.ContentCaptureHelper.sVerbose; @@ -38,6 +39,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.ParceledListSlice; import android.graphics.Insets; +import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -776,6 +778,14 @@ public final class MainContentCaptureSession extends ContentCaptureSession { .setClientContext(context), FORCE_FLUSH)); } + /** public because is also used by ViewRootImpl */ + public void notifyWindowBoundsChanged(int sessionId, @NonNull Rect bounds) { + mHandler.post(() -> sendEvent( + new ContentCaptureEvent(sessionId, TYPE_WINDOW_BOUNDS_CHANGED) + .setBounds(bounds) + )); + } + @Override void dump(@NonNull String prefix, @NonNull PrintWriter pw) { super.dump(prefix, pw);