Merge changes from topic "aa_whitelist"
* changes: Check for empty arguments in setWhitelist(). Implemented a WhitelistHelper for whitelisting packages/activities for Augmented Autofill and Content Capture.
This commit is contained in:
@@ -563,11 +563,13 @@ package android.content {
|
||||
ctor public AutofillOptions(int, boolean);
|
||||
method public int describeContents();
|
||||
method public static android.content.AutofillOptions forWhitelistingItself();
|
||||
method public boolean isAugmentedAutofillEnabled(@NonNull android.content.Context);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.content.AutofillOptions> CREATOR;
|
||||
field public boolean augmentedEnabled;
|
||||
field public boolean augmentedAutofillEnabled;
|
||||
field public final boolean compatModeEnabled;
|
||||
field public final int loggingLevel;
|
||||
field @Nullable public android.util.ArraySet<android.content.ComponentName> whitelistedActivitiesForAugmentedAutofill;
|
||||
}
|
||||
|
||||
public final class ContentCaptureOptions implements android.os.Parcelable {
|
||||
|
||||
@@ -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;
|
||||
@@ -717,7 +718,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;
|
||||
|
||||
@@ -1119,6 +1120,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.
|
||||
@@ -6464,6 +6471,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
|
||||
|
||||
@@ -16,12 +16,15 @@
|
||||
package android.content;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.TestApi;
|
||||
import android.app.ActivityThread;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.view.autofill.AutofillManager;
|
||||
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
@@ -51,14 +54,33 @@ public final class AutofillOptions implements Parcelable {
|
||||
/**
|
||||
* Whether package is whitelisted for augmented autofill.
|
||||
*/
|
||||
public boolean augmentedEnabled;
|
||||
// TODO(b/123100824): add (optional) list of activities
|
||||
public boolean augmentedAutofillEnabled;
|
||||
|
||||
/**
|
||||
* List of whitelisted activities.
|
||||
*/
|
||||
@Nullable
|
||||
public ArraySet<ComponentName> whitelistedActivitiesForAugmentedAutofill;
|
||||
|
||||
public AutofillOptions(int loggingLevel, boolean compatModeEnabled) {
|
||||
this.loggingLevel = loggingLevel;
|
||||
this.compatModeEnabled = compatModeEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether activity is whitelisted for augmented autofill.
|
||||
*/
|
||||
public boolean isAugmentedAutofillEnabled(@NonNull Context context) {
|
||||
if (!augmentedAutofillEnabled) return false;
|
||||
|
||||
final ContentCaptureClient contentCaptureClient = context.getContentCaptureClient();
|
||||
if (contentCaptureClient == null) return false;
|
||||
|
||||
final ComponentName component = contentCaptureClient.contentCaptureClientGetComponentName();
|
||||
return whitelistedActivitiesForAugmentedAutofill == null
|
||||
|| whitelistedActivitiesForAugmentedAutofill.contains(component);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@@ -78,7 +100,7 @@ public final class AutofillOptions implements Parcelable {
|
||||
|
||||
final AutofillOptions options = new AutofillOptions(
|
||||
AutofillManager.FLAG_ADD_CLIENT_VERBOSE, /* compatModeAllowed= */ true);
|
||||
options.augmentedEnabled = true;
|
||||
options.augmentedAutofillEnabled = true;
|
||||
// Always log, as it's used by test only
|
||||
Log.i(TAG, "forWhitelistingItself(" + packageName + "): " + options);
|
||||
|
||||
@@ -87,15 +109,19 @@ public final class AutofillOptions implements Parcelable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AutofillOptions [loggingLevel=" + loggingLevel + ", compatMode="
|
||||
+ compatModeEnabled + ", augmentedEnabled=" + augmentedEnabled + "]";
|
||||
return "AutofillOptions [loggingLevel=" + loggingLevel + ", compatMode=" + compatModeEnabled
|
||||
+ ", augmentedAutofillEnabled=" + augmentedAutofillEnabled + "]";
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void dumpShort(@NonNull PrintWriter pw) {
|
||||
pw.print("logLvl="); pw.print(loggingLevel);
|
||||
pw.print(", compatMode="); pw.print(compatModeEnabled);
|
||||
pw.print(", augmented="); pw.print(augmentedEnabled);
|
||||
pw.print(", augmented="); pw.print(augmentedAutofillEnabled);
|
||||
if (whitelistedActivitiesForAugmentedAutofill != null) {
|
||||
pw.print(", whitelistedActivitiesForAugmentedAutofill=");
|
||||
pw.print(whitelistedActivitiesForAugmentedAutofill);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,7 +133,8 @@ public final class AutofillOptions implements Parcelable {
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeInt(loggingLevel);
|
||||
parcel.writeBoolean(compatModeEnabled);
|
||||
parcel.writeBoolean(augmentedEnabled);
|
||||
parcel.writeBoolean(augmentedAutofillEnabled);
|
||||
parcel.writeArraySet(whitelistedActivitiesForAugmentedAutofill);
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<AutofillOptions> CREATOR =
|
||||
@@ -118,7 +145,9 @@ public final class AutofillOptions implements Parcelable {
|
||||
final int loggingLevel = parcel.readInt();
|
||||
final boolean compatMode = parcel.readBoolean();
|
||||
final AutofillOptions options = new AutofillOptions(loggingLevel, compatMode);
|
||||
options.augmentedEnabled = parcel.readBoolean();
|
||||
options.augmentedAutofillEnabled = parcel.readBoolean();
|
||||
options.whitelistedActivitiesForAugmentedAutofill =
|
||||
(ArraySet<ComponentName>) parcel.readArraySet(null);
|
||||
return options;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,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;
|
||||
@@ -5340,6 +5341,14 @@ public abstract class Context {
|
||||
public void setAutofillClient(@SuppressWarnings("unused") AutofillClient client) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Nullable
|
||||
public ContentCaptureClient getContentCaptureClient() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -9530,8 +9530,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
||||
// View is not important for "regular" autofill, so we must check if Augmented Autofill
|
||||
// is enabled for the activity
|
||||
final AutofillOptions options = mContext.getAutofillOptions();
|
||||
if (options == null || !options.augmentedEnabled) {
|
||||
// TODO(b/123100824): should also check if activity is whitelisted
|
||||
if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
|
||||
return false;
|
||||
}
|
||||
final AutofillManager afm = getAutofillManager();
|
||||
|
||||
@@ -192,6 +192,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) {
|
||||
|
||||
@@ -121,11 +121,11 @@ public abstract class ContentCaptureSession implements AutoCloseable {
|
||||
public static final int STATE_INTERNAL_ERROR = 0x100;
|
||||
|
||||
/**
|
||||
* Session is disabled because service didn't whitelist package.
|
||||
* Session is disabled because service didn't whitelist package or activity.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int STATE_PACKAGE_NOT_WHITELISTED = 0x200;
|
||||
public static final int STATE_NOT_WHITELISTED = 0x200;
|
||||
|
||||
private static final int INITIAL_CHILDREN_CAPACITY = 5;
|
||||
|
||||
|
||||
163
core/java/com/android/internal/infra/WhitelistHelper.java
Normal file
163
core/java/com/android/internal/infra/WhitelistHelper.java
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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 com.android.internal.infra;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Helper class for keeping track of whitelisted packages/activities.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class WhitelistHelper {
|
||||
|
||||
private static final String TAG = "WhitelistHelper";
|
||||
|
||||
/**
|
||||
* Map of whitelisted packages/activities. The whole package is whitelisted if its
|
||||
* corresponding value is {@code null}.
|
||||
*/
|
||||
@Nullable
|
||||
private ArrayMap<String, ArraySet<ComponentName>> mWhitelistedPackages;
|
||||
|
||||
/**
|
||||
* Sets the whitelist with the given packages and activities. The list is cleared if both
|
||||
* packageNames and components are {@code null}.
|
||||
*
|
||||
* @param packageNames packages to be whitelisted.
|
||||
* @param components activities to be whitelisted.
|
||||
*
|
||||
* @throws IllegalArgumentException if packages or components are empty.
|
||||
*/
|
||||
public void setWhitelist(@Nullable ArraySet<String> packageNames,
|
||||
@Nullable ArraySet<ComponentName> components) {
|
||||
mWhitelistedPackages = null;
|
||||
if (packageNames == null && components == null) return;
|
||||
|
||||
if ((packageNames != null && packageNames.isEmpty())
|
||||
|| (components != null && components.isEmpty())) {
|
||||
throw new IllegalArgumentException("Packages or Components cannot be empty.");
|
||||
}
|
||||
|
||||
mWhitelistedPackages = new ArrayMap<>();
|
||||
|
||||
if (packageNames != null) {
|
||||
for (int i = 0; i < packageNames.size(); i++) {
|
||||
mWhitelistedPackages.put(packageNames.valueAt(i), null);
|
||||
}
|
||||
}
|
||||
|
||||
if (components != null) {
|
||||
for (int i = 0; i < components.size(); i++) {
|
||||
final ComponentName component = components.valueAt(i);
|
||||
if (component == null) {
|
||||
Log.w(TAG, "setWhitelist(): component is null");
|
||||
continue;
|
||||
}
|
||||
|
||||
final String packageName = component.getPackageName();
|
||||
ArraySet<ComponentName> set = mWhitelistedPackages.get(packageName);
|
||||
if (set == null) {
|
||||
set = new ArraySet<>();
|
||||
mWhitelistedPackages.put(packageName, set);
|
||||
}
|
||||
set.add(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the entire package is whitelisted.
|
||||
*/
|
||||
public boolean isWhitelisted(@NonNull String packageName) {
|
||||
Preconditions.checkNotNull(packageName);
|
||||
|
||||
if (mWhitelistedPackages == null) return false;
|
||||
|
||||
return mWhitelistedPackages.containsKey(packageName)
|
||||
&& mWhitelistedPackages.get(packageName) == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the specified activity is whitelisted.
|
||||
*/
|
||||
public boolean isWhitelisted(@NonNull ComponentName componentName) {
|
||||
Preconditions.checkNotNull(componentName);
|
||||
|
||||
final String packageName = componentName.getPackageName();
|
||||
final ArraySet<ComponentName> whitelistedComponents = getWhitelistedComponents(packageName);
|
||||
if (whitelistedComponents != null) {
|
||||
return whitelistedComponents.contains(componentName);
|
||||
}
|
||||
|
||||
return isWhitelisted(packageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of whitelisted components with the given package, or null if nothing is
|
||||
* whitelisted.
|
||||
*/
|
||||
@Nullable
|
||||
public ArraySet<ComponentName> getWhitelistedComponents(@NonNull String packageName) {
|
||||
Preconditions.checkNotNull(packageName);
|
||||
|
||||
return mWhitelistedPackages == null ? null : mWhitelistedPackages.get(packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WhitelistHelper[" + mWhitelistedPackages + ']';
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps it!
|
||||
*/
|
||||
public void dump(@NonNull String prefix, @NonNull String message, @NonNull PrintWriter pw) {
|
||||
if (mWhitelistedPackages == null || mWhitelistedPackages.size() == 0) {
|
||||
pw.print(prefix); pw.print(message); pw.println(": (no whitelisted packages)");
|
||||
return;
|
||||
}
|
||||
|
||||
final int size = mWhitelistedPackages.size();
|
||||
pw.print(prefix); pw.print(message); pw.print(": "); pw.print(size);
|
||||
pw.println(" packages");
|
||||
for (int i = 0; i < mWhitelistedPackages.size(); i++) {
|
||||
final String packageName = mWhitelistedPackages.keyAt(i);
|
||||
final ArraySet<ComponentName> components = mWhitelistedPackages.valueAt(i);
|
||||
pw.print(prefix); pw.print(i); pw.print("."); pw.print(packageName); pw.print(": ");
|
||||
if (components == null) {
|
||||
pw.println("(whole package)");
|
||||
continue;
|
||||
}
|
||||
|
||||
pw.print("["); pw.print(components.valueAt(0));
|
||||
for (int j = 1; j < components.size(); j++) {
|
||||
pw.print(", "); pw.print(components.valueAt(i));
|
||||
}
|
||||
pw.println("]");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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 com.android.internal.infra;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.testng.Assert.assertThrows;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
/**
|
||||
* Unit test for {@link WhitelistHelper}.
|
||||
*
|
||||
* <p>To run it:
|
||||
* {@code atest FrameworksCoreTests:com.android.internal.infra.WhitelistHelperTest}
|
||||
*/
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class WhitelistHelperTest {
|
||||
private WhitelistHelper mWhitelistHelper = new WhitelistHelper();
|
||||
|
||||
private String mPackage1 = "com.example";
|
||||
private String mPackage2 = "com.example2";
|
||||
|
||||
private ComponentName mComponent1 = new ComponentName(mPackage1, "class1");
|
||||
private ComponentName mComponent2 = new ComponentName(mPackage1, "class2");
|
||||
private ComponentName mComponentDifferentPkg = new ComponentName(mPackage2, "class3");
|
||||
|
||||
@Test
|
||||
public void testSetWhitelist_emptyArguments() {
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> mWhitelistHelper.setWhitelist(new ArraySet<>(), null));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> mWhitelistHelper.setWhitelist(null, new ArraySet<>()));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> mWhitelistHelper.setWhitelist(new ArraySet<>(), new ArraySet<>()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhitelistHelper_nullArguments() {
|
||||
assertThrows(NullPointerException.class,
|
||||
() -> mWhitelistHelper.isWhitelisted((String) null));
|
||||
assertThrows(NullPointerException.class,
|
||||
() -> mWhitelistHelper.isWhitelisted((ComponentName) null));
|
||||
assertThrows(NullPointerException.class,
|
||||
() -> mWhitelistHelper.getWhitelistedComponents(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetWhitelist_nullPackage() {
|
||||
final ArraySet<String> packages = new ArraySet<>();
|
||||
packages.add(null);
|
||||
mWhitelistHelper.setWhitelist(packages, null);
|
||||
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mPackage1)).isFalse();
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mPackage2)).isFalse();
|
||||
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponent1)).isFalse();
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponent2)).isFalse();
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponentDifferentPkg)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetWhitelist_nullActivity() {
|
||||
final ArraySet<ComponentName> components = new ArraySet<>();
|
||||
components.add(null);
|
||||
mWhitelistHelper.setWhitelist(null, components);
|
||||
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mPackage1)).isFalse();
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mPackage2)).isFalse();
|
||||
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponent1)).isFalse();
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponent2)).isFalse();
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponentDifferentPkg)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetWhitelist_replaceWhitelist() {
|
||||
final ArraySet<ComponentName> components = new ArraySet<>();
|
||||
components.add(mComponent1);
|
||||
mWhitelistHelper.setWhitelist(null, components);
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponent1)).isTrue();
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponent2)).isFalse();
|
||||
|
||||
final ArraySet<ComponentName> components2 = new ArraySet<>();
|
||||
components2.add(mComponent2);
|
||||
mWhitelistHelper.setWhitelist(null, components2);
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponent1)).isFalse();
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponent2)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsWhitelisted_packageWhitelisted() {
|
||||
final ArraySet<String> packages = new ArraySet<>();
|
||||
packages.add(mPackage1);
|
||||
mWhitelistHelper.setWhitelist(packages, null);
|
||||
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mPackage1)).isTrue();
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mPackage2)).isFalse();
|
||||
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponent1)).isTrue();
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponent2)).isTrue();
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponentDifferentPkg)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsWhitelisted_activityWhitelisted() {
|
||||
final ArraySet<ComponentName> components = new ArraySet<>();
|
||||
components.add(mComponent1);
|
||||
mWhitelistHelper.setWhitelist(null, components);
|
||||
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mPackage1)).isFalse();
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mPackage2)).isFalse();
|
||||
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponent1)).isTrue();
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponent2)).isFalse();
|
||||
assertThat(mWhitelistHelper.isWhitelisted(mComponentDifferentPkg)).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,7 @@ import android.view.autofill.IAutoFillManagerClient;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.infra.WhitelistHelper;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.server.LocalServices;
|
||||
@@ -173,10 +174,10 @@ final class AutofillManagerServiceImpl
|
||||
private ServiceInfo mRemoteAugmentedAutofillServiceInfo;
|
||||
|
||||
/**
|
||||
* List of packages that are whitelisted to be trigger augmented autofill.
|
||||
* List of packages/activities that are whitelisted to be trigger augmented autofill.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private final ArraySet<String> mWhitelistedAugmentAutofillPackages = new ArraySet<>();
|
||||
private final WhitelistHelper mAugmentedWhitelistHelper = new WhitelistHelper();
|
||||
|
||||
AutofillManagerServiceImpl(AutofillManagerService master, Object lock,
|
||||
LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
|
||||
@@ -905,13 +906,8 @@ final class AutofillManagerServiceImpl
|
||||
pw.println(mRemoteAugmentedAutofillServiceInfo);
|
||||
}
|
||||
|
||||
final int whitelistSize = mWhitelistedAugmentAutofillPackages.size();
|
||||
pw.print(prefix); pw.print("Packages whitelisted for augmented autofill: ");
|
||||
pw.println(whitelistSize);
|
||||
for (int i = 0; i < whitelistSize; i++) {
|
||||
final String whitelistedPkg = mWhitelistedAugmentAutofillPackages.valueAt(i);
|
||||
pw.print(prefix2); pw.print(i + 1); pw.print(": "); pw.println(whitelistedPkg);
|
||||
}
|
||||
pw.print(prefix); pw.print("augmented autofill whitelist: ");
|
||||
mAugmentedWhitelistHelper.dump(prefix2, "Whitelist", pw);
|
||||
|
||||
pw.print(prefix); pw.print("Field classification enabled: ");
|
||||
pw.println(isFieldClassificationEnabledLocked());
|
||||
@@ -1129,9 +1125,8 @@ final class AutofillManagerServiceImpl
|
||||
Slog.v(TAG, "setAugmentedAutofillWhitelistLocked(packages=" + packages + ", activities="
|
||||
+ activities + ")");
|
||||
}
|
||||
whitelistForAugmentedAutofillPackages(packages);
|
||||
whitelistForAugmentedAutofillPackages(packages, activities);
|
||||
|
||||
// TODO(b/123100824): whitelist activities as well
|
||||
// TODO(b/122858578): log metrics
|
||||
return true;
|
||||
}
|
||||
@@ -1171,28 +1166,30 @@ final class AutofillManagerServiceImpl
|
||||
|
||||
@GuardedBy("mLock")
|
||||
boolean isWhitelistedForAugmentedAutofillLocked(@NonNull ComponentName componentName) {
|
||||
// TODO(b/122595322): need to check whitelisted activities as well.
|
||||
final String packageName = componentName.getPackageName();
|
||||
return mWhitelistedAugmentAutofillPackages.contains(packageName);
|
||||
return mAugmentedWhitelistHelper.isWhitelisted(componentName);
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
void setAugmentedAutofillWhitelistLocked(@NonNull AutofillOptions options,
|
||||
@NonNull String packageName) {
|
||||
// TODO(b/122595322): need to setwhitelisted activities as well.
|
||||
options.augmentedEnabled = mWhitelistedAugmentAutofillPackages.contains(packageName);
|
||||
options.augmentedAutofillEnabled = mAugmentedWhitelistHelper.isWhitelisted(packageName);
|
||||
options.whitelistedActivitiesForAugmentedAutofill = mAugmentedWhitelistHelper
|
||||
.getWhitelistedComponents(packageName);
|
||||
}
|
||||
|
||||
private void whitelistForAugmentedAutofillPackages(@NonNull List<String> packages) {
|
||||
/**
|
||||
*
|
||||
* @throws IllegalArgumentException if packages or components are empty.
|
||||
*/
|
||||
private void whitelistForAugmentedAutofillPackages(@Nullable List<String> packages,
|
||||
@Nullable List<ComponentName> components) {
|
||||
// TODO(b/123100824): add CTS test for when it's null
|
||||
synchronized (mLock) {
|
||||
if (packages == null) {
|
||||
if (mMaster.verbose) Slog.v(TAG, "clearing all whitelisted augmented packages");
|
||||
mWhitelistedAugmentAutofillPackages.clear();
|
||||
} else {
|
||||
if (mMaster.verbose) Slog.v(TAG, "whitelisting augmented packages: " + packages);
|
||||
mWhitelistedAugmentAutofillPackages.addAll(packages);
|
||||
if (mMaster.verbose) {
|
||||
Slog.v(TAG, "whitelisting packages: " + packages + "and activities: " + components);
|
||||
}
|
||||
mAugmentedWhitelistHelper.setWhitelist(new ArraySet<>(packages),
|
||||
new ArraySet<>(components));
|
||||
mRemoteAugmentedAutofillService = getRemoteAugmentedAutofillServiceLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ import static android.service.contentcapture.ContentCaptureService.setClientStat
|
||||
import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED;
|
||||
import static android.view.contentcapture.ContentCaptureSession.STATE_DUPLICATED_ID;
|
||||
import static android.view.contentcapture.ContentCaptureSession.STATE_INTERNAL_ERROR;
|
||||
import static android.view.contentcapture.ContentCaptureSession.STATE_NOT_WHITELISTED;
|
||||
import static android.view.contentcapture.ContentCaptureSession.STATE_NO_SERVICE;
|
||||
import static android.view.contentcapture.ContentCaptureSession.STATE_PACKAGE_NOT_WHITELISTED;
|
||||
|
||||
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
|
||||
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
|
||||
@@ -29,6 +29,7 @@ import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUC
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.ActivityManagerInternal;
|
||||
import android.app.AppGlobals;
|
||||
@@ -55,6 +56,7 @@ import android.util.Slog;
|
||||
import android.view.contentcapture.UserDataRemovalRequest;
|
||||
|
||||
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;
|
||||
@@ -94,7 +96,7 @@ final class ContentCapturePerUserService
|
||||
* List of packages that are whitelisted to be content captured.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private final ArraySet<String> mWhitelistedPackages = new ArraySet<>();
|
||||
private final WhitelistHelper mWhitelistHelper = new WhitelistHelper();
|
||||
|
||||
// TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
|
||||
|
||||
@@ -194,7 +196,7 @@ final class ContentCapturePerUserService
|
||||
final int taskId = activityPresentationInfo.taskId;
|
||||
final int displayId = activityPresentationInfo.displayId;
|
||||
final ComponentName componentName = activityPresentationInfo.componentName;
|
||||
final boolean whitelisted = isWhitelistedLocked(componentName);
|
||||
final boolean whiteListed = isWhitelistedLocked(componentName);
|
||||
final ComponentName serviceComponentName = getServiceComponentName();
|
||||
final boolean enabled = isEnabledLocked();
|
||||
if (mMaster.mRequestsHistory != null) {
|
||||
@@ -204,7 +206,7 @@ final class ContentCapturePerUserService
|
||||
+ " t=" + taskId + " d=" + displayId
|
||||
+ " s=" + ComponentName.flattenToShortString(serviceComponentName)
|
||||
+ " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)")
|
||||
+ " w=" + whitelisted;
|
||||
+ " w=" + whiteListed;
|
||||
mMaster.mRequestsHistory.log(historyItem);
|
||||
}
|
||||
|
||||
@@ -225,12 +227,12 @@ final class ContentCapturePerUserService
|
||||
return;
|
||||
}
|
||||
|
||||
if (!whitelisted) {
|
||||
if (!whiteListed) {
|
||||
if (mMaster.debug) {
|
||||
Slog.d(TAG, "startSession(" + componentName + "): not whitelisted");
|
||||
Slog.d(TAG, "startSession(" + componentName + "): package or component "
|
||||
+ "not whitelisted");
|
||||
}
|
||||
// TODO(b/122595322): need to return STATE_ACTIVITY_NOT_WHITELISTED as well
|
||||
setClientState(clientReceiver, STATE_DISABLED | STATE_PACKAGE_NOT_WHITELISTED,
|
||||
setClientState(clientReceiver, STATE_DISABLED | STATE_NOT_WHITELISTED,
|
||||
/* binder= */ null);
|
||||
return;
|
||||
}
|
||||
@@ -270,21 +272,20 @@ final class ContentCapturePerUserService
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private boolean isWhitelistedLocked(@NonNull ComponentName componentName) {
|
||||
// TODO(b/122595322): need to check whitelisted activities as well.
|
||||
final String packageName = componentName.getPackageName();
|
||||
return mWhitelistedPackages.contains(packageName);
|
||||
return mWhitelistHelper.isWhitelisted(componentName);
|
||||
}
|
||||
|
||||
private void whitelistPackages(@NonNull List<String> packages) {
|
||||
/**
|
||||
* @throws IllegalArgumentException if packages or components are empty.
|
||||
*/
|
||||
private void setWhitelist(@Nullable List<String> packages,
|
||||
@Nullable List<ComponentName> components) {
|
||||
// TODO(b/122595322): add CTS test for when it's null
|
||||
synchronized (mLock) {
|
||||
if (packages == null) {
|
||||
if (mMaster.verbose) Slog.v(TAG, "clearing all whitelisted packages");
|
||||
mWhitelistedPackages.clear();
|
||||
} else {
|
||||
if (mMaster.verbose) Slog.v(TAG, "whitelisting packages: " + packages);
|
||||
mWhitelistedPackages.addAll(packages);
|
||||
if (mMaster.verbose) {
|
||||
Slog.v(TAG, "whitelisting packages: " + packages + "and activities: " + components);
|
||||
}
|
||||
mWhitelistHelper.setWhitelist(new ArraySet<>(packages), new ArraySet<>(components));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -411,15 +412,15 @@ final class ContentCapturePerUserService
|
||||
|
||||
@GuardedBy("mLock")
|
||||
ContentCaptureOptions getOptionsForPackageLocked(@NonNull String packageName) {
|
||||
if (!mWhitelistedPackages.contains(packageName)) {
|
||||
if (!mWhitelistHelper.isWhitelisted(packageName)) {
|
||||
if (mMaster.verbose) {
|
||||
Slog.v(mTag, "getOptionsForPackage(" + packageName + "): not whitelisted");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO(b/122595322): need to check whitelisted activities as well.
|
||||
final ArraySet<ComponentName> whitelistedComponents = null;
|
||||
final ArraySet<ComponentName> whitelistedComponents = mWhitelistHelper
|
||||
.getWhitelistedComponents(packageName);
|
||||
ContentCaptureOptions options = new ContentCaptureOptions(mMaster.mDevCfgLoggingLevel,
|
||||
mMaster.mDevCfgMaxBufferSize, mMaster.mDevCfgIdleFlushingFrequencyMs,
|
||||
mMaster.mDevCfgTextChangeFlushingFrequencyMs, mMaster.mDevCfgLogHistorySize,
|
||||
@@ -440,12 +441,7 @@ final class ContentCapturePerUserService
|
||||
mRemoteService.dump(prefix2, pw);
|
||||
}
|
||||
|
||||
final int whitelistSize = mWhitelistedPackages.size();
|
||||
pw.print(prefix); pw.print("Whitelisted packages: "); pw.println(whitelistSize);
|
||||
for (int i = 0; i < whitelistSize; i++) {
|
||||
final String whitelistedPkg = mWhitelistedPackages.valueAt(i);
|
||||
pw.print(prefix2); pw.print(i + 1); pw.print(": "); pw.println(whitelistedPkg);
|
||||
}
|
||||
pw.print(prefix); pw.print("Whitelist: "); pw.println(mWhitelistHelper);
|
||||
|
||||
if (mSessions.isEmpty()) {
|
||||
pw.print(prefix); pw.println("no sessions");
|
||||
@@ -485,9 +481,8 @@ final class ContentCapturePerUserService
|
||||
Slog.v(TAG, "setContentCaptureWhitelist(packages=" + packages + ", activities="
|
||||
+ activities + ")");
|
||||
}
|
||||
whitelistPackages(packages);
|
||||
setWhitelist(packages, activities);
|
||||
|
||||
// TODO(b/122595322): whitelist activities as well
|
||||
// TODO(b/119613670): log metrics
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user