Merge "Add flags and options for content protection" into udc-qpr-dev

This commit is contained in:
Nino Jagar
2023-05-28 22:58:45 +00:00
committed by Android (Google) Code Review
5 changed files with 578 additions and 103 deletions

View File

@@ -75,6 +75,20 @@ public final class ContentCaptureOptions implements Parcelable {
*/
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
* 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.
*/
public ContentCaptureOptions(int loggingLevel) {
this(/* lite= */ true, loggingLevel, /* maxBufferSize= */ 0,
/* idleFlushingFrequencyMs= */ 0, /* textChangeFlushingFrequencyMs= */ 0,
/* logHistorySize= */ 0, /* disableFlushForViewTreeAppearing= */ false,
this(
/* lite= */ true,
loggingLevel,
/* maxBufferSize= */ 0,
/* idleFlushingFrequencyMs= */ 0,
/* textChangeFlushingFrequencyMs= */ 0,
/* logHistorySize= */ 0,
/* disableFlushForViewTreeAppearing= */ false,
/* enableReceiver= */ false,
new ContentProtectionOptions(
/* enableReceiver= */ false,
/* bufferSize= */ 0),
/* whitelistedComponents= */ null);
}
/**
* Default constructor.
*/
public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
int textChangeFlushingFrequencyMs, int logHistorySize,
@SuppressLint({"ConcreteCollection", "NullableCollection"})
@Nullable ArraySet<ComponentName> whitelistedComponents) {
this(/* lite= */ false, loggingLevel, maxBufferSize, idleFlushingFrequencyMs,
textChangeFlushingFrequencyMs, logHistorySize,
/** Default constructor. */
public ContentCaptureOptions(
int loggingLevel,
int maxBufferSize,
int idleFlushingFrequencyMs,
int textChangeFlushingFrequencyMs,
int logHistorySize,
@SuppressLint({"ConcreteCollection", "NullableCollection"}) @Nullable
ArraySet<ComponentName> whitelistedComponents) {
this(
/* lite= */ false,
loggingLevel,
maxBufferSize,
idleFlushingFrequencyMs,
textChangeFlushingFrequencyMs,
logHistorySize,
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);
}
/** @hide */
public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
int textChangeFlushingFrequencyMs, int logHistorySize,
public ContentCaptureOptions(
int loggingLevel,
int maxBufferSize,
int idleFlushingFrequencyMs,
int textChangeFlushingFrequencyMs,
int logHistorySize,
boolean disableFlushForViewTreeAppearing,
@SuppressLint({"ConcreteCollection", "NullableCollection"})
@Nullable ArraySet<ComponentName> whitelistedComponents) {
this(/* lite= */ false, loggingLevel, maxBufferSize, idleFlushingFrequencyMs,
textChangeFlushingFrequencyMs, logHistorySize, disableFlushForViewTreeAppearing,
boolean enableReceiver,
@NonNull ContentProtectionOptions contentProtectionOptions,
@SuppressLint({"ConcreteCollection", "NullableCollection"}) @Nullable
ArraySet<ComponentName> whitelistedComponents) {
this(
/* lite= */ false,
loggingLevel,
maxBufferSize,
idleFlushingFrequencyMs,
textChangeFlushingFrequencyMs,
logHistorySize,
disableFlushForViewTreeAppearing,
enableReceiver,
contentProtectionOptions,
whitelistedComponents);
}
/** @hide */
@VisibleForTesting
public ContentCaptureOptions(@Nullable ArraySet<ComponentName> whitelistedComponents) {
this(ContentCaptureManager.LOGGING_LEVEL_VERBOSE,
this(
ContentCaptureManager.LOGGING_LEVEL_VERBOSE,
ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE,
ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS,
ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS,
ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE,
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);
}
private ContentCaptureOptions(boolean lite, int loggingLevel, int maxBufferSize,
int idleFlushingFrequencyMs, int textChangeFlushingFrequencyMs, int logHistorySize,
private ContentCaptureOptions(
boolean lite,
int loggingLevel,
int maxBufferSize,
int idleFlushingFrequencyMs,
int textChangeFlushingFrequencyMs,
int logHistorySize,
boolean disableFlushForViewTreeAppearing,
@Nullable ArraySet<ComponentName> whitelistedComponents) {
boolean enableReceiver,
@NonNull ContentProtectionOptions contentProtectionOptions,
@SuppressLint({"ConcreteCollection", "NullableCollection"}) @Nullable
ArraySet<ComponentName> whitelistedComponents) {
this.lite = lite;
this.loggingLevel = loggingLevel;
this.maxBufferSize = maxBufferSize;
@@ -147,6 +208,8 @@ public final class ContentCaptureOptions implements Parcelable {
this.textChangeFlushingFrequencyMs = textChangeFlushingFrequencyMs;
this.logHistorySize = logHistorySize;
this.disableFlushForViewTreeAppearing = disableFlushForViewTreeAppearing;
this.enableReceiver = enableReceiver;
this.contentProtectionOptions = contentProtectionOptions;
this.whitelistedComponents = whitelistedComponents;
}
@@ -191,12 +254,22 @@ public final class ContentCaptureOptions implements Parcelable {
return "ContentCaptureOptions [loggingLevel=" + loggingLevel + " (lite)]";
}
final StringBuilder string = new StringBuilder("ContentCaptureOptions [");
string.append("loggingLevel=").append(loggingLevel)
.append(", maxBufferSize=").append(maxBufferSize)
.append(", idleFlushingFrequencyMs=").append(idleFlushingFrequencyMs)
.append(", textChangeFlushingFrequencyMs=").append(textChangeFlushingFrequencyMs)
.append(", logHistorySize=").append(logHistorySize)
.append(", disableFlushForViewTreeAppearing=").append(disableFlushForViewTreeAppearing);
string.append("loggingLevel=")
.append(loggingLevel)
.append(", maxBufferSize=")
.append(maxBufferSize)
.append(", idleFlushingFrequencyMs=")
.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) {
string.append(", whitelisted=").append(whitelistedComponents);
}
@@ -210,11 +283,21 @@ public final class ContentCaptureOptions implements Parcelable {
pw.print(", lite");
return;
}
pw.print(", bufferSize="); pw.print(maxBufferSize);
pw.print(", idle="); pw.print(idleFlushingFrequencyMs);
pw.print(", textIdle="); pw.print(textChangeFlushingFrequencyMs);
pw.print(", logSize="); pw.print(logHistorySize);
pw.print(", disableFlushForViewTreeAppearing="); pw.print(disableFlushForViewTreeAppearing);
pw.print(", bufferSize=");
pw.print(maxBufferSize);
pw.print(", idle=");
pw.print(idleFlushingFrequencyMs);
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) {
pw.print(", whitelisted="); pw.print(whitelistedComponents);
}
@@ -236,6 +319,8 @@ public final class ContentCaptureOptions implements Parcelable {
parcel.writeInt(textChangeFlushingFrequencyMs);
parcel.writeInt(logHistorySize);
parcel.writeBoolean(disableFlushForViewTreeAppearing);
parcel.writeBoolean(enableReceiver);
contentProtectionOptions.writeToParcel(parcel);
parcel.writeArraySet(whitelistedComponents);
}
@@ -254,12 +339,22 @@ public final class ContentCaptureOptions implements Parcelable {
final int textChangeFlushingFrequencyMs = parcel.readInt();
final int logHistorySize = parcel.readInt();
final boolean disableFlushForViewTreeAppearing = parcel.readBoolean();
final boolean enableReceiver = parcel.readBoolean();
final ContentProtectionOptions contentProtectionOptions =
ContentProtectionOptions.createFromParcel(parcel);
@SuppressWarnings("unchecked")
final ArraySet<ComponentName> whitelistedComponents =
(ArraySet<ComponentName>) parcel.readArraySet(null);
return new ContentCaptureOptions(loggingLevel, maxBufferSize,
idleFlushingFrequencyMs, textChangeFlushingFrequencyMs, logHistorySize,
disableFlushForViewTreeAppearing, whitelistedComponents);
return new ContentCaptureOptions(
loggingLevel,
maxBufferSize,
idleFlushingFrequencyMs,
textChangeFlushingFrequencyMs,
logHistorySize,
disableFlushForViewTreeAppearing,
enableReceiver,
contentProtectionOptions,
whitelistedComponents);
}
@Override
@@ -267,4 +362,62 @@ public final class ContentCaptureOptions implements Parcelable {
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);
}
}
}

View File

@@ -352,6 +352,30 @@ public final class ContentCaptureManager {
public static final String DEVICE_CONFIG_PROPERTY_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 */
@TestApi
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;
/** @hide */
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();
@@ -425,11 +457,11 @@ public final class ContentCaptureManager {
/** @hide */
static class StrippedContext {
final String mPackageName;
final String mContext;
@NonNull final String mPackageName;
@NonNull final String mContext;
final @UserIdInt int mUserId;
private StrippedContext(Context context) {
private StrippedContext(@NonNull Context context) {
mPackageName = context.getPackageName();
mContext = context.toString();
mUserId = context.getUserId();
@@ -440,6 +472,7 @@ public final class ContentCaptureManager {
return mContext;
}
@NonNull
public String getPackageName() {
return mPackageName;
}

View File

@@ -22,6 +22,7 @@ import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.util.ArraySet;
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
@@ -40,16 +41,29 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ContentCaptureOptionsTest {
private final ComponentName mContextComponent = new ComponentName("marco", "polo");
private final ComponentName mComp1 = new ComponentName("comp", "one");
private final ComponentName mComp2 = new ComponentName("two", "comp");
private static final ComponentName CONTEXT_COMPONENT = new ComponentName("marco", "polo");
private static final ComponentName COMPONENT1 = new ComponentName("comp", "one");
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 ContentCaptureClient mClient;
@Before
public void setExpectation() {
when(mClient.contentCaptureClientGetComponentName()).thenReturn(mContextComponent);
when(mClient.contentCaptureClientGetComponentName()).thenReturn(CONTEXT_COMPONENT);
when(mContext.getContentCaptureClient()).thenReturn(mClient);
}
@@ -67,26 +81,27 @@ public class ContentCaptureOptionsTest {
@Test
public void testIsWhitelisted_notWhitelisted() {
ContentCaptureOptions options = new ContentCaptureOptions(toSet(mComp1, mComp2));
ContentCaptureOptions options = new ContentCaptureOptions(toSet(COMPONENT1, COMPONENT2));
assertThat(options.isWhitelisted(mContext)).isFalse();
}
@Test
public void testIsWhitelisted_whitelisted() {
ContentCaptureOptions options = new ContentCaptureOptions(toSet(mComp1, mContextComponent));
ContentCaptureOptions options =
new ContentCaptureOptions(toSet(COMPONENT1, CONTEXT_COMPONENT));
assertThat(options.isWhitelisted(mContext)).isTrue();
}
@Test
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
assertThat(options.isWhitelisted(invalidContext)).isFalse();
}
@Test
public void testIsWhitelisted_clientWithNullComponentName() {
ContentCaptureOptions options = new ContentCaptureOptions(toSet(mContextComponent));
ContentCaptureOptions options = new ContentCaptureOptions(toSet(CONTEXT_COMPONENT));
ContentCaptureClient client = mock(ContentCaptureClient.class);
Context context = mock(Context.class);
when(context.getContentCaptureClient()).thenReturn(client);
@@ -94,8 +109,69 @@ public class ContentCaptureOptionsTest {
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
private ArraySet<ComponentName> toSet(@Nullable ComponentName... comps) {
private static ArraySet<ComponentName> toSet(@Nullable ComponentName... comps) {
ArraySet<ComponentName> set = new ArraySet<>();
if (comps != null) {
for (int i = 0; i < comps.length; i++) {

View File

@@ -163,13 +163,35 @@ public final class ContentCaptureManagerService extends
private boolean mDisabledByDeviceConfig;
// Device-config settings that are cached and passed back to apps
@GuardedBy("mLock") int mDevCfgLoggingLevel;
@GuardedBy("mLock") int mDevCfgMaxBufferSize;
@GuardedBy("mLock") int mDevCfgIdleFlushingFrequencyMs;
@GuardedBy("mLock") int mDevCfgTextChangeFlushingFrequencyMs;
@GuardedBy("mLock") int mDevCfgLogHistorySize;
@GuardedBy("mLock") int mDevCfgIdleUnbindTimeoutMs;
@GuardedBy("mLock") boolean mDevCfgDisableFlushForViewTreeAppearing;
@GuardedBy("mLock")
int mDevCfgLoggingLevel;
@GuardedBy("mLock")
int mDevCfgMaxBufferSize;
@GuardedBy("mLock")
int mDevCfgIdleFlushingFrequencyMs;
@GuardedBy("mLock")
int mDevCfgTextChangeFlushingFrequencyMs;
@GuardedBy("mLock")
int mDevCfgLogHistorySize;
@GuardedBy("mLock")
int mDevCfgIdleUnbindTimeoutMs;
@GuardedBy("mLock")
boolean mDevCfgDisableFlushForViewTreeAppearing;
@GuardedBy("mLock")
boolean mDevCfgEnableContentProtectionReceiver;
@GuardedBy("mLock")
int mDevCfgContentProtectionAppsBlocklistSize;
@GuardedBy("mLock")
int mDevCfgContentProtectionBufferSize;
private final Executor mDataShareExecutor = Executors.newCachedThreadPool();
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -362,6 +384,11 @@ public final class ContentCaptureManagerService extends
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT:
case ContentCaptureManager
.DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING:
case ContentCaptureManager
.DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER:
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE:
case ContentCaptureManager
.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE:
setFineTuneParamsFromDeviceConfig();
return;
default:
@@ -372,39 +399,78 @@ public final class ContentCaptureManagerService extends
private void setFineTuneParamsFromDeviceConfig() {
synchronized (mLock) {
mDevCfgMaxBufferSize = DeviceConfig.getInt(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE,
ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE);
mDevCfgIdleFlushingFrequencyMs = DeviceConfig.getInt(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY,
ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS);
mDevCfgTextChangeFlushingFrequencyMs = DeviceConfig.getInt(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY,
ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS);
mDevCfgLogHistorySize = DeviceConfig.getInt(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE, 20);
mDevCfgIdleUnbindTimeoutMs = DeviceConfig.getInt(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT,
(int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
mDevCfgDisableFlushForViewTreeAppearing = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager
.DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
false);
mDevCfgMaxBufferSize =
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE,
ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE);
mDevCfgIdleFlushingFrequencyMs =
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY,
ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS);
mDevCfgTextChangeFlushingFrequencyMs =
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager
.DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY,
ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS);
mDevCfgLogHistorySize =
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE,
20);
mDevCfgIdleUnbindTimeoutMs =
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT,
(int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
mDevCfgDisableFlushForViewTreeAppearing =
DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager
.DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
false);
mDevCfgEnableContentProtectionReceiver =
DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager
.DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER,
ContentCaptureManager.DEFAULT_ENABLE_CONTENT_PROTECTION_RECEIVER);
mDevCfgContentProtectionAppsBlocklistSize =
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager
.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE,
ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE);
mDevCfgContentProtectionBufferSize =
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager
.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE,
ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_BUFFER_SIZE);
if (verbose) {
Slog.v(TAG, "setFineTuneParamsFromDeviceConfig(): "
+ "bufferSize=" + mDevCfgMaxBufferSize
+ ", idleFlush=" + mDevCfgIdleFlushingFrequencyMs
+ ", textFluxh=" + mDevCfgTextChangeFlushingFrequencyMs
+ ", logHistory=" + mDevCfgLogHistorySize
+ ", idleUnbindTimeoutMs=" + mDevCfgIdleUnbindTimeoutMs
+ ", disableFlushForViewTreeAppearing="
+ mDevCfgDisableFlushForViewTreeAppearing);
Slog.v(
TAG,
"setFineTuneParamsFromDeviceConfig(): "
+ "bufferSize="
+ mDevCfgMaxBufferSize
+ ", idleFlush="
+ mDevCfgIdleFlushingFrequencyMs
+ ", textFluxh="
+ mDevCfgTextChangeFlushingFrequencyMs
+ ", logHistory="
+ mDevCfgLogHistorySize
+ ", idleUnbindTimeoutMs="
+ mDevCfgIdleUnbindTimeoutMs
+ ", disableFlushForViewTreeAppearing="
+ mDevCfgDisableFlushForViewTreeAppearing
+ ", enableContentProtectionReceiver="
+ mDevCfgEnableContentProtectionReceiver
+ ", contentProtectionAppsBlocklistSize="
+ mDevCfgContentProtectionAppsBlocklistSize
+ ", contentProtectionBufferSize="
+ mDevCfgContentProtectionBufferSize);
}
}
}
@@ -645,21 +711,46 @@ public final class ContentCaptureManagerService extends
final String prefix2 = prefix + " ";
pw.print(prefix); pw.print("Users disabled by Settings: "); pw.println(mDisabledBySettings);
pw.print(prefix); pw.println("DeviceConfig Settings: ");
pw.print(prefix2); pw.print("disabled: "); pw.println(mDisabledByDeviceConfig);
pw.print(prefix2); pw.print("loggingLevel: "); pw.println(mDevCfgLoggingLevel);
pw.print(prefix2); pw.print("maxBufferSize: "); pw.println(mDevCfgMaxBufferSize);
pw.print(prefix2); pw.print("idleFlushingFrequencyMs: ");
pw.print(prefix);
pw.print("Users disabled by Settings: ");
pw.println(mDisabledBySettings);
pw.print(prefix);
pw.println("DeviceConfig Settings: ");
pw.print(prefix2);
pw.print("disabled: ");
pw.println(mDisabledByDeviceConfig);
pw.print(prefix2);
pw.print("loggingLevel: ");
pw.println(mDevCfgLoggingLevel);
pw.print(prefix2);
pw.print("maxBufferSize: ");
pw.println(mDevCfgMaxBufferSize);
pw.print(prefix2);
pw.print("idleFlushingFrequencyMs: ");
pw.println(mDevCfgIdleFlushingFrequencyMs);
pw.print(prefix2); pw.print("textChangeFlushingFrequencyMs: ");
pw.print(prefix2);
pw.print("textChangeFlushingFrequencyMs: ");
pw.println(mDevCfgTextChangeFlushingFrequencyMs);
pw.print(prefix2); pw.print("logHistorySize: "); pw.println(mDevCfgLogHistorySize);
pw.print(prefix2); pw.print("idleUnbindTimeoutMs: ");
pw.print(prefix2);
pw.print("logHistorySize: ");
pw.println(mDevCfgLogHistorySize);
pw.print(prefix2);
pw.print("idleUnbindTimeoutMs: ");
pw.println(mDevCfgIdleUnbindTimeoutMs);
pw.print(prefix2); pw.print("disableFlushForViewTreeAppearing: ");
pw.print(prefix2);
pw.print("disableFlushForViewTreeAppearing: ");
pw.println(mDevCfgDisableFlushForViewTreeAppearing);
pw.print(prefix); pw.println("Global Options:");
pw.print(prefix2);
pw.print("enableContentProtectionReceiver: ");
pw.println(mDevCfgEnableContentProtectionReceiver);
pw.print(prefix2);
pw.print("contentProtectionAppsBlocklistSize: ");
pw.println(mDevCfgContentProtectionAppsBlocklistSize);
pw.print(prefix2);
pw.print("contentProtectionBufferSize: ");
pw.println(mDevCfgContentProtectionBufferSize);
pw.print(prefix);
pw.println("Global Options:");
mGlobalContentCaptureOptions.dump(prefix2, pw);
}
@@ -1019,11 +1110,19 @@ public final class ContentCaptureManagerService extends
}
synchronized (mLock) {
final ContentCaptureOptions options = new ContentCaptureOptions(mDevCfgLoggingLevel,
mDevCfgMaxBufferSize, mDevCfgIdleFlushingFrequencyMs,
mDevCfgTextChangeFlushingFrequencyMs, mDevCfgLogHistorySize,
mDevCfgDisableFlushForViewTreeAppearing,
whitelistedComponents);
final ContentCaptureOptions options =
new ContentCaptureOptions(
mDevCfgLoggingLevel,
mDevCfgMaxBufferSize,
mDevCfgIdleFlushingFrequencyMs,
mDevCfgTextChangeFlushingFrequencyMs,
mDevCfgLogHistorySize,
mDevCfgDisableFlushForViewTreeAppearing,
/* enableReceiver= */ true,
new ContentCaptureOptions.ContentProtectionOptions(
mDevCfgEnableContentProtectionReceiver,
mDevCfgContentProtectionBufferSize),
whitelistedComponents);
if (verbose) Slog.v(TAG, "getOptionsForPackage(" + packageName + "): " + options);
return options;
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.contentcapture;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.content.ContentCaptureOptions;
import android.content.Context;
import android.content.pm.UserInfo;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.server.LocalServices;
import com.android.server.pm.UserManagerInternal;
import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
/**
* Test for {@link ContentCaptureManagerService}.
*
* <p>Run with: {@code atest
* FrameworksServicesTests:com.android.server.contentcapture.ContentCaptureManagerServiceTest}
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
@SuppressWarnings("GuardedBy") // Service not really running, no need to expose locks
public class ContentCaptureManagerServiceTest {
private static final int USER_ID = 1234;
private static final String PACKAGE_NAME = "com.test.package";
private static final Context sContext = ApplicationProvider.getApplicationContext();
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock private UserManagerInternal mMockUserManagerInternal;
private ContentCaptureManagerService mContentCaptureManagerService;
@Before
public void setup() {
when(mMockUserManagerInternal.getUserInfos()).thenReturn(new UserInfo[0]);
LocalServices.removeServiceForTest(UserManagerInternal.class);
LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
mContentCaptureManagerService = new ContentCaptureManagerService(sContext);
}
@Test
public void getOptions_notAllowlisted() {
ContentCaptureOptions actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
USER_ID, PACKAGE_NAME);
assertThat(actual).isNull();
}
@Test
public void getOptions_allowlisted_contentCaptureReceiver() {
mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist(
USER_ID, ImmutableList.of(PACKAGE_NAME), /* components= */ null);
ContentCaptureOptions actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
USER_ID, PACKAGE_NAME);
assertThat(actual).isNotNull();
assertThat(actual.enableReceiver).isTrue();
assertThat(actual.contentProtectionOptions.enableReceiver).isFalse();
assertThat(actual.whitelistedComponents).isNull();
}
@Test
public void getOptions_allowlisted_bothReceivers() {
mContentCaptureManagerService.mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist(
USER_ID, ImmutableList.of(PACKAGE_NAME), /* components= */ null);
ContentCaptureOptions actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
USER_ID, PACKAGE_NAME);
assertThat(actual).isNotNull();
assertThat(actual.enableReceiver).isTrue();
assertThat(actual.contentProtectionOptions.enableReceiver).isTrue();
assertThat(actual.whitelistedComponents).isNull();
}
}