Merge "Fixed content capture whitelist for specific activities." into qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
845d5ee587
@@ -127,6 +127,7 @@ import android.view.autofill.AutofillPopupWindow;
|
|||||||
import android.view.autofill.IAutofillWindowPresenter;
|
import android.view.autofill.IAutofillWindowPresenter;
|
||||||
import android.view.contentcapture.ContentCaptureContext;
|
import android.view.contentcapture.ContentCaptureContext;
|
||||||
import android.view.contentcapture.ContentCaptureManager;
|
import android.view.contentcapture.ContentCaptureManager;
|
||||||
|
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import android.widget.Toolbar;
|
import android.widget.Toolbar;
|
||||||
@@ -723,7 +724,7 @@ public class Activity extends ContextThemeWrapper
|
|||||||
Window.Callback, KeyEvent.Callback,
|
Window.Callback, KeyEvent.Callback,
|
||||||
OnCreateContextMenuListener, ComponentCallbacks2,
|
OnCreateContextMenuListener, ComponentCallbacks2,
|
||||||
Window.OnWindowDismissedCallback, WindowControllerCallback,
|
Window.OnWindowDismissedCallback, WindowControllerCallback,
|
||||||
AutofillManager.AutofillClient {
|
AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {
|
||||||
private static final String TAG = "Activity";
|
private static final String TAG = "Activity";
|
||||||
private static final boolean DEBUG_LIFECYCLE = false;
|
private static final boolean DEBUG_LIFECYCLE = false;
|
||||||
|
|
||||||
@@ -1125,6 +1126,12 @@ public class Activity extends ContextThemeWrapper
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
@Override
|
||||||
|
public final ContentCaptureClient getContentCaptureClient() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register an {@link Application.ActivityLifecycleCallbacks} instance that receives
|
* Register an {@link Application.ActivityLifecycleCallbacks} instance that receives
|
||||||
* lifecycle callbacks for only this Activity.
|
* lifecycle callbacks for only this Activity.
|
||||||
@@ -6511,6 +6518,12 @@ public class Activity extends ContextThemeWrapper
|
|||||||
return getComponentName();
|
return getComponentName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
@Override
|
||||||
|
public final ComponentName contentCaptureClientGetComponentName() {
|
||||||
|
return getComponentName();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a {@link SharedPreferences} object for accessing preferences
|
* Retrieve a {@link SharedPreferences} object for accessing preferences
|
||||||
* that are private to this activity. This simply calls the underlying
|
* that are private to this activity. This simply calls the underlying
|
||||||
|
|||||||
@@ -1143,7 +1143,7 @@ final class SystemServiceRegistry {
|
|||||||
Context outerContext = ctx.getOuterContext();
|
Context outerContext = ctx.getOuterContext();
|
||||||
ContentCaptureOptions options = outerContext.getContentCaptureOptions();
|
ContentCaptureOptions options = outerContext.getContentCaptureOptions();
|
||||||
// Options is null when the service didn't whitelist the activity or package
|
// 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
|
IBinder b = ServiceManager
|
||||||
.getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
|
.getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
|
||||||
IContentCaptureManager service = IContentCaptureManager.Stub.asInterface(b);
|
IContentCaptureManager service = IContentCaptureManager.Stub.asInterface(b);
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ import android.os.Parcelable;
|
|||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.contentcapture.ContentCaptureManager;
|
import android.view.contentcapture.ContentCaptureManager;
|
||||||
|
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
@@ -78,12 +81,19 @@ public final class ContentCaptureOptions implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public final boolean lite;
|
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) {
|
public ContentCaptureOptions(int loggingLevel) {
|
||||||
this(/* lite= */ true, loggingLevel, /* maxBufferSize= */ 0,
|
this(/* lite= */ true, loggingLevel, /* maxBufferSize= */ 0,
|
||||||
/* idleFlushingFrequencyMs= */ 0, /* textChangeFlushingFrequencyMs= */ 0,
|
/* idleFlushingFrequencyMs= */ 0, /* textChangeFlushingFrequencyMs= */ 0,
|
||||||
/* logHistorySize= */ 0, /* whitelistedComponents= */ null);
|
/* logHistorySize= */ 0, /* whitelistedComponents= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor.
|
||||||
|
*/
|
||||||
public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
|
public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
|
||||||
int textChangeFlushingFrequencyMs, int logHistorySize,
|
int textChangeFlushingFrequencyMs, int logHistorySize,
|
||||||
@Nullable ArraySet<ComponentName> whitelistedComponents) {
|
@Nullable ArraySet<ComponentName> whitelistedComponents) {
|
||||||
@@ -91,6 +101,16 @@ public final class ContentCaptureOptions implements Parcelable {
|
|||||||
textChangeFlushingFrequencyMs, logHistorySize, whitelistedComponents);
|
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,
|
private ContentCaptureOptions(boolean lite, int loggingLevel, int maxBufferSize,
|
||||||
int idleFlushingFrequencyMs, int textChangeFlushingFrequencyMs, int logHistorySize,
|
int idleFlushingFrequencyMs, int textChangeFlushingFrequencyMs, int logHistorySize,
|
||||||
@Nullable ArraySet<ComponentName> whitelistedComponents) {
|
@Nullable ArraySet<ComponentName> whitelistedComponents) {
|
||||||
@@ -103,10 +123,6 @@ public final class ContentCaptureOptions implements Parcelable {
|
|||||||
this.whitelistedComponents = whitelistedComponents;
|
this.whitelistedComponents = whitelistedComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
@TestApi
|
|
||||||
public static ContentCaptureOptions forWhitelistingItself() {
|
public static ContentCaptureOptions forWhitelistingItself() {
|
||||||
final ActivityThread at = ActivityThread.currentActivityThread();
|
final ActivityThread at = ActivityThread.currentActivityThread();
|
||||||
if (at == null) {
|
if (at == null) {
|
||||||
@@ -120,19 +136,27 @@ public final class ContentCaptureOptions implements Parcelable {
|
|||||||
throw new SecurityException("Thou shall not pass!");
|
throw new SecurityException("Thou shall not pass!");
|
||||||
}
|
}
|
||||||
|
|
||||||
final ContentCaptureOptions options = new ContentCaptureOptions(
|
final ContentCaptureOptions options =
|
||||||
ContentCaptureManager.LOGGING_LEVEL_VERBOSE,
|
new ContentCaptureOptions(/* whitelistedComponents= */ null);
|
||||||
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);
|
|
||||||
// Always log, as it's used by test only
|
// Always log, as it's used by test only
|
||||||
Log.i(TAG, "forWhitelistingItself(" + packageName + "): " + options);
|
Log.i(TAG, "forWhitelistingItself(" + packageName + "): " + options);
|
||||||
|
|
||||||
return 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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (lite) {
|
if (lite) {
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ import android.view.View;
|
|||||||
import android.view.ViewDebug;
|
import android.view.ViewDebug;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.autofill.AutofillManager.AutofillClient;
|
import android.view.autofill.AutofillManager.AutofillClient;
|
||||||
|
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
|
||||||
import android.view.textclassifier.TextClassificationManager;
|
import android.view.textclassifier.TextClassificationManager;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -5411,6 +5412,14 @@ public abstract class Context {
|
|||||||
public void setAutofillClient(@SuppressWarnings("unused") AutofillClient client) {
|
public void setAutofillClient(@SuppressWarnings("unused") AutofillClient client) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public ContentCaptureClient getContentCaptureClient() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -293,6 +293,15 @@ public final class ContentCaptureManager {
|
|||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private MainContentCaptureSession mMainSession;
|
private MainContentCaptureSession mMainSession;
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public interface ContentCaptureClient {
|
||||||
|
/**
|
||||||
|
* Gets the component name of the client.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
ComponentName contentCaptureClientGetComponentName();
|
||||||
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public ContentCaptureManager(@NonNull Context context,
|
public ContentCaptureManager(@NonNull Context context,
|
||||||
@NonNull IContentCaptureManager service, @NonNull ContentCaptureOptions options) {
|
@NonNull IContentCaptureManager service, @NonNull ContentCaptureOptions options) {
|
||||||
|
|||||||
@@ -35,11 +35,13 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* <p>This class is thread safe.
|
* <p>This class is thread safe.
|
||||||
*/
|
*/
|
||||||
|
// TODO: add unit tests
|
||||||
public class GlobalWhitelistState {
|
public class GlobalWhitelistState {
|
||||||
|
|
||||||
// Uses full-name to avoid collision with service-provided mLock
|
// Uses full-name to avoid collision with service-provided mLock
|
||||||
protected final Object mGlobalWhitelistStateLock = new Object();
|
protected final Object mGlobalWhitelistStateLock = new Object();
|
||||||
|
|
||||||
|
// TODO: should not be exposed directly
|
||||||
@Nullable
|
@Nullable
|
||||||
@GuardedBy("mGlobalWhitelistStateLock")
|
@GuardedBy("mGlobalWhitelistStateLock")
|
||||||
protected SparseArray<WhitelistHelper> mWhitelisterHelpers;
|
protected SparseArray<WhitelistHelper> mWhitelisterHelpers;
|
||||||
|
|||||||
@@ -98,9 +98,9 @@ public final class WhitelistHelper {
|
|||||||
@Nullable List<ComponentName> components) {
|
@Nullable List<ComponentName> components) {
|
||||||
final ArraySet<String> packageNamesSet = packageNames == null ? null
|
final ArraySet<String> packageNamesSet = packageNames == null ? null
|
||||||
: new ArraySet<>(packageNames);
|
: new ArraySet<>(packageNames);
|
||||||
final ArraySet<ComponentName> componentssSet = components == null ? null
|
final ArraySet<ComponentName> componentsSet = components == null ? null
|
||||||
: new ArraySet<>(components);
|
: new ArraySet<>(components);
|
||||||
setWhitelist(packageNamesSet, componentssSet);
|
setWhitelist(packageNamesSet, componentsSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -170,7 +170,7 @@ public final class WhitelistHelper {
|
|||||||
|
|
||||||
pw.print("["); pw.print(components.valueAt(0));
|
pw.print("["); pw.print(components.valueAt(0));
|
||||||
for (int j = 1; j < components.size(); j++) {
|
for (int j = 1; j < components.size(); j++) {
|
||||||
pw.print(", "); pw.print(components.valueAt(i));
|
pw.print(", "); pw.print(components.valueAt(j));
|
||||||
}
|
}
|
||||||
pw.println("]");
|
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")
|
@GuardedBy("mGlobalWhitelistStateLock")
|
||||||
public ContentCaptureOptions getOptions(@UserIdInt int userId,
|
public ContentCaptureOptions getOptions(@UserIdInt int userId,
|
||||||
@NonNull String packageName) {
|
@NonNull String packageName) {
|
||||||
|
boolean packageWhitelisted;
|
||||||
|
ArraySet<ComponentName> whitelistedComponents = null;
|
||||||
synchronized (mGlobalWhitelistStateLock) {
|
synchronized (mGlobalWhitelistStateLock) {
|
||||||
if (!isWhitelisted(userId, packageName)) {
|
packageWhitelisted = isWhitelisted(userId, packageName);
|
||||||
if (packageName.equals(mServicePackages.get(userId))) {
|
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);
|
if (verbose) Slog.v(mTag, "getOptionsForPackage() lite for " + packageName);
|
||||||
return new ContentCaptureOptions(mDevCfgLoggingLevel);
|
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;
|
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
|
@Override
|
||||||
|
|||||||
@@ -35,13 +35,11 @@ import android.app.ActivityManagerInternal;
|
|||||||
import android.app.assist.AssistContent;
|
import android.app.assist.AssistContent;
|
||||||
import android.app.assist.AssistStructure;
|
import android.app.assist.AssistStructure;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.ContentCaptureOptions;
|
|
||||||
import android.content.pm.ActivityPresentationInfo;
|
import android.content.pm.ActivityPresentationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.content.pm.ServiceInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
@@ -60,7 +58,6 @@ import android.view.contentcapture.ContentCaptureCondition;
|
|||||||
import android.view.contentcapture.DataRemovalRequest;
|
import android.view.contentcapture.DataRemovalRequest;
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.internal.infra.WhitelistHelper;
|
|
||||||
import com.android.internal.os.IResultReceiver;
|
import com.android.internal.os.IResultReceiver;
|
||||||
import com.android.server.LocalServices;
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.contentcapture.RemoteContentCaptureService.ContentCaptureServiceCallbacks;
|
import com.android.server.contentcapture.RemoteContentCaptureService.ContentCaptureServiceCallbacks;
|
||||||
@@ -96,12 +93,6 @@ final class ContentCapturePerUserService
|
|||||||
private final ContentCaptureServiceRemoteCallback mRemoteServiceCallback =
|
private final ContentCaptureServiceRemoteCallback mRemoteServiceCallback =
|
||||||
new ContentCaptureServiceRemoteCallback();
|
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.
|
* List of conditions keyed by package.
|
||||||
*/
|
*/
|
||||||
@@ -131,6 +122,7 @@ final class ContentCapturePerUserService
|
|||||||
* Updates the reference to the remote service.
|
* Updates the reference to the remote service.
|
||||||
*/
|
*/
|
||||||
private void updateRemoteServiceLocked(boolean disabled) {
|
private void updateRemoteServiceLocked(boolean disabled) {
|
||||||
|
if (mMaster.verbose) Slog.v(TAG, "updateRemoteService(disabled=" + disabled + ")");
|
||||||
if (mRemoteService != null) {
|
if (mRemoteService != null) {
|
||||||
if (mMaster.debug) Slog.d(TAG, "updateRemoteService(): destroying old remote service");
|
if (mMaster.debug) Slog.d(TAG, "updateRemoteService(): destroying old remote service");
|
||||||
mRemoteService.destroy();
|
mRemoteService.destroy();
|
||||||
@@ -247,7 +239,8 @@ final class ContentCapturePerUserService
|
|||||||
final int displayId = activityPresentationInfo.displayId;
|
final int displayId = activityPresentationInfo.displayId;
|
||||||
final ComponentName componentName = activityPresentationInfo.componentName;
|
final ComponentName componentName = activityPresentationInfo.componentName;
|
||||||
final boolean whiteListed = mMaster.mGlobalContentCaptureOptions.isWhitelisted(mUserId,
|
final boolean whiteListed = mMaster.mGlobalContentCaptureOptions.isWhitelisted(mUserId,
|
||||||
componentName);
|
componentName) || mMaster.mGlobalContentCaptureOptions.isWhitelisted(mUserId,
|
||||||
|
componentName.getPackageName());
|
||||||
final ComponentName serviceComponentName = getServiceComponentName();
|
final ComponentName serviceComponentName = getServiceComponentName();
|
||||||
final boolean enabled = isEnabledLocked();
|
final boolean enabled = isEnabledLocked();
|
||||||
if (mMaster.mRequestsHistory != null) {
|
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")
|
@GuardedBy("mLock")
|
||||||
@Nullable
|
@Nullable
|
||||||
ArraySet<ContentCaptureCondition> getContentCaptureConditionsLocked(
|
ArraySet<ContentCaptureCondition> getContentCaptureConditionsLocked(
|
||||||
|
|||||||
Reference in New Issue
Block a user