Loading core/java/android/provider/DeviceConfig.java +1 −1 Original line number Diff line number Diff line Loading @@ -623,7 +623,7 @@ public final class DeviceConfig { private static final List<String> PUBLIC_NAMESPACES = Arrays.asList(NAMESPACE_TEXTCLASSIFIER, NAMESPACE_RUNTIME, NAMESPACE_STATSD_JAVA, NAMESPACE_STATSD_JAVA_BOOT, NAMESPACE_SELECTION_TOOLBAR, NAMESPACE_AUTOFILL, NAMESPACE_DEVICE_POLICY_MANAGER); NAMESPACE_DEVICE_POLICY_MANAGER, NAMESPACE_CONTENT_CAPTURE); /** * Privacy related properties definitions. * Loading core/java/android/view/ViewStructure.java +24 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,30 @@ import java.util.List; */ public abstract class ViewStructure { /** * Key used for writing active child view information to the content capture bundle. * * The value stored under this key will be an ordered list of Autofill IDs of child views. * * TODO(b/241498401): Add @TestApi in Android U * @hide */ public static final String EXTRA_ACTIVE_CHILDREN_IDS = "android.view.ViewStructure.extra.ACTIVE_CHILDREN_IDS"; /** * Key used for writing the first active child's position to the content capture bundle. * * When active child view information is provided under the * {@link #EXTRA_ACTIVE_CHILDREN_IDS}, the value stored under this key will be the * 0-based position of the first child view in the list relative to the positions of child views * in the containing View's dataset. * * TODO(b/241498401): Add @TestApi in Android U * @hide */ public static final String EXTRA_FIRST_ACTIVE_POSITION = "android.view.ViewStructure.extra.FIRST_ACTIVE_POSITION"; /** * Set the identifier for this view. * Loading core/java/android/view/contentcapture/ContentCaptureEvent.java +9 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,15 @@ public final class ContentCaptureEvent implements Parcelable { /** * Called when a node has been added to the screen and is visible to the user. * * On API level 33, this event may be re-sent with additional information if a view's children * have changed, e.g. scrolling Views inside of a ListView. This information will be stored in * the extras Bundle associated with the event's ViewNode. Within the Bundle, the * "android.view.ViewStructure.extra.ACTIVE_CHILDREN_IDS" key may be used to get a list of * Autofill IDs of active child views, and the * "android.view.ViewStructure.extra.FIRST_ACTIVE_POSITION" key may be used to get the 0-based * position of the first active child view in the list relative to the positions of child views * in the container View's dataset. * * <p>The metadata of the node is available through {@link #getViewNode()}. */ public static final int TYPE_VIEW_APPEARED = 1; Loading core/java/android/view/contentcapture/ContentCaptureManager.java +9 −0 Original line number Diff line number Diff line Loading @@ -279,6 +279,15 @@ public final class ContentCaptureManager { public static final String DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED = "service_explicitly_enabled"; /** * Device config property used by {@code android.widget.AbsListView} to determine whether or * not it should report the positions of its children to Content Capture. * * @hide */ public static final String DEVICE_CONFIG_PROPERTY_REPORT_LIST_VIEW_CHILDREN = "report_list_view_children"; /** * Maximum number of events that are buffered before sent to the app. * Loading core/java/android/widget/AbsListView.java +141 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.ColorInt; import android.annotation.DrawableRes; import android.annotation.NonNull; import android.annotation.TestApi; import android.app.ActivityThread; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.Intent; Loading @@ -37,6 +38,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.StrictMode; import android.os.Trace; import android.provider.DeviceConfig; import android.text.Editable; import android.text.InputType; import android.text.TextUtils; Loading Loading @@ -65,6 +67,7 @@ import android.view.ViewDebug; import android.view.ViewGroup; import android.view.ViewHierarchyEncoder; import android.view.ViewParent; import android.view.ViewStructure; import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; Loading @@ -73,6 +76,9 @@ import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.view.autofill.AutofillId; import android.view.contentcapture.ContentCaptureManager; import android.view.contentcapture.ContentCaptureSession; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; Loading Loading @@ -633,6 +639,23 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te */ private int mLastScrollState = OnScrollListener.SCROLL_STATE_IDLE; /** * Indicates that reporting positions of child views to content capture is enabled via * DeviceConfig. */ private static boolean sContentCaptureReportingEnabledByDeviceConfig = false; /** * Listens for changes to DeviceConfig properties and updates stored values accordingly. */ private static DeviceConfig.OnPropertiesChangedListener sDeviceConfigChangeListener = null; /** * Indicates that child positions of views should be reported to Content Capture the next time * that active views are refreshed. */ private boolean mReportChildrenToContentCaptureOnNextUpdate = true; /** * Helper object that renders and controls the fast scroll thumb. */ Loading Loading @@ -850,8 +873,44 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te public void adjustListItemSelectionBounds(Rect bounds); } private static class DeviceConfigChangeListener implements DeviceConfig.OnPropertiesChangedListener { @Override public void onPropertiesChanged( @NonNull DeviceConfig.Properties properties) { if (!DeviceConfig.NAMESPACE_CONTENT_CAPTURE.equals(properties.getNamespace())) { return; } for (String key : properties.getKeyset()) { if (!ContentCaptureManager.DEVICE_CONFIG_PROPERTY_REPORT_LIST_VIEW_CHILDREN .equals(key)) { continue; } sContentCaptureReportingEnabledByDeviceConfig = properties.getBoolean(key, false); } } } private static void setupDeviceConfigProperties() { if (sDeviceConfigChangeListener == null) { sContentCaptureReportingEnabledByDeviceConfig = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_CONTENT_CAPTURE, ContentCaptureManager.DEVICE_CONFIG_PROPERTY_REPORT_LIST_VIEW_CHILDREN, false); sDeviceConfigChangeListener = new DeviceConfigChangeListener(); DeviceConfig.addOnPropertiesChangedListener( DeviceConfig.NAMESPACE_CONTENT_CAPTURE, ActivityThread.currentApplication().getMainExecutor(), sDeviceConfigChangeListener); } } public AbsListView(Context context) { super(context); setupDeviceConfigProperties(); mEdgeGlowBottom = new EdgeEffect(context); mEdgeGlowTop = new EdgeEffect(context); initAbsListView(); Loading @@ -874,6 +933,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te public AbsListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); setupDeviceConfigProperties(); mEdgeGlowBottom = new EdgeEffect(context, attrs); mEdgeGlowTop = new EdgeEffect(context, attrs); initAbsListView(); Loading Loading @@ -4699,6 +4759,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mOnScrollListener.onScrollStateChanged(this, newState); } } // When scrolling, we want to report changes in the active children to Content Capture, // so set the flag to report on the next update only when scrolling has stopped or a fling // scroll is performed. if (newState == OnScrollListener.SCROLL_STATE_IDLE || newState == OnScrollListener.SCROLL_STATE_FLING) { mReportChildrenToContentCaptureOnNextUpdate = true; } } /** Loading Loading @@ -6654,10 +6722,77 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mRecycler.mRecyclerListener = listener; } /** * {@inheritDoc} * * This method will initialize the fields of the {@link ViewStructure} * using the base implementation in {@link View}. On API level 33 and higher, it may also * write information about the positions of active views to the extras bundle provided by the * {@link ViewStructure}. * * NOTE: When overriding this method on API level 33, if not calling super() or if changing the * logic for child views, be sure to provide values for the first active child view position and * the list of active child views in the {@link ViewStructure}'s extras {@link Bundle} using the * "android.view.ViewStructure.extra.ACTIVE_CHILDREN_IDS" and * "android.view.ViewStructure.extra.FIRST_ACTIVE_POSITION" keys. * * @param structure {@link ViewStructure} to be filled in with structured view data. * @param flags optional flags. * * @see View#AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS */ @Override public void onProvideContentCaptureStructure( @NonNull ViewStructure structure, int flags) { super.onProvideContentCaptureStructure(structure, flags); if (!sContentCaptureReportingEnabledByDeviceConfig) { return; } Bundle extras = structure.getExtras(); if (extras == null) { Log.wtf(TAG, "Unexpected null extras Bundle in ViewStructure"); return; } int childCount = getChildCount(); ArrayList<AutofillId> idsList = new ArrayList<>(childCount); for (int i = 0; i < childCount; ++i) { View activeView = getChildAt(i); if (activeView == null) { continue; } idsList.add(activeView.getAutofillId()); } extras.putParcelableArrayList(ViewStructure.EXTRA_ACTIVE_CHILDREN_IDS, idsList); extras.putInt(ViewStructure.EXTRA_FIRST_ACTIVE_POSITION, getFirstVisiblePosition()); } private void reportActiveViewsToContentCapture() { if (!sContentCaptureReportingEnabledByDeviceConfig) { return; } ContentCaptureSession session = getContentCaptureSession(); if (session != null) { ViewStructure structure = session.newViewStructure(this); onProvideContentCaptureStructure(structure, /* flags= */ 0); session.notifyViewAppeared(structure); } } class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver { @Override public void onChanged() { super.onChanged(); mReportChildrenToContentCaptureOnNextUpdate = true; if (mFastScroll != null) { mFastScroll.onSectionsChanged(); } Loading @@ -6666,6 +6801,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te @Override public void onInvalidated() { super.onInvalidated(); mReportChildrenToContentCaptureOnNextUpdate = true; if (mFastScroll != null) { mFastScroll.onSectionsChanged(); } Loading Loading @@ -6984,6 +7120,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te lp.scrappedFromPosition = firstActivePosition + i; } } if (mReportChildrenToContentCaptureOnNextUpdate && childCount > 0) { AbsListView.this.reportActiveViewsToContentCapture(); mReportChildrenToContentCaptureOnNextUpdate = false; } } /** Loading Loading
core/java/android/provider/DeviceConfig.java +1 −1 Original line number Diff line number Diff line Loading @@ -623,7 +623,7 @@ public final class DeviceConfig { private static final List<String> PUBLIC_NAMESPACES = Arrays.asList(NAMESPACE_TEXTCLASSIFIER, NAMESPACE_RUNTIME, NAMESPACE_STATSD_JAVA, NAMESPACE_STATSD_JAVA_BOOT, NAMESPACE_SELECTION_TOOLBAR, NAMESPACE_AUTOFILL, NAMESPACE_DEVICE_POLICY_MANAGER); NAMESPACE_DEVICE_POLICY_MANAGER, NAMESPACE_CONTENT_CAPTURE); /** * Privacy related properties definitions. * Loading
core/java/android/view/ViewStructure.java +24 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,30 @@ import java.util.List; */ public abstract class ViewStructure { /** * Key used for writing active child view information to the content capture bundle. * * The value stored under this key will be an ordered list of Autofill IDs of child views. * * TODO(b/241498401): Add @TestApi in Android U * @hide */ public static final String EXTRA_ACTIVE_CHILDREN_IDS = "android.view.ViewStructure.extra.ACTIVE_CHILDREN_IDS"; /** * Key used for writing the first active child's position to the content capture bundle. * * When active child view information is provided under the * {@link #EXTRA_ACTIVE_CHILDREN_IDS}, the value stored under this key will be the * 0-based position of the first child view in the list relative to the positions of child views * in the containing View's dataset. * * TODO(b/241498401): Add @TestApi in Android U * @hide */ public static final String EXTRA_FIRST_ACTIVE_POSITION = "android.view.ViewStructure.extra.FIRST_ACTIVE_POSITION"; /** * Set the identifier for this view. * Loading
core/java/android/view/contentcapture/ContentCaptureEvent.java +9 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,15 @@ public final class ContentCaptureEvent implements Parcelable { /** * Called when a node has been added to the screen and is visible to the user. * * On API level 33, this event may be re-sent with additional information if a view's children * have changed, e.g. scrolling Views inside of a ListView. This information will be stored in * the extras Bundle associated with the event's ViewNode. Within the Bundle, the * "android.view.ViewStructure.extra.ACTIVE_CHILDREN_IDS" key may be used to get a list of * Autofill IDs of active child views, and the * "android.view.ViewStructure.extra.FIRST_ACTIVE_POSITION" key may be used to get the 0-based * position of the first active child view in the list relative to the positions of child views * in the container View's dataset. * * <p>The metadata of the node is available through {@link #getViewNode()}. */ public static final int TYPE_VIEW_APPEARED = 1; Loading
core/java/android/view/contentcapture/ContentCaptureManager.java +9 −0 Original line number Diff line number Diff line Loading @@ -279,6 +279,15 @@ public final class ContentCaptureManager { public static final String DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED = "service_explicitly_enabled"; /** * Device config property used by {@code android.widget.AbsListView} to determine whether or * not it should report the positions of its children to Content Capture. * * @hide */ public static final String DEVICE_CONFIG_PROPERTY_REPORT_LIST_VIEW_CHILDREN = "report_list_view_children"; /** * Maximum number of events that are buffered before sent to the app. * Loading
core/java/android/widget/AbsListView.java +141 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.ColorInt; import android.annotation.DrawableRes; import android.annotation.NonNull; import android.annotation.TestApi; import android.app.ActivityThread; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.Intent; Loading @@ -37,6 +38,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.StrictMode; import android.os.Trace; import android.provider.DeviceConfig; import android.text.Editable; import android.text.InputType; import android.text.TextUtils; Loading Loading @@ -65,6 +67,7 @@ import android.view.ViewDebug; import android.view.ViewGroup; import android.view.ViewHierarchyEncoder; import android.view.ViewParent; import android.view.ViewStructure; import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; Loading @@ -73,6 +76,9 @@ import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.view.autofill.AutofillId; import android.view.contentcapture.ContentCaptureManager; import android.view.contentcapture.ContentCaptureSession; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; Loading Loading @@ -633,6 +639,23 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te */ private int mLastScrollState = OnScrollListener.SCROLL_STATE_IDLE; /** * Indicates that reporting positions of child views to content capture is enabled via * DeviceConfig. */ private static boolean sContentCaptureReportingEnabledByDeviceConfig = false; /** * Listens for changes to DeviceConfig properties and updates stored values accordingly. */ private static DeviceConfig.OnPropertiesChangedListener sDeviceConfigChangeListener = null; /** * Indicates that child positions of views should be reported to Content Capture the next time * that active views are refreshed. */ private boolean mReportChildrenToContentCaptureOnNextUpdate = true; /** * Helper object that renders and controls the fast scroll thumb. */ Loading Loading @@ -850,8 +873,44 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te public void adjustListItemSelectionBounds(Rect bounds); } private static class DeviceConfigChangeListener implements DeviceConfig.OnPropertiesChangedListener { @Override public void onPropertiesChanged( @NonNull DeviceConfig.Properties properties) { if (!DeviceConfig.NAMESPACE_CONTENT_CAPTURE.equals(properties.getNamespace())) { return; } for (String key : properties.getKeyset()) { if (!ContentCaptureManager.DEVICE_CONFIG_PROPERTY_REPORT_LIST_VIEW_CHILDREN .equals(key)) { continue; } sContentCaptureReportingEnabledByDeviceConfig = properties.getBoolean(key, false); } } } private static void setupDeviceConfigProperties() { if (sDeviceConfigChangeListener == null) { sContentCaptureReportingEnabledByDeviceConfig = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_CONTENT_CAPTURE, ContentCaptureManager.DEVICE_CONFIG_PROPERTY_REPORT_LIST_VIEW_CHILDREN, false); sDeviceConfigChangeListener = new DeviceConfigChangeListener(); DeviceConfig.addOnPropertiesChangedListener( DeviceConfig.NAMESPACE_CONTENT_CAPTURE, ActivityThread.currentApplication().getMainExecutor(), sDeviceConfigChangeListener); } } public AbsListView(Context context) { super(context); setupDeviceConfigProperties(); mEdgeGlowBottom = new EdgeEffect(context); mEdgeGlowTop = new EdgeEffect(context); initAbsListView(); Loading @@ -874,6 +933,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te public AbsListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); setupDeviceConfigProperties(); mEdgeGlowBottom = new EdgeEffect(context, attrs); mEdgeGlowTop = new EdgeEffect(context, attrs); initAbsListView(); Loading Loading @@ -4699,6 +4759,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mOnScrollListener.onScrollStateChanged(this, newState); } } // When scrolling, we want to report changes in the active children to Content Capture, // so set the flag to report on the next update only when scrolling has stopped or a fling // scroll is performed. if (newState == OnScrollListener.SCROLL_STATE_IDLE || newState == OnScrollListener.SCROLL_STATE_FLING) { mReportChildrenToContentCaptureOnNextUpdate = true; } } /** Loading Loading @@ -6654,10 +6722,77 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mRecycler.mRecyclerListener = listener; } /** * {@inheritDoc} * * This method will initialize the fields of the {@link ViewStructure} * using the base implementation in {@link View}. On API level 33 and higher, it may also * write information about the positions of active views to the extras bundle provided by the * {@link ViewStructure}. * * NOTE: When overriding this method on API level 33, if not calling super() or if changing the * logic for child views, be sure to provide values for the first active child view position and * the list of active child views in the {@link ViewStructure}'s extras {@link Bundle} using the * "android.view.ViewStructure.extra.ACTIVE_CHILDREN_IDS" and * "android.view.ViewStructure.extra.FIRST_ACTIVE_POSITION" keys. * * @param structure {@link ViewStructure} to be filled in with structured view data. * @param flags optional flags. * * @see View#AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS */ @Override public void onProvideContentCaptureStructure( @NonNull ViewStructure structure, int flags) { super.onProvideContentCaptureStructure(structure, flags); if (!sContentCaptureReportingEnabledByDeviceConfig) { return; } Bundle extras = structure.getExtras(); if (extras == null) { Log.wtf(TAG, "Unexpected null extras Bundle in ViewStructure"); return; } int childCount = getChildCount(); ArrayList<AutofillId> idsList = new ArrayList<>(childCount); for (int i = 0; i < childCount; ++i) { View activeView = getChildAt(i); if (activeView == null) { continue; } idsList.add(activeView.getAutofillId()); } extras.putParcelableArrayList(ViewStructure.EXTRA_ACTIVE_CHILDREN_IDS, idsList); extras.putInt(ViewStructure.EXTRA_FIRST_ACTIVE_POSITION, getFirstVisiblePosition()); } private void reportActiveViewsToContentCapture() { if (!sContentCaptureReportingEnabledByDeviceConfig) { return; } ContentCaptureSession session = getContentCaptureSession(); if (session != null) { ViewStructure structure = session.newViewStructure(this); onProvideContentCaptureStructure(structure, /* flags= */ 0); session.notifyViewAppeared(structure); } } class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver { @Override public void onChanged() { super.onChanged(); mReportChildrenToContentCaptureOnNextUpdate = true; if (mFastScroll != null) { mFastScroll.onSectionsChanged(); } Loading @@ -6666,6 +6801,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te @Override public void onInvalidated() { super.onInvalidated(); mReportChildrenToContentCaptureOnNextUpdate = true; if (mFastScroll != null) { mFastScroll.onSectionsChanged(); } Loading Loading @@ -6984,6 +7120,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te lp.scrappedFromPosition = firstActivePosition + i; } } if (mReportChildrenToContentCaptureOnNextUpdate && childCount > 0) { AbsListView.this.reportActiveViewsToContentCapture(); mReportChildrenToContentCaptureOnNextUpdate = false; } } /** Loading