Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f8b80eb8 authored by Nino Jagar's avatar Nino Jagar Committed by Automerger Merge Worker
Browse files

Merge "Add flags and options for content protection" into udc-qpr-dev am: 6b5e167b

parents 9f9361d5 6b5e167b
Loading
Loading
Loading
Loading
+189 −36
Original line number Original line Diff line number Diff line
@@ -75,6 +75,20 @@ public final class ContentCaptureOptions implements Parcelable {
     */
     */
    public final boolean disableFlushForViewTreeAppearing;
    public final boolean disableFlushForViewTreeAppearing;


    /**
     * Is the content capture receiver enabled.
     *
     * @hide
     */
    public final boolean enableReceiver;

    /**
     * Options for the content protection flow.
     *
     * @hide
     */
    @NonNull public final ContentProtectionOptions contentProtectionOptions;

    /**
    /**
     * List of activities explicitly allowlisted for content capture (or {@code null} if allowlisted
     * List of activities explicitly allowlisted for content capture (or {@code null} if allowlisted
     * for all acitivites in the package).
     * for all acitivites in the package).
@@ -94,52 +108,99 @@ public final class ContentCaptureOptions implements Parcelable {
     * for contexts belonging to the content capture service app.
     * for contexts belonging to the content capture service app.
     */
     */
    public ContentCaptureOptions(int loggingLevel) {
    public ContentCaptureOptions(int loggingLevel) {
        this(/* lite= */ true, loggingLevel, /* maxBufferSize= */ 0,
        this(
                /* idleFlushingFrequencyMs= */ 0, /* textChangeFlushingFrequencyMs= */ 0,
                /* lite= */ true,
                /* logHistorySize= */ 0, /* disableFlushForViewTreeAppearing= */ false,
                loggingLevel,
                /* maxBufferSize= */ 0,
                /* idleFlushingFrequencyMs= */ 0,
                /* textChangeFlushingFrequencyMs= */ 0,
                /* logHistorySize= */ 0,
                /* disableFlushForViewTreeAppearing= */ false,
                /* enableReceiver= */ false,
                new ContentProtectionOptions(
                        /* enableReceiver= */ false,
                        /* bufferSize= */ 0),
                /* whitelistedComponents= */ null);
                /* whitelistedComponents= */ null);
    }
    }


    /**
    /** Default constructor. */
     * Default constructor.
    public ContentCaptureOptions(
     */
            int loggingLevel,
    public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
            int maxBufferSize,
            int textChangeFlushingFrequencyMs, int logHistorySize,
            int idleFlushingFrequencyMs,
            @SuppressLint({"ConcreteCollection", "NullableCollection"})
            int textChangeFlushingFrequencyMs,
            @Nullable ArraySet<ComponentName> whitelistedComponents) {
            int logHistorySize,
        this(/* lite= */ false, loggingLevel, maxBufferSize, idleFlushingFrequencyMs,
            @SuppressLint({"ConcreteCollection", "NullableCollection"}) @Nullable
                textChangeFlushingFrequencyMs, logHistorySize,
                    ArraySet<ComponentName> whitelistedComponents) {
        this(
                /* lite= */ false,
                loggingLevel,
                maxBufferSize,
                idleFlushingFrequencyMs,
                textChangeFlushingFrequencyMs,
                logHistorySize,
                ContentCaptureManager.DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
                ContentCaptureManager.DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
                ContentCaptureManager.DEFAULT_ENABLE_CONTENT_CAPTURE_RECEIVER,
                new ContentProtectionOptions(
                        ContentCaptureManager.DEFAULT_ENABLE_CONTENT_PROTECTION_RECEIVER,
                        ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_BUFFER_SIZE),
                whitelistedComponents);
                whitelistedComponents);
    }
    }


    /** @hide */
    /** @hide */
    public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
    public ContentCaptureOptions(
            int textChangeFlushingFrequencyMs, int logHistorySize,
            int loggingLevel,
            int maxBufferSize,
            int idleFlushingFrequencyMs,
            int textChangeFlushingFrequencyMs,
            int logHistorySize,
            boolean disableFlushForViewTreeAppearing,
            boolean disableFlushForViewTreeAppearing,
            @SuppressLint({"ConcreteCollection", "NullableCollection"})
            boolean enableReceiver,
            @Nullable ArraySet<ComponentName> whitelistedComponents) {
            @NonNull ContentProtectionOptions contentProtectionOptions,
        this(/* lite= */ false, loggingLevel, maxBufferSize, idleFlushingFrequencyMs,
            @SuppressLint({"ConcreteCollection", "NullableCollection"}) @Nullable
                textChangeFlushingFrequencyMs, logHistorySize, disableFlushForViewTreeAppearing,
                    ArraySet<ComponentName> whitelistedComponents) {
        this(
                /* lite= */ false,
                loggingLevel,
                maxBufferSize,
                idleFlushingFrequencyMs,
                textChangeFlushingFrequencyMs,
                logHistorySize,
                disableFlushForViewTreeAppearing,
                enableReceiver,
                contentProtectionOptions,
                whitelistedComponents);
                whitelistedComponents);
    }
    }


    /** @hide */
    /** @hide */
    @VisibleForTesting
    @VisibleForTesting
    public ContentCaptureOptions(@Nullable ArraySet<ComponentName> whitelistedComponents) {
    public ContentCaptureOptions(@Nullable ArraySet<ComponentName> whitelistedComponents) {
        this(ContentCaptureManager.LOGGING_LEVEL_VERBOSE,
        this(
                ContentCaptureManager.LOGGING_LEVEL_VERBOSE,
                ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE,
                ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE,
                ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS,
                ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS,
                ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS,
                ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS,
                ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE,
                ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE,
                ContentCaptureManager.DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
                ContentCaptureManager.DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
                ContentCaptureManager.DEFAULT_ENABLE_CONTENT_CAPTURE_RECEIVER,
                new ContentProtectionOptions(
                        ContentCaptureManager.DEFAULT_ENABLE_CONTENT_PROTECTION_RECEIVER,
                        ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_BUFFER_SIZE),
                whitelistedComponents);
                whitelistedComponents);
    }
    }


    private ContentCaptureOptions(boolean lite, int loggingLevel, int maxBufferSize,
    private ContentCaptureOptions(
            int idleFlushingFrequencyMs, int textChangeFlushingFrequencyMs, int logHistorySize,
            boolean lite,
            int loggingLevel,
            int maxBufferSize,
            int idleFlushingFrequencyMs,
            int textChangeFlushingFrequencyMs,
            int logHistorySize,
            boolean disableFlushForViewTreeAppearing,
            boolean disableFlushForViewTreeAppearing,
            @Nullable ArraySet<ComponentName> whitelistedComponents) {
            boolean enableReceiver,
            @NonNull ContentProtectionOptions contentProtectionOptions,
            @SuppressLint({"ConcreteCollection", "NullableCollection"}) @Nullable
                    ArraySet<ComponentName> whitelistedComponents) {
        this.lite = lite;
        this.lite = lite;
        this.loggingLevel = loggingLevel;
        this.loggingLevel = loggingLevel;
        this.maxBufferSize = maxBufferSize;
        this.maxBufferSize = maxBufferSize;
@@ -147,6 +208,8 @@ public final class ContentCaptureOptions implements Parcelable {
        this.textChangeFlushingFrequencyMs = textChangeFlushingFrequencyMs;
        this.textChangeFlushingFrequencyMs = textChangeFlushingFrequencyMs;
        this.logHistorySize = logHistorySize;
        this.logHistorySize = logHistorySize;
        this.disableFlushForViewTreeAppearing = disableFlushForViewTreeAppearing;
        this.disableFlushForViewTreeAppearing = disableFlushForViewTreeAppearing;
        this.enableReceiver = enableReceiver;
        this.contentProtectionOptions = contentProtectionOptions;
        this.whitelistedComponents = whitelistedComponents;
        this.whitelistedComponents = whitelistedComponents;
    }
    }


@@ -191,12 +254,22 @@ public final class ContentCaptureOptions implements Parcelable {
            return "ContentCaptureOptions [loggingLevel=" + loggingLevel + " (lite)]";
            return "ContentCaptureOptions [loggingLevel=" + loggingLevel + " (lite)]";
        }
        }
        final StringBuilder string = new StringBuilder("ContentCaptureOptions [");
        final StringBuilder string = new StringBuilder("ContentCaptureOptions [");
        string.append("loggingLevel=").append(loggingLevel)
        string.append("loggingLevel=")
            .append(", maxBufferSize=").append(maxBufferSize)
                .append(loggingLevel)
            .append(", idleFlushingFrequencyMs=").append(idleFlushingFrequencyMs)
                .append(", maxBufferSize=")
            .append(", textChangeFlushingFrequencyMs=").append(textChangeFlushingFrequencyMs)
                .append(maxBufferSize)
            .append(", logHistorySize=").append(logHistorySize)
                .append(", idleFlushingFrequencyMs=")
            .append(", disableFlushForViewTreeAppearing=").append(disableFlushForViewTreeAppearing);
                .append(idleFlushingFrequencyMs)
                .append(", textChangeFlushingFrequencyMs=")
                .append(textChangeFlushingFrequencyMs)
                .append(", logHistorySize=")
                .append(logHistorySize)
                .append(", disableFlushForViewTreeAppearing=")
                .append(disableFlushForViewTreeAppearing)
                .append(", enableReceiver=")
                .append(enableReceiver)
                .append(", contentProtectionOptions=")
                .append(contentProtectionOptions);
        if (whitelistedComponents != null) {
        if (whitelistedComponents != null) {
            string.append(", whitelisted=").append(whitelistedComponents);
            string.append(", whitelisted=").append(whitelistedComponents);
        }
        }
@@ -210,11 +283,21 @@ public final class ContentCaptureOptions implements Parcelable {
            pw.print(", lite");
            pw.print(", lite");
            return;
            return;
        }
        }
        pw.print(", bufferSize="); pw.print(maxBufferSize);
        pw.print(", bufferSize=");
        pw.print(", idle="); pw.print(idleFlushingFrequencyMs);
        pw.print(maxBufferSize);
        pw.print(", textIdle="); pw.print(textChangeFlushingFrequencyMs);
        pw.print(", idle=");
        pw.print(", logSize="); pw.print(logHistorySize);
        pw.print(idleFlushingFrequencyMs);
        pw.print(", disableFlushForViewTreeAppearing="); pw.print(disableFlushForViewTreeAppearing);
        pw.print(", textIdle=");
        pw.print(textChangeFlushingFrequencyMs);
        pw.print(", logSize=");
        pw.print(logHistorySize);
        pw.print(", disableFlushForViewTreeAppearing=");
        pw.print(disableFlushForViewTreeAppearing);
        pw.print(", enableReceiver=");
        pw.print(enableReceiver);
        pw.print(", contentProtectionOptions=[");
        contentProtectionOptions.dumpShort(pw);
        pw.print("]");
        if (whitelistedComponents != null) {
        if (whitelistedComponents != null) {
            pw.print(", whitelisted="); pw.print(whitelistedComponents);
            pw.print(", whitelisted="); pw.print(whitelistedComponents);
        }
        }
@@ -236,6 +319,8 @@ public final class ContentCaptureOptions implements Parcelable {
        parcel.writeInt(textChangeFlushingFrequencyMs);
        parcel.writeInt(textChangeFlushingFrequencyMs);
        parcel.writeInt(logHistorySize);
        parcel.writeInt(logHistorySize);
        parcel.writeBoolean(disableFlushForViewTreeAppearing);
        parcel.writeBoolean(disableFlushForViewTreeAppearing);
        parcel.writeBoolean(enableReceiver);
        contentProtectionOptions.writeToParcel(parcel);
        parcel.writeArraySet(whitelistedComponents);
        parcel.writeArraySet(whitelistedComponents);
    }
    }


@@ -254,12 +339,22 @@ public final class ContentCaptureOptions implements Parcelable {
                    final int textChangeFlushingFrequencyMs = parcel.readInt();
                    final int textChangeFlushingFrequencyMs = parcel.readInt();
                    final int logHistorySize = parcel.readInt();
                    final int logHistorySize = parcel.readInt();
                    final boolean disableFlushForViewTreeAppearing = parcel.readBoolean();
                    final boolean disableFlushForViewTreeAppearing = parcel.readBoolean();
                    final boolean enableReceiver = parcel.readBoolean();
                    final ContentProtectionOptions contentProtectionOptions =
                            ContentProtectionOptions.createFromParcel(parcel);
                    @SuppressWarnings("unchecked")
                    @SuppressWarnings("unchecked")
                    final ArraySet<ComponentName> whitelistedComponents =
                    final ArraySet<ComponentName> whitelistedComponents =
                            (ArraySet<ComponentName>) parcel.readArraySet(null);
                            (ArraySet<ComponentName>) parcel.readArraySet(null);
                    return new ContentCaptureOptions(loggingLevel, maxBufferSize,
                    return new ContentCaptureOptions(
                            idleFlushingFrequencyMs, textChangeFlushingFrequencyMs, logHistorySize,
                            loggingLevel,
                            disableFlushForViewTreeAppearing, whitelistedComponents);
                            maxBufferSize,
                            idleFlushingFrequencyMs,
                            textChangeFlushingFrequencyMs,
                            logHistorySize,
                            disableFlushForViewTreeAppearing,
                            enableReceiver,
                            contentProtectionOptions,
                            whitelistedComponents);
                }
                }


                @Override
                @Override
@@ -267,4 +362,62 @@ public final class ContentCaptureOptions implements Parcelable {
                    return new ContentCaptureOptions[size];
                    return new ContentCaptureOptions[size];
                }
                }
    };
    };

    /**
     * Content protection options for a given package.
     *
     * <p>Does not implement {@code Parcelable} since it is an inner class without a matching AIDL.
     *
     * @hide
     */
    public static class ContentProtectionOptions {

        /**
         * Is the content protection receiver enabled.
         *
         * @hide
         */
        public final boolean enableReceiver;

        /**
         * Size of the in-memory ring buffer for the content protection flow.
         *
         * @hide
         */
        public final int bufferSize;

        public ContentProtectionOptions(boolean enableReceiver, int bufferSize) {
            this.enableReceiver = enableReceiver;
            this.bufferSize = bufferSize;
        }

        @Override
        public String toString() {
            StringBuilder stringBuilder = new StringBuilder("ContentProtectionOptions [");
            stringBuilder
                    .append("enableReceiver=")
                    .append(enableReceiver)
                    .append(", bufferSize=")
                    .append(bufferSize);
            return stringBuilder.append(']').toString();
        }

        private void dumpShort(@NonNull PrintWriter pw) {
            pw.print("enableReceiver=");
            pw.print(enableReceiver);
            pw.print(", bufferSize=");
            pw.print(bufferSize);
        }

        private void writeToParcel(Parcel parcel) {
            parcel.writeBoolean(enableReceiver);
            parcel.writeInt(bufferSize);
        }

        private static ContentProtectionOptions createFromParcel(Parcel parcel) {
            boolean enableReceiver = parcel.readBoolean();
            int bufferSize = parcel.readInt();
            return new ContentProtectionOptions(enableReceiver, bufferSize);
        }
    }
}
}
+36 −3
Original line number Original line Diff line number Diff line
@@ -352,6 +352,30 @@ public final class ContentCaptureManager {
    public static final String DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING =
    public static final String DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING =
            "disable_flush_for_view_tree_appearing";
            "disable_flush_for_view_tree_appearing";


    /**
     * Enables the content protection receiver.
     *
     * @hide
     */
    public static final String DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER =
            "enable_content_protection_receiver";

    /**
     * Sets the size of the app blocklist for the content protection flow.
     *
     * @hide
     */
    public static final String DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE =
            "content_protection_apps_blocklist_size";

    /**
     * Sets the size of the in-memory ring buffer for the content protection flow.
     *
     * @hide
     */
    public static final String DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE =
            "content_protection_buffer_size";

    /** @hide */
    /** @hide */
    @TestApi
    @TestApi
    public static final int LOGGING_LEVEL_OFF = 0;
    public static final int LOGGING_LEVEL_OFF = 0;
@@ -384,6 +408,14 @@ public final class ContentCaptureManager {
    public static final int DEFAULT_LOG_HISTORY_SIZE = 10;
    public static final int DEFAULT_LOG_HISTORY_SIZE = 10;
    /** @hide */
    /** @hide */
    public static final boolean DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING = false;
    public static final boolean DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING = false;
    /** @hide */
    public static final boolean DEFAULT_ENABLE_CONTENT_CAPTURE_RECEIVER = true;
    /** @hide */
    public static final boolean DEFAULT_ENABLE_CONTENT_PROTECTION_RECEIVER = false;
    /** @hide */
    public static final int DEFAULT_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE = 1000;
    /** @hide */
    public static final int DEFAULT_CONTENT_PROTECTION_BUFFER_SIZE = 150;


    private final Object mLock = new Object();
    private final Object mLock = new Object();


@@ -425,11 +457,11 @@ public final class ContentCaptureManager {


    /** @hide */
    /** @hide */
    static class StrippedContext {
    static class StrippedContext {
        final String mPackageName;
        @NonNull final String mPackageName;
        final String mContext;
        @NonNull final String mContext;
        final @UserIdInt int mUserId;
        final @UserIdInt int mUserId;


        private StrippedContext(Context context) {
        private StrippedContext(@NonNull Context context) {
            mPackageName = context.getPackageName();
            mPackageName = context.getPackageName();
            mContext = context.toString();
            mContext = context.toString();
            mUserId = context.getUserId();
            mUserId = context.getUserId();
@@ -440,6 +472,7 @@ public final class ContentCaptureManager {
            return mContext;
            return mContext;
        }
        }


        @NonNull
        public String getPackageName() {
        public String getPackageName() {
            return mPackageName;
            return mPackageName;
        }
        }
+85 −9
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@ import static org.mockito.Mockito.when;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.os.Parcel;
import android.util.ArraySet;
import android.util.ArraySet;
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;


@@ -40,16 +41,29 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
@RunWith(MockitoJUnitRunner.class)
public class ContentCaptureOptionsTest {
public class ContentCaptureOptionsTest {


    private final ComponentName mContextComponent = new ComponentName("marco", "polo");
    private static final ComponentName CONTEXT_COMPONENT = new ComponentName("marco", "polo");
    private final ComponentName mComp1 = new ComponentName("comp", "one");
    private static final ComponentName COMPONENT1 = new ComponentName("comp", "one");
    private final ComponentName mComp2 = new ComponentName("two", "comp");
    private static final ComponentName COMPONENT2 = new ComponentName("two", "comp");
    private static final ContentCaptureOptions CONTENT_CAPTURE_OPTIONS =
            new ContentCaptureOptions(
                    /* loggingLevel= */ 1000,
                    /* maxBufferSize= */ 1001,
                    /* idleFlushingFrequencyMs= */ 1002,
                    /* textChangeFlushingFrequencyMs= */ 1003,
                    /* logHistorySize= */ 1004,
                    /* disableFlushForViewTreeAppearing= */ true,
                    /* enableReceiver= */ false,
                    new ContentCaptureOptions.ContentProtectionOptions(
                            /* enableReceiver= */ true,
                            /* bufferSize= */ 2001),
                    /* whitelistedComponents= */ toSet(COMPONENT1, COMPONENT2));


    @Mock private Context mContext;
    @Mock private Context mContext;
    @Mock private ContentCaptureClient mClient;
    @Mock private ContentCaptureClient mClient;


    @Before
    @Before
    public void setExpectation() {
    public void setExpectation() {
        when(mClient.contentCaptureClientGetComponentName()).thenReturn(mContextComponent);
        when(mClient.contentCaptureClientGetComponentName()).thenReturn(CONTEXT_COMPONENT);
        when(mContext.getContentCaptureClient()).thenReturn(mClient);
        when(mContext.getContentCaptureClient()).thenReturn(mClient);
    }
    }


@@ -67,26 +81,27 @@ public class ContentCaptureOptionsTest {


    @Test
    @Test
    public void testIsWhitelisted_notWhitelisted() {
    public void testIsWhitelisted_notWhitelisted() {
        ContentCaptureOptions options = new ContentCaptureOptions(toSet(mComp1, mComp2));
        ContentCaptureOptions options = new ContentCaptureOptions(toSet(COMPONENT1, COMPONENT2));
        assertThat(options.isWhitelisted(mContext)).isFalse();
        assertThat(options.isWhitelisted(mContext)).isFalse();
    }
    }


    @Test
    @Test
    public void testIsWhitelisted_whitelisted() {
    public void testIsWhitelisted_whitelisted() {
        ContentCaptureOptions options = new ContentCaptureOptions(toSet(mComp1, mContextComponent));
        ContentCaptureOptions options =
                new ContentCaptureOptions(toSet(COMPONENT1, CONTEXT_COMPONENT));
        assertThat(options.isWhitelisted(mContext)).isTrue();
        assertThat(options.isWhitelisted(mContext)).isTrue();
    }
    }


    @Test
    @Test
    public void testIsWhitelisted_invalidContext() {
    public void testIsWhitelisted_invalidContext() {
        ContentCaptureOptions options = new ContentCaptureOptions(toSet(mContextComponent));
        ContentCaptureOptions options = new ContentCaptureOptions(toSet(CONTEXT_COMPONENT));
        Context invalidContext = mock(Context.class); // has no client
        Context invalidContext = mock(Context.class); // has no client
        assertThat(options.isWhitelisted(invalidContext)).isFalse();
        assertThat(options.isWhitelisted(invalidContext)).isFalse();
    }
    }


    @Test
    @Test
    public void testIsWhitelisted_clientWithNullComponentName() {
    public void testIsWhitelisted_clientWithNullComponentName() {
        ContentCaptureOptions options = new ContentCaptureOptions(toSet(mContextComponent));
        ContentCaptureOptions options = new ContentCaptureOptions(toSet(CONTEXT_COMPONENT));
        ContentCaptureClient client = mock(ContentCaptureClient.class);
        ContentCaptureClient client = mock(ContentCaptureClient.class);
        Context context = mock(Context.class);
        Context context = mock(Context.class);
        when(context.getContentCaptureClient()).thenReturn(client);
        when(context.getContentCaptureClient()).thenReturn(client);
@@ -94,8 +109,69 @@ public class ContentCaptureOptionsTest {
        assertThat(options.isWhitelisted(context)).isFalse();
        assertThat(options.isWhitelisted(context)).isFalse();
    }
    }


    @Test
    public void testToString() {
        String actual = CONTENT_CAPTURE_OPTIONS.toString();

        String expected =
                new StringBuilder("ContentCaptureOptions [")
                        .append("loggingLevel=")
                        .append(CONTENT_CAPTURE_OPTIONS.loggingLevel)
                        .append(", maxBufferSize=")
                        .append(CONTENT_CAPTURE_OPTIONS.maxBufferSize)
                        .append(", idleFlushingFrequencyMs=")
                        .append(CONTENT_CAPTURE_OPTIONS.idleFlushingFrequencyMs)
                        .append(", textChangeFlushingFrequencyMs=")
                        .append(CONTENT_CAPTURE_OPTIONS.textChangeFlushingFrequencyMs)
                        .append(", logHistorySize=")
                        .append(CONTENT_CAPTURE_OPTIONS.logHistorySize)
                        .append(", disableFlushForViewTreeAppearing=")
                        .append(CONTENT_CAPTURE_OPTIONS.disableFlushForViewTreeAppearing)
                        .append(", enableReceiver=")
                        .append(CONTENT_CAPTURE_OPTIONS.enableReceiver)
                        .append(", contentProtectionOptions=ContentProtectionOptions [")
                        .append("enableReceiver=")
                        .append(CONTENT_CAPTURE_OPTIONS.contentProtectionOptions.enableReceiver)
                        .append(", bufferSize=")
                        .append(CONTENT_CAPTURE_OPTIONS.contentProtectionOptions.bufferSize)
                        .append("], whitelisted=")
                        .append(CONTENT_CAPTURE_OPTIONS.whitelistedComponents)
                        .append(']')
                        .toString();
        assertThat(actual).isEqualTo(expected);
    }

    @Test
    public void testParcelSerializationDeserialization() {
        Parcel parcel = Parcel.obtain();
        CONTENT_CAPTURE_OPTIONS.writeToParcel(parcel, /* flags= */ 0);
        parcel.setDataPosition(0);

        ContentCaptureOptions actual = ContentCaptureOptions.CREATOR.createFromParcel(parcel);
        parcel.recycle();

        assertThat(actual).isNotNull();
        assertThat(actual.loggingLevel).isEqualTo(CONTENT_CAPTURE_OPTIONS.loggingLevel);
        assertThat(actual.maxBufferSize).isEqualTo(CONTENT_CAPTURE_OPTIONS.maxBufferSize);
        assertThat(actual.idleFlushingFrequencyMs)
                .isEqualTo(CONTENT_CAPTURE_OPTIONS.idleFlushingFrequencyMs);
        assertThat(actual.textChangeFlushingFrequencyMs)
                .isEqualTo(CONTENT_CAPTURE_OPTIONS.textChangeFlushingFrequencyMs);
        assertThat(actual.logHistorySize).isEqualTo(CONTENT_CAPTURE_OPTIONS.logHistorySize);
        assertThat(actual.disableFlushForViewTreeAppearing)
                .isEqualTo(CONTENT_CAPTURE_OPTIONS.disableFlushForViewTreeAppearing);
        assertThat(actual.enableReceiver).isEqualTo(CONTENT_CAPTURE_OPTIONS.enableReceiver);
        assertThat(actual.contentProtectionOptions).isNotNull();
        assertThat(actual.contentProtectionOptions.enableReceiver)
                .isEqualTo(CONTENT_CAPTURE_OPTIONS.contentProtectionOptions.enableReceiver);
        assertThat(actual.contentProtectionOptions.bufferSize)
                .isEqualTo(CONTENT_CAPTURE_OPTIONS.contentProtectionOptions.bufferSize);
        assertThat(actual.whitelistedComponents)
                .containsExactlyElementsIn(CONTENT_CAPTURE_OPTIONS.whitelistedComponents);
    }

    @NonNull
    @NonNull
    private ArraySet<ComponentName> toSet(@Nullable ComponentName... comps) {
    private static ArraySet<ComponentName> toSet(@Nullable ComponentName... comps) {
        ArraySet<ComponentName> set = new ArraySet<>();
        ArraySet<ComponentName> set = new ArraySet<>();
        if (comps != null) {
        if (comps != null) {
            for (int i = 0; i < comps.length; i++) {
            for (int i = 0; i < comps.length; i++) {
+154 −55

File changed.

Preview size limit exceeded, changes collapsed.

+114 −0

File added.

Preview size limit exceeded, changes collapsed.