Add content protection buffer to ContentCaptureManager

BYPASS_INCLUSIVE_LANGUAGE_REASON=All issues are in the existing code
which is already in production. New code has no issues.

Bug: 275732576
Test: Added new tests
Change-Id: I676ae25d5245892e995d87e3793da73aff4a5f0e
This commit is contained in:
Nino Jagar
2023-05-29 00:03:44 +00:00
parent 90ca501cdf
commit cc8c1f91f7
2 changed files with 108 additions and 9 deletions

View File

@@ -52,6 +52,7 @@ import android.view.contentcapture.ContentCaptureSession.FlushReason;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.RingBuffer;
import com.android.internal.util.SyncResultReceiver;
import java.io.PrintWriter;
@@ -446,6 +447,9 @@ public final class ContentCaptureManager {
@Nullable // set on-demand by addDumpable()
private Dumper mDumpable;
// Created here in order to live across activity and session changes
@Nullable private final RingBuffer<ContentCaptureEvent> mContentProtectionEventBuffer;
/** @hide */
public interface ContentCaptureClient {
/**
@@ -456,12 +460,15 @@ public final class ContentCaptureManager {
}
/** @hide */
static class StrippedContext {
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public static class StrippedContext {
@NonNull final String mPackageName;
@NonNull final String mContext;
final @UserIdInt int mUserId;
private StrippedContext(@NonNull Context context) {
/** @hide */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
public StrippedContext(@NonNull Context context) {
mPackageName = context.getPackageName();
mContext = context.toString();
mUserId = context.getUserId();
@@ -502,6 +509,16 @@ public final class ContentCaptureManager {
mHandler = Handler.createAsync(Looper.getMainLooper());
mDataShareAdapterResourceManager = new LocalDataShareAdapterResourceManager();
if (mOptions.contentProtectionOptions.enableReceiver
&& mOptions.contentProtectionOptions.bufferSize > 0) {
mContentProtectionEventBuffer =
new RingBuffer(
ContentCaptureEvent.class,
mOptions.contentProtectionOptions.bufferSize);
} else {
mContentProtectionEventBuffer = null;
}
}
/**
@@ -870,6 +887,13 @@ public final class ContentCaptureManager {
activity.addDumpable(mDumpable);
}
/** @hide */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@Nullable
public RingBuffer<ContentCaptureEvent> getContentProtectionEventBuffer() {
return mContentProtectionEventBuffer;
}
// NOTE: ContentCaptureManager cannot implement it directly as it would be exposed as public API
private final class Dumper implements Dumpable {
@Override

View File

@@ -15,14 +15,17 @@
*/
package android.view.contentcapture;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_STARTED;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.testng.Assert.assertThrows;
import android.content.ContentCaptureOptions;
import android.content.Context;
import com.android.internal.util.RingBuffer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -37,9 +40,15 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ContentCaptureManagerTest {
private static final int BUFFER_SIZE = 100;
private static final ContentCaptureOptions EMPTY_OPTIONS = new ContentCaptureOptions(null);
@Mock
private Context mMockContext;
@Mock private IContentCaptureManager mMockContentCaptureManager;
@Test
public void testConstructor_invalidParametersThrowsException() {
assertThrows(NullPointerException.class,
@@ -47,12 +56,66 @@ public class ContentCaptureManagerTest {
null));
}
@Test
public void testConstructor_contentProtection_default_bufferNotCreated() {
ContentCaptureManager manager =
new ContentCaptureManager(mMockContext, mMockContentCaptureManager, EMPTY_OPTIONS);
assertThat(manager.getContentProtectionEventBuffer()).isNull();
}
@Test
public void testConstructor_contentProtection_disabled_bufferNotCreated() {
ContentCaptureOptions options =
createOptions(
new ContentCaptureOptions.ContentProtectionOptions(
/* enableReceiver= */ false, BUFFER_SIZE));
ContentCaptureManager manager =
new ContentCaptureManager(mMockContext, mMockContentCaptureManager, options);
assertThat(manager.getContentProtectionEventBuffer()).isNull();
}
@Test
public void testConstructor_contentProtection_invalidBufferSize_bufferNotCreated() {
ContentCaptureOptions options =
createOptions(
new ContentCaptureOptions.ContentProtectionOptions(
/* enableReceiver= */ true, /* bufferSize= */ 0));
ContentCaptureManager manager =
new ContentCaptureManager(mMockContext, mMockContentCaptureManager, options);
assertThat(manager.getContentProtectionEventBuffer()).isNull();
}
@Test
public void testConstructor_contentProtection_enabled_bufferCreated() {
ContentCaptureOptions options =
createOptions(
new ContentCaptureOptions.ContentProtectionOptions(
/* enableReceiver= */ true, BUFFER_SIZE));
ContentCaptureManager manager =
new ContentCaptureManager(mMockContext, mMockContentCaptureManager, options);
RingBuffer<ContentCaptureEvent> buffer = manager.getContentProtectionEventBuffer();
assertThat(buffer).isNotNull();
ContentCaptureEvent[] expected = new ContentCaptureEvent[BUFFER_SIZE];
int offset = 3;
for (int i = 0; i < BUFFER_SIZE + offset; i++) {
ContentCaptureEvent event = new ContentCaptureEvent(i, TYPE_SESSION_STARTED);
buffer.append(event);
expected[(i + BUFFER_SIZE - offset) % BUFFER_SIZE] = event;
}
assertThat(buffer.toArray()).isEqualTo(expected);
}
@Test
public void testRemoveData_invalidParametersThrowsException() {
final IContentCaptureManager mockService = mock(IContentCaptureManager.class);
final ContentCaptureOptions options = new ContentCaptureOptions(null);
final ContentCaptureManager manager =
new ContentCaptureManager(mMockContext, mockService, options);
new ContentCaptureManager(mMockContext, mMockContentCaptureManager, EMPTY_OPTIONS);
assertThrows(NullPointerException.class, () -> manager.removeData(null));
}
@@ -60,10 +123,8 @@ public class ContentCaptureManagerTest {
@Test
@SuppressWarnings("GuardedBy")
public void testFlushViewTreeAppearingEventDisabled_setAndGet() {
final IContentCaptureManager mockService = mock(IContentCaptureManager.class);
final ContentCaptureOptions options = new ContentCaptureOptions(null);
final ContentCaptureManager manager =
new ContentCaptureManager(mMockContext, mockService, options);
new ContentCaptureManager(mMockContext, mMockContentCaptureManager, EMPTY_OPTIONS);
assertThat(manager.getFlushViewTreeAppearingEventDisabled()).isFalse();
manager.setFlushViewTreeAppearingEventDisabled(true);
@@ -71,4 +132,18 @@ public class ContentCaptureManagerTest {
manager.setFlushViewTreeAppearingEventDisabled(false);
assertThat(manager.getFlushViewTreeAppearingEventDisabled()).isFalse();
}
private ContentCaptureOptions createOptions(
ContentCaptureOptions.ContentProtectionOptions contentProtectionOptions) {
return new ContentCaptureOptions(
/* loggingLevel= */ 0,
/* maxBufferSize= */ 0,
/* idleFlushingFrequencyMs= */ 0,
/* textChangeFlushingFrequencyMs= */ 0,
/* logHistorySize= */ 0,
/* disableFlushForViewTreeAppearing= */ false,
/* enableReceiver= */ true,
contentProtectionOptions,
/* whitelistedComponents= */ null);
}
}