Update framework from jetpack.

Changes included:
* 79f2ffe: Fixes required for export.
* e1ca63a: Implement empty schema shouldn't have a version number.
* 8b76be4: Refactor VisibilityStore from a no-op implementation into an interface.
* 47ba533: Remove the max repeatable length limit for GenericDocument
* 52ca287: Add GetSchemaResponse cts test.
* 56585f5: Change PutDocumentsRequestTest to be a cts test.

Bug: 183050495
Bug: 180058203
Bug: 191592792
Bug: 189161227
Bug: 183239766
Test: Presubmit
Change-Id: I30f51a18d697d3a5e43d2c63549ab19a36bbe99e
This commit is contained in:
Alexander Dorokhine
2021-06-22 12:32:15 -07:00
parent ec801cc398
commit bb978dfe38
12 changed files with 113 additions and 135 deletions

View File

@@ -50,9 +50,6 @@ import java.util.Set;
public class GenericDocument {
private static final String TAG = "AppSearchGenericDocumen";
/** The maximum number of elements in a repeatable field. */
private static final int MAX_REPEATED_PROPERTY_LENGTH = 100;
/** The maximum {@link String#length} of a {@link String} field. */
private static final int MAX_STRING_LENGTH = 20_000;
@@ -1187,8 +1184,8 @@ public class GenericDocument {
* @param name the name associated with the {@code values}. Must match the name for this
* property as given in {@link AppSearchSchema.PropertyConfig#getName}.
* @param values the {@code String} values of the property.
* @throws IllegalArgumentException if no values are provided, if provided values exceed
* maximum repeated property length, or if a passed in {@code String} is {@code null}.
* @throws IllegalArgumentException if no values are provided, or if a passed in {@code
* String} is {@code null}.
*/
@NonNull
public BuilderType setPropertyString(@NonNull String name, @NonNull String... values) {
@@ -1206,7 +1203,6 @@ public class GenericDocument {
* @param name the name associated with the {@code values}. Must match the name for this
* property as given in {@link AppSearchSchema.PropertyConfig#getName}.
* @param values the {@code boolean} values of the property.
* @throws IllegalArgumentException if values exceed maximum repeated property length.
*/
@NonNull
public BuilderType setPropertyBoolean(@NonNull String name, @NonNull boolean... values) {
@@ -1223,7 +1219,6 @@ public class GenericDocument {
* @param name the name associated with the {@code values}. Must match the name for this
* property as given in {@link AppSearchSchema.PropertyConfig#getName}.
* @param values the {@code long} values of the property.
* @throws IllegalArgumentException if values exceed maximum repeated property length.
*/
@NonNull
public BuilderType setPropertyLong(@NonNull String name, @NonNull long... values) {
@@ -1240,7 +1235,6 @@ public class GenericDocument {
* @param name the name associated with the {@code values}. Must match the name for this
* property as given in {@link AppSearchSchema.PropertyConfig#getName}.
* @param values the {@code double} values of the property.
* @throws IllegalArgumentException if values exceed maximum repeated property length.
*/
@NonNull
public BuilderType setPropertyDouble(@NonNull String name, @NonNull double... values) {
@@ -1257,8 +1251,8 @@ public class GenericDocument {
* @param name the name associated with the {@code values}. Must match the name for this
* property as given in {@link AppSearchSchema.PropertyConfig#getName}.
* @param values the {@code byte[]} of the property.
* @throws IllegalArgumentException if no values are provided, if provided values exceed
* maximum repeated property length, or if a passed in {@code byte[]} is {@code null}.
* @throws IllegalArgumentException if no values are provided, or if a passed in {@code
* byte[]} is {@code null}.
*/
@NonNull
public BuilderType setPropertyBytes(@NonNull String name, @NonNull byte[]... values) {
@@ -1276,8 +1270,7 @@ public class GenericDocument {
* @param name the name associated with the {@code values}. Must match the name for this
* property as given in {@link AppSearchSchema.PropertyConfig#getName}.
* @param values the {@link GenericDocument} values of the property.
* @throws IllegalArgumentException if no values are provided, if provided values exceed if
* provided values exceed maximum repeated property length, or if a passed in {@link
* @throws IllegalArgumentException if no values are provided, or if a passed in {@link
* GenericDocument} is {@code null}.
*/
@NonNull
@@ -1308,7 +1301,6 @@ public class GenericDocument {
private void putInPropertyBundle(@NonNull String name, @NonNull String[] values)
throws IllegalArgumentException {
validateRepeatedPropertyLength(name, values.length);
for (int i = 0; i < values.length; i++) {
if (values[i] == null) {
throw new IllegalArgumentException("The String at " + i + " is null.");
@@ -1327,17 +1319,14 @@ public class GenericDocument {
}
private void putInPropertyBundle(@NonNull String name, @NonNull boolean[] values) {
validateRepeatedPropertyLength(name, values.length);
mProperties.putBooleanArray(name, values);
}
private void putInPropertyBundle(@NonNull String name, @NonNull double[] values) {
validateRepeatedPropertyLength(name, values.length);
mProperties.putDoubleArray(name, values);
}
private void putInPropertyBundle(@NonNull String name, @NonNull long[] values) {
validateRepeatedPropertyLength(name, values.length);
mProperties.putLongArray(name, values);
}
@@ -1348,7 +1337,6 @@ public class GenericDocument {
* into ArrayList<Bundle>, and each elements will contain a one dimension byte[].
*/
private void putInPropertyBundle(@NonNull String name, @NonNull byte[][] values) {
validateRepeatedPropertyLength(name, values.length);
ArrayList<Bundle> bundles = new ArrayList<>(values.length);
for (int i = 0; i < values.length; i++) {
if (values[i] == null) {
@@ -1362,7 +1350,6 @@ public class GenericDocument {
}
private void putInPropertyBundle(@NonNull String name, @NonNull GenericDocument[] values) {
validateRepeatedPropertyLength(name, values.length);
Parcelable[] documentBundles = new Parcelable[values.length];
for (int i = 0; i < values.length; i++) {
if (values[i] == null) {
@@ -1373,18 +1360,6 @@ public class GenericDocument {
mProperties.putParcelableArray(name, documentBundles);
}
private static void validateRepeatedPropertyLength(@NonNull String name, int length) {
if (length > MAX_REPEATED_PROPERTY_LENGTH) {
throw new IllegalArgumentException(
"Repeated property \""
+ name
+ "\" has length "
+ length
+ ", which exceeds the limit of "
+ MAX_REPEATED_PROPERTY_LENGTH);
}
}
/** Builds the {@link GenericDocument} object. */
@NonNull
public GenericDocument build() {

View File

@@ -169,13 +169,14 @@ public final class SetSchemaRequest {
/** Builder for {@link SetSchemaRequest} objects. */
public static final class Builder {
private static final int DEFAULT_VERSION = 1;
private ArraySet<AppSearchSchema> mSchemas = new ArraySet<>();
private ArraySet<String> mSchemasNotDisplayedBySystem = new ArraySet<>();
private ArrayMap<String, Set<PackageIdentifier>> mSchemasVisibleToPackages =
new ArrayMap<>();
private ArrayMap<String, Migrator> mMigrators = new ArrayMap<>();
private boolean mForceOverride = false;
private int mVersion = 1;
private int mVersion = DEFAULT_VERSION;
private boolean mBuilt = false;
/**
@@ -384,6 +385,9 @@ public final class SetSchemaRequest {
* <p>The version number can stay the same, increase, or decrease relative to the current
* version number that is already stored in the {@link AppSearchSession} database.
*
* <p>The version of an empty database will always be 0. You cannot set version to the
* {@link SetSchemaRequest}, if it doesn't contains any {@link AppSearchSchema}.
*
* @param version A positive integer representing the version of the entire set of schemas
* represents the version of the whole schema in the {@link AppSearchSession} database,
* default version is 1.
@@ -423,7 +427,10 @@ public final class SetSchemaRequest {
throw new IllegalArgumentException(
"Schema types " + referencedSchemas + " referenced, but were not added.");
}
if (mSchemas.isEmpty() && mVersion != DEFAULT_VERSION) {
throw new IllegalArgumentException(
"Cannot set version to the request if schema is empty.");
}
mBuilt = true;
return new SetSchemaRequest(
mSchemas,

View File

@@ -60,8 +60,8 @@ import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalManagerRegistry;
import com.android.server.SystemService;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
import com.android.server.appsearch.util.PackageUtil;
import com.android.server.appsearch.visibilitystore.VisibilityStore;
import com.android.server.usage.StorageStatsManagerLocal;
import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;

View File

@@ -19,7 +19,7 @@ import android.annotation.NonNull;
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
import com.android.server.appsearch.stats.PlatformLogger;
import com.android.server.appsearch.visibilitystore.VisibilityStore;
import com.android.server.appsearch.visibilitystore.VisibilityStoreImpl;
import java.util.Objects;
@@ -30,12 +30,12 @@ import java.util.Objects;
public final class AppSearchUserInstance {
private final PlatformLogger mLogger;
private final AppSearchImpl mAppSearchImpl;
private final VisibilityStore mVisibilityStore;
private final VisibilityStoreImpl mVisibilityStore;
AppSearchUserInstance(
@NonNull PlatformLogger logger,
@NonNull AppSearchImpl appSearchImpl,
@NonNull VisibilityStore visibilityStore) {
@NonNull VisibilityStoreImpl visibilityStore) {
mLogger = Objects.requireNonNull(logger);
mAppSearchImpl = Objects.requireNonNull(appSearchImpl);
mVisibilityStore = Objects.requireNonNull(visibilityStore);
@@ -52,7 +52,7 @@ public final class AppSearchUserInstance {
}
@NonNull
public VisibilityStore getVisibilityStore() {
public VisibilityStoreImpl getVisibilityStore() {
return mVisibilityStore;
}
}

View File

@@ -30,7 +30,7 @@ import com.android.server.appsearch.external.localstorage.AppSearchImpl;
import com.android.server.appsearch.external.localstorage.FrameworkOptimizeStrategy;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
import com.android.server.appsearch.stats.PlatformLogger;
import com.android.server.appsearch.visibilitystore.VisibilityStore;
import com.android.server.appsearch.visibilitystore.VisibilityStoreImpl;
import java.io.File;
import java.util.Map;
@@ -178,7 +178,8 @@ public final class AppSearchUserInstanceManager {
AppSearchImpl.create(icingDir, initStatsBuilder, new FrameworkOptimizeStrategy());
long prepareVisibilityStoreLatencyStartMillis = SystemClock.elapsedRealtime();
VisibilityStore visibilityStore = VisibilityStore.create(appSearchImpl, userContext);
VisibilityStoreImpl visibilityStore =
VisibilityStoreImpl.create(appSearchImpl, userContext);
long prepareVisibilityStoreLatencyEndMillis = SystemClock.elapsedRealtime();
initStatsBuilder

View File

@@ -58,7 +58,7 @@ import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
import com.android.server.appsearch.visibilitystore.VisibilityStore;
import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
import com.google.android.icing.IcingSearchEngine;
import com.google.android.icing.proto.DeleteByQueryResultProto;

View File

@@ -0,0 +1,72 @@
/*
* Copyright 2021 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.appsearch.external.localstorage.visibilitystore;
import android.annotation.NonNull;
import android.app.appsearch.PackageIdentifier;
import android.app.appsearch.exceptions.AppSearchException;
import com.android.internal.annotations.VisibleForTesting;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* An interface for classes that store and validate document visibility data.
*
* @hide
*/
public interface VisibilityStore {
/**
* These cannot have any of the special characters used by AppSearchImpl (e.g. {@code
* AppSearchImpl#PACKAGE_DELIMITER} or {@code AppSearchImpl#DATABASE_DELIMITER}.
*/
String PACKAGE_NAME = "VS#Pkg";
@VisibleForTesting String DATABASE_NAME = "VS#Db";
/**
* Sets visibility settings for the given database. Any previous visibility settings will be
* overwritten.
*
* @param packageName Package of app that owns the schemas.
* @param databaseName Database that owns the schemas.
* @param schemasNotDisplayedBySystem Set of prefixed schemas that should be hidden from
* platform surfaces.
* @param schemasVisibleToPackages Map of prefixed schemas to a list of package identifiers that
* have access to the schema.
* @throws AppSearchException on AppSearchImpl error.
*/
void setVisibility(
@NonNull String packageName,
@NonNull String databaseName,
@NonNull Set<String> schemasNotDisplayedBySystem,
@NonNull Map<String, List<PackageIdentifier>> schemasVisibleToPackages)
throws AppSearchException;
/**
* Checks whether the given package has access to system-surfaceable schemas.
*
* @param callerUid UID of the app that wants to see the data.
*/
boolean isSchemaSearchableByCaller(
@NonNull String packageName,
@NonNull String databaseName,
@NonNull String prefixedSchema,
int callerUid,
boolean callerHasSystemAccess);
}

View File

@@ -30,9 +30,9 @@ import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
import com.android.server.appsearch.util.PackageUtil;
import com.google.android.icing.proto.PersistType;
@@ -60,23 +60,12 @@ import java.util.Set;
* <p>This class doesn't handle any locking itself. Its callers should handle the locking at a
* higher level.
*
* <p>NOTE: This class holds an instance of AppSearchImpl and AppSearchImpl holds an instance of
* this class. Take care to not cause any circular dependencies.
*
* @hide
*/
public class VisibilityStore {
public class VisibilityStoreImpl implements VisibilityStore {
/** Version for the visibility schema */
private static final int SCHEMA_VERSION = 0;
/**
* These cannot have any of the special characters used by AppSearchImpl (e.g. {@code
* AppSearchImpl#PACKAGE_DELIMITER} or {@code AppSearchImpl#DATABASE_DELIMITER}.
*/
public static final String PACKAGE_NAME = "VS#Pkg";
@VisibleForTesting public static final String DATABASE_NAME = "VS#Db";
/** Namespace of documents that contain visibility settings */
private static final String NAMESPACE = "";
@@ -101,13 +90,13 @@ public class VisibilityStore {
* @param userContext Context of the user that the call is being made as
*/
@NonNull
public static VisibilityStore create(
public static VisibilityStoreImpl create(
@NonNull AppSearchImpl appSearchImpl, @NonNull Context userContext)
throws AppSearchException {
return new VisibilityStore(appSearchImpl, userContext);
return new VisibilityStoreImpl(appSearchImpl, userContext);
}
private VisibilityStore(@NonNull AppSearchImpl appSearchImpl, @NonNull Context userContext)
private VisibilityStoreImpl(@NonNull AppSearchImpl appSearchImpl, @NonNull Context userContext)
throws AppSearchException {
mAppSearchImpl = Objects.requireNonNull(appSearchImpl);
mUserContext = Objects.requireNonNull(userContext);
@@ -207,18 +196,7 @@ public class VisibilityStore {
}
}
/**
* Sets visibility settings for the given database. Any previous visibility settings will be
* overwritten.
*
* @param packageName Package of app that owns the schemas.
* @param databaseName Database that owns the schemas.
* @param schemasNotDisplayedBySystem Set of prefixed schemas that should be hidden from the
* platform.
* @param schemasVisibleToPackages Map of prefixed schemas to a list of package identifiers that
* have access to the schema.
* @throws AppSearchException on AppSearchImpl error.
*/
@Override
public void setVisibility(
@NonNull String packageName,
@NonNull String databaseName,
@@ -282,17 +260,7 @@ public class VisibilityStore {
== PackageManager.PERMISSION_GRANTED;
}
/**
* Checks whether {@code prefixedSchema} can be searched over by the {@code callerUid}.
*
* @param packageName Package that owns the schema.
* @param databaseName Database within the package that owns the schema.
* @param prefixedSchema Prefixed schema type the caller is trying to access.
* @param callerUid UID of the client making the globalQuery call.
* @param callerHasSystemAccess Whether the caller has been identified as having
* access to schemas marked system surfaceable by {@link
* #doesCallerHaveSystemAccess}.
*/
@Override
public boolean isSchemaSearchableByCaller(
@NonNull String packageName,
@NonNull String databaseName,

View File

@@ -1 +1 @@
04351b43fbbf9d59ffeae41903322023931c84f2
a11281766f66aa4919e9bbe70da95919ce054c35

View File

@@ -1,44 +0,0 @@
/*
* Copyright 2020 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.app.appsearch;
import static com.google.common.truth.Truth.assertThat;
import com.android.server.appsearch.testing.AppSearchEmail;
import com.google.common.collect.ImmutableSet;
import org.junit.Test;
import java.util.Set;
public class PutDocumentsRequestTest {
@Test
public void addGenericDocument_byCollection() {
Set<AppSearchEmail> emails =
ImmutableSet.of(
new AppSearchEmail.Builder("namespace", "test1").build(),
new AppSearchEmail.Builder("namespace", "test2").build());
PutDocumentsRequest request =
new PutDocumentsRequest.Builder().addGenericDocuments(emails).build();
assertThat(request.getGenericDocuments().get(0).getId()).isEqualTo("test1");
assertThat(request.getGenericDocuments().get(1).getId()).isEqualTo("test2");
}
}

View File

@@ -42,7 +42,7 @@ import androidx.test.core.app.ApplicationProvider;
import com.android.compatibility.common.util.SystemUtil;
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
import com.android.server.appsearch.visibilitystore.VisibilityStore;
import com.android.server.appsearch.visibilitystore.VisibilityStoreImpl;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -67,7 +67,7 @@ public class AppSearchImplPlatformTest {
private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
private Context mContext;
private AppSearchImpl mAppSearchImpl;
private VisibilityStore mVisibilityStore;
private VisibilityStoreImpl mVisibilityStore;
private int mGlobalQuerierUid;
@Before
@@ -93,7 +93,7 @@ public class AppSearchImplPlatformTest {
// Give ourselves global query permissions
mAppSearchImpl = AppSearchImpl.create(
mTemporaryFolder.newFolder(), /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
mVisibilityStore = VisibilityStore.create(mAppSearchImpl, mContext);
mVisibilityStore = VisibilityStoreImpl.create(mAppSearchImpl, mContext);
mGlobalQuerierUid =
mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
}

View File

@@ -14,10 +14,7 @@
* limitations under the License.
*/
// TODO(b/169883602): This is purposely a different package from the path so that it can access
// AppSearchImpl methods without having to make methods public. This should be moved into a proper
// package once AppSearchImpl-VisibilityStore's dependencies are refactored.
package com.android.server.appsearch.external.localstorage;
package com.android.server.appsearch.visibilitystore;
import static android.Manifest.permission.READ_GLOBAL_APP_SEARCH_DATA;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
@@ -39,8 +36,10 @@ import android.util.ArrayMap;
import androidx.test.core.app.ApplicationProvider;
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
import com.android.server.appsearch.external.localstorage.OptimizeStrategy;
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
import com.android.server.appsearch.visibilitystore.VisibilityStore;
import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -55,7 +54,7 @@ import org.mockito.Mockito;
import java.util.Collections;
import java.util.Map;
public class VisibilityStoreTest {
public class VisibilityStoreImplTest {
/**
* Always trigger optimize in this class. OptimizeStrategy will be tested in its own test class.
*/
@@ -64,7 +63,7 @@ public class VisibilityStoreTest {
@Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
private Context mContext;
private VisibilityStore mVisibilityStore;
private VisibilityStoreImpl mVisibilityStore;
private int mUid;
@Before
@@ -90,7 +89,7 @@ public class VisibilityStoreTest {
// Give ourselves global query permissions
AppSearchImpl appSearchImpl = AppSearchImpl.create(
mTemporaryFolder.newFolder(), /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
mVisibilityStore = VisibilityStore.create(appSearchImpl, mContext);
mVisibilityStore = VisibilityStoreImpl.create(appSearchImpl, mContext);
mUid = mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
}