Fixed content capture whitelist for specific activities.
Test: manual verification (it cannot be fully verified using the current CTS setup) Test: atest CtsContentCaptureServiceTestCases:android.contentcaptureservice.cts.WhitelistTest Test: atest FrameworksCoreTests:android.content.ContentCaptureOptionsTest Test: atest CtsContentCaptureServiceTestCases # sanity check Test: m update-api Fixes: 130573023 Merged-In: I2c76a01bd98c4154c4c59099f1368232d2dba80d Change-Id: I2c76a01bd98c4154c4c59099f1368232d2dba80d
This commit is contained in:
@@ -127,6 +127,7 @@ import android.view.autofill.AutofillPopupWindow;
|
||||
import android.view.autofill.IAutofillWindowPresenter;
|
||||
import android.view.contentcapture.ContentCaptureContext;
|
||||
import android.view.contentcapture.ContentCaptureManager;
|
||||
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.Toolbar;
|
||||
@@ -723,7 +724,7 @@ public class Activity extends ContextThemeWrapper
|
||||
Window.Callback, KeyEvent.Callback,
|
||||
OnCreateContextMenuListener, ComponentCallbacks2,
|
||||
Window.OnWindowDismissedCallback, WindowControllerCallback,
|
||||
AutofillManager.AutofillClient {
|
||||
AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {
|
||||
private static final String TAG = "Activity";
|
||||
private static final boolean DEBUG_LIFECYCLE = false;
|
||||
|
||||
@@ -1125,6 +1126,12 @@ public class Activity extends ContextThemeWrapper
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public final ContentCaptureClient getContentCaptureClient() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an {@link Application.ActivityLifecycleCallbacks} instance that receives
|
||||
* lifecycle callbacks for only this Activity.
|
||||
@@ -6511,6 +6518,12 @@ public class Activity extends ContextThemeWrapper
|
||||
return getComponentName();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public final ComponentName contentCaptureClientGetComponentName() {
|
||||
return getComponentName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a {@link SharedPreferences} object for accessing preferences
|
||||
* that are private to this activity. This simply calls the underlying
|
||||
|
||||
@@ -1143,7 +1143,7 @@ final class SystemServiceRegistry {
|
||||
Context outerContext = ctx.getOuterContext();
|
||||
ContentCaptureOptions options = outerContext.getContentCaptureOptions();
|
||||
// Options is null when the service didn't whitelist the activity or package
|
||||
if (options != null) {
|
||||
if (options != null && (options.lite || options.isWhitelisted(outerContext))) {
|
||||
IBinder b = ServiceManager
|
||||
.getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
|
||||
IContentCaptureManager service = IContentCaptureManager.Stub.asInterface(b);
|
||||
|
||||
@@ -24,6 +24,9 @@ import android.os.Parcelable;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.view.contentcapture.ContentCaptureManager;
|
||||
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
@@ -78,12 +81,19 @@ public final class ContentCaptureOptions implements Parcelable {
|
||||
*/
|
||||
public final boolean lite;
|
||||
|
||||
/**
|
||||
* Constructor for "lite" objects that are just used to enable a {@link ContentCaptureManager}
|
||||
* 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, /* whitelistedComponents= */ null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
|
||||
int textChangeFlushingFrequencyMs, int logHistorySize,
|
||||
@Nullable ArraySet<ComponentName> whitelistedComponents) {
|
||||
@@ -91,6 +101,16 @@ public final class ContentCaptureOptions implements Parcelable {
|
||||
textChangeFlushingFrequencyMs, logHistorySize, whitelistedComponents);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting
|
||||
public ContentCaptureOptions(@Nullable ArraySet<ComponentName> whitelistedComponents) {
|
||||
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, whitelistedComponents);
|
||||
}
|
||||
|
||||
private ContentCaptureOptions(boolean lite, int loggingLevel, int maxBufferSize,
|
||||
int idleFlushingFrequencyMs, int textChangeFlushingFrequencyMs, int logHistorySize,
|
||||
@Nullable ArraySet<ComponentName> whitelistedComponents) {
|
||||
@@ -103,10 +123,6 @@ public final class ContentCaptureOptions implements Parcelable {
|
||||
this.whitelistedComponents = whitelistedComponents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public static ContentCaptureOptions forWhitelistingItself() {
|
||||
final ActivityThread at = ActivityThread.currentActivityThread();
|
||||
if (at == null) {
|
||||
@@ -120,19 +136,27 @@ public final class ContentCaptureOptions implements Parcelable {
|
||||
throw new SecurityException("Thou shall not pass!");
|
||||
}
|
||||
|
||||
final ContentCaptureOptions options = new ContentCaptureOptions(
|
||||
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,
|
||||
/* whitelistedComponents= */ null);
|
||||
final ContentCaptureOptions options =
|
||||
new ContentCaptureOptions(/* whitelistedComponents= */ null);
|
||||
// Always log, as it's used by test only
|
||||
Log.i(TAG, "forWhitelistingItself(" + packageName + "): " + options);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting
|
||||
public boolean isWhitelisted(@NonNull Context context) {
|
||||
if (whitelistedComponents == null) return true; // whole package is whitelisted
|
||||
final ContentCaptureClient client = context.getContentCaptureClient();
|
||||
if (client == null) {
|
||||
// Shouldn't happen, but it doesn't hurt to check...
|
||||
Log.w(TAG, "isWhitelisted(): no ContentCaptureClient on " + context);
|
||||
return false;
|
||||
}
|
||||
return whitelistedComponents.contains(client.contentCaptureClientGetComponentName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (lite) {
|
||||
|
||||
@@ -70,6 +70,7 @@ import android.view.View;
|
||||
import android.view.ViewDebug;
|
||||
import android.view.WindowManager;
|
||||
import android.view.autofill.AutofillManager.AutofillClient;
|
||||
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
|
||||
import android.view.textclassifier.TextClassificationManager;
|
||||
|
||||
import java.io.File;
|
||||
@@ -5411,6 +5412,14 @@ public abstract class Context {
|
||||
public void setAutofillClient(@SuppressWarnings("unused") AutofillClient client) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Nullable
|
||||
public ContentCaptureClient getContentCaptureClient() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -342,6 +342,15 @@ public final class ContentCaptureManager {
|
||||
@GuardedBy("mLock")
|
||||
private MainContentCaptureSession mMainSession;
|
||||
|
||||
/** @hide */
|
||||
public interface ContentCaptureClient {
|
||||
/**
|
||||
* Gets the component name of the client.
|
||||
*/
|
||||
@NonNull
|
||||
ComponentName contentCaptureClientGetComponentName();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public ContentCaptureManager(@NonNull Context context,
|
||||
@NonNull IContentCaptureManager service, @NonNull ContentCaptureOptions options) {
|
||||
|
||||
@@ -35,11 +35,13 @@ import java.util.List;
|
||||
*
|
||||
* <p>This class is thread safe.
|
||||
*/
|
||||
// TODO: add unit tests
|
||||
public class GlobalWhitelistState {
|
||||
|
||||
// Uses full-name to avoid collision with service-provided mLock
|
||||
protected final Object mGlobalWhitelistStateLock = new Object();
|
||||
|
||||
// TODO: should not be exposed directly
|
||||
@Nullable
|
||||
@GuardedBy("mGlobalWhitelistStateLock")
|
||||
protected SparseArray<WhitelistHelper> mWhitelisterHelpers;
|
||||
|
||||
@@ -98,9 +98,9 @@ public final class WhitelistHelper {
|
||||
@Nullable List<ComponentName> components) {
|
||||
final ArraySet<String> packageNamesSet = packageNames == null ? null
|
||||
: new ArraySet<>(packageNames);
|
||||
final ArraySet<ComponentName> componentssSet = components == null ? null
|
||||
final ArraySet<ComponentName> componentsSet = components == null ? null
|
||||
: new ArraySet<>(components);
|
||||
setWhitelist(packageNamesSet, componentssSet);
|
||||
setWhitelist(packageNamesSet, componentsSet);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,7 +170,7 @@ public final class WhitelistHelper {
|
||||
|
||||
pw.print("["); pw.print(components.valueAt(0));
|
||||
for (int j = 1; j < components.size(); j++) {
|
||||
pw.print(", "); pw.print(components.valueAt(i));
|
||||
pw.print(", "); pw.print(components.valueAt(j));
|
||||
}
|
||||
pw.println("]");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 android.content;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.util.ArraySet;
|
||||
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
/**
|
||||
* Unit test for {@link ContentCaptureOptions}.
|
||||
*
|
||||
* <p>To run it:
|
||||
* {@code atest FrameworksCoreTests:android.content.ContentCaptureOptionsTest}
|
||||
*/
|
||||
@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");
|
||||
|
||||
@Mock private Context mContext;
|
||||
@Mock private ContentCaptureClient mClient;
|
||||
|
||||
@Before
|
||||
public void setExpectation() {
|
||||
when(mClient.contentCaptureClientGetComponentName()).thenReturn(mContextComponent);
|
||||
when(mContext.getContentCaptureClient()).thenReturn(mClient);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsWhitelisted_nullWhitelistedComponents() {
|
||||
ContentCaptureOptions options = new ContentCaptureOptions(null);
|
||||
assertThat(options.isWhitelisted(mContext)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsWhitelisted_emptyWhitelistedComponents() {
|
||||
ContentCaptureOptions options = new ContentCaptureOptions(toSet((ComponentName) null));
|
||||
assertThat(options.isWhitelisted(mContext)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsWhitelisted_notWhitelisted() {
|
||||
ContentCaptureOptions options = new ContentCaptureOptions(toSet(mComp1, mComp2));
|
||||
assertThat(options.isWhitelisted(mContext)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsWhitelisted_whitelisted() {
|
||||
ContentCaptureOptions options = new ContentCaptureOptions(toSet(mComp1, mContextComponent));
|
||||
assertThat(options.isWhitelisted(mContext)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsWhitelisted_invalidContext() {
|
||||
ContentCaptureOptions options = new ContentCaptureOptions(toSet(mContextComponent));
|
||||
Context invalidContext = mock(Context.class); // has no client
|
||||
assertThat(options.isWhitelisted(invalidContext)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsWhitelisted_clientWithNullComponentName() {
|
||||
ContentCaptureOptions options = new ContentCaptureOptions(toSet(mContextComponent));
|
||||
ContentCaptureClient client = mock(ContentCaptureClient.class);
|
||||
Context context = mock(Context.class);
|
||||
when(context.getContentCaptureClient()).thenReturn(client);
|
||||
|
||||
assertThat(options.isWhitelisted(context)).isFalse();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private ArraySet<ComponentName> toSet(@Nullable ComponentName... comps) {
|
||||
ArraySet<ComponentName> set = new ArraySet<>();
|
||||
if (comps != null) {
|
||||
for (int i = 0; i < comps.length; i++) {
|
||||
set.add(comps[i]);
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
}
|
||||
@@ -781,36 +781,46 @@ public final class ContentCaptureManagerService extends
|
||||
@GuardedBy("mGlobalWhitelistStateLock")
|
||||
public ContentCaptureOptions getOptions(@UserIdInt int userId,
|
||||
@NonNull String packageName) {
|
||||
boolean packageWhitelisted;
|
||||
ArraySet<ComponentName> whitelistedComponents = null;
|
||||
synchronized (mGlobalWhitelistStateLock) {
|
||||
if (!isWhitelisted(userId, packageName)) {
|
||||
if (packageName.equals(mServicePackages.get(userId))) {
|
||||
packageWhitelisted = isWhitelisted(userId, packageName);
|
||||
if (!packageWhitelisted) {
|
||||
// Full package is not whitelisted: check individual components first
|
||||
whitelistedComponents = getWhitelistedComponents(userId, packageName);
|
||||
if (whitelistedComponents == null
|
||||
&& packageName.equals(mServicePackages.get(userId))) {
|
||||
// No components whitelisted either, but let it go because it's the
|
||||
// service's own package
|
||||
if (verbose) Slog.v(mTag, "getOptionsForPackage() lite for " + packageName);
|
||||
return new ContentCaptureOptions(mDevCfgLoggingLevel);
|
||||
}
|
||||
if (verbose) {
|
||||
Slog.v(mTag, "getOptionsForPackage(" + packageName + "): not whitelisted");
|
||||
}
|
||||
}
|
||||
} // synchronized
|
||||
|
||||
// Restrict what temporary services can whitelist
|
||||
if (Build.IS_USER && mServiceNameResolver.isTemporary(userId)) {
|
||||
if (!packageName.equals(mServicePackages.get(userId))) {
|
||||
Slog.w(mTag, "Ignoring package " + packageName + " while using temporary "
|
||||
+ "service " + mServicePackages.get(userId));
|
||||
return null;
|
||||
}
|
||||
|
||||
final ArraySet<ComponentName> whitelistedComponents =
|
||||
getWhitelistedComponents(userId, packageName);
|
||||
if (Build.IS_USER && mServiceNameResolver.isTemporary(userId)) {
|
||||
if (!packageName.equals(mServicePackages.get(userId))) {
|
||||
Slog.w(mTag, "Ignoring package " + packageName
|
||||
+ " while using temporary service " + mServicePackages.get(userId));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
final ContentCaptureOptions options = new ContentCaptureOptions(mDevCfgLoggingLevel,
|
||||
mDevCfgMaxBufferSize, mDevCfgIdleFlushingFrequencyMs,
|
||||
mDevCfgTextChangeFlushingFrequencyMs, mDevCfgLogHistorySize,
|
||||
whitelistedComponents);
|
||||
if (verbose) {
|
||||
Slog.v(mTag, "getOptionsForPackage(" + packageName + "): " + options);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
if (!packageWhitelisted && whitelistedComponents == null) {
|
||||
// No can do!
|
||||
if (verbose) {
|
||||
Slog.v(mTag, "getOptionsForPackage(" + packageName + "): not whitelisted");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final ContentCaptureOptions options = new ContentCaptureOptions(mDevCfgLoggingLevel,
|
||||
mDevCfgMaxBufferSize, mDevCfgIdleFlushingFrequencyMs,
|
||||
mDevCfgTextChangeFlushingFrequencyMs, mDevCfgLogHistorySize,
|
||||
whitelistedComponents);
|
||||
if (verbose) Slog.v(mTag, "getOptionsForPackage(" + packageName + "): " + options);
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,13 +35,11 @@ import android.app.ActivityManagerInternal;
|
||||
import android.app.assist.AssistContent;
|
||||
import android.app.assist.AssistStructure;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentCaptureOptions;
|
||||
import android.content.pm.ActivityPresentationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.UserHandle;
|
||||
@@ -60,7 +58,6 @@ import android.view.contentcapture.ContentCaptureCondition;
|
||||
import android.view.contentcapture.DataRemovalRequest;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.infra.WhitelistHelper;
|
||||
import com.android.internal.os.IResultReceiver;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.contentcapture.RemoteContentCaptureService.ContentCaptureServiceCallbacks;
|
||||
@@ -96,12 +93,6 @@ final class ContentCapturePerUserService
|
||||
private final ContentCaptureServiceRemoteCallback mRemoteServiceCallback =
|
||||
new ContentCaptureServiceRemoteCallback();
|
||||
|
||||
/**
|
||||
* List of packages that are whitelisted to be content captured.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private final WhitelistHelper mWhitelistHelper = new WhitelistHelper();
|
||||
|
||||
/**
|
||||
* List of conditions keyed by package.
|
||||
*/
|
||||
@@ -131,6 +122,7 @@ final class ContentCapturePerUserService
|
||||
* Updates the reference to the remote service.
|
||||
*/
|
||||
private void updateRemoteServiceLocked(boolean disabled) {
|
||||
if (mMaster.verbose) Slog.v(TAG, "updateRemoteService(disabled=" + disabled + ")");
|
||||
if (mRemoteService != null) {
|
||||
if (mMaster.debug) Slog.d(TAG, "updateRemoteService(): destroying old remote service");
|
||||
mRemoteService.destroy();
|
||||
@@ -247,7 +239,8 @@ final class ContentCapturePerUserService
|
||||
final int displayId = activityPresentationInfo.displayId;
|
||||
final ComponentName componentName = activityPresentationInfo.componentName;
|
||||
final boolean whiteListed = mMaster.mGlobalContentCaptureOptions.isWhitelisted(mUserId,
|
||||
componentName);
|
||||
componentName) || mMaster.mGlobalContentCaptureOptions.isWhitelisted(mUserId,
|
||||
componentName.getPackageName());
|
||||
final ComponentName serviceComponentName = getServiceComponentName();
|
||||
final boolean enabled = isEnabledLocked();
|
||||
if (mMaster.mRequestsHistory != null) {
|
||||
@@ -460,40 +453,6 @@ final class ContentCapturePerUserService
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@Nullable
|
||||
ContentCaptureOptions getOptionsForPackageLocked(@NonNull String packageName) {
|
||||
if (!mWhitelistHelper.isWhitelisted(packageName)) {
|
||||
if (packageName.equals(getServicePackageName())) {
|
||||
if (mMaster.verbose) Slog.v(mTag, "getOptionsForPackage() lite for " + packageName);
|
||||
return new ContentCaptureOptions(mMaster.mDevCfgLoggingLevel);
|
||||
}
|
||||
if (mMaster.verbose) {
|
||||
Slog.v(mTag, "getOptionsForPackage(" + packageName + "): not whitelisted");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final ArraySet<ComponentName> whitelistedComponents = mWhitelistHelper
|
||||
.getWhitelistedComponents(packageName);
|
||||
if (Build.IS_USER && isTemporaryServiceSetLocked()) {
|
||||
final String servicePackageName = getServicePackageName();
|
||||
if (!packageName.equals(servicePackageName)) {
|
||||
Slog.w(mTag, "Ignoring package " + packageName
|
||||
+ " while using temporary service " + servicePackageName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
final ContentCaptureOptions options = new ContentCaptureOptions(mMaster.mDevCfgLoggingLevel,
|
||||
mMaster.mDevCfgMaxBufferSize, mMaster.mDevCfgIdleFlushingFrequencyMs,
|
||||
mMaster.mDevCfgTextChangeFlushingFrequencyMs, mMaster.mDevCfgLogHistorySize,
|
||||
whitelistedComponents);
|
||||
if (mMaster.verbose) {
|
||||
Slog.v(mTag, "getOptionsForPackage(" + packageName + "): " + options);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@Nullable
|
||||
ArraySet<ContentCaptureCondition> getContentCaptureConditionsLocked(
|
||||
|
||||
Reference in New Issue
Block a user