Remove package certificate from ContactsIndexerTests
- Refactor ContactsIndexerConfig into an interface and add a test
implementation that returns only default values which can be used for
tests that don't need the READ_DEVICE_CONFIG permission.
- Remove INTERACT_ACROSS_USERS_FULL and READ_DEVICE_CONFIG permissions
since they are privileged.
- Remove the platform certificate since this is not allowed in MTS.
- Move the tests to the general-tests suite now that the issues making
it device-specific are resolved.
Bug: 203690505
Bug: 229203989
Test: ContactsIndexerTests
Change-Id: Idd171751580a21128b9c2986e8784ca340af06d3
diff --git a/service/java/com/android/server/appsearch/AppSearchModule.java b/service/java/com/android/server/appsearch/AppSearchModule.java
index 41ec91b..9e7fe95 100644
--- a/service/java/com/android/server/appsearch/AppSearchModule.java
+++ b/service/java/com/android/server/appsearch/AppSearchModule.java
@@ -25,6 +25,7 @@
import com.android.server.SystemService;
import com.android.server.appsearch.contactsindexer.ContactsIndexerConfig;
+import com.android.server.appsearch.contactsindexer.FrameworkContactsIndexerConfig;
import com.android.server.appsearch.contactsindexer.ContactsIndexerManagerService;
import java.io.File;
@@ -69,8 +70,10 @@
// It is safe to check DeviceConfig here, since SettingsProvider, which DeviceConfig
// uses, starts before AppSearch.
- if (ContactsIndexerConfig.isContactsIndexerEnabled()) {
- mContactsIndexerManagerService = new ContactsIndexerManagerService(getContext());
+ ContactsIndexerConfig contactsIndexerConfig = new FrameworkContactsIndexerConfig();
+ if (contactsIndexerConfig.isContactsIndexerEnabled()) {
+ mContactsIndexerManagerService = new ContactsIndexerManagerService(getContext(),
+ contactsIndexerConfig);
try {
mContactsIndexerManagerService.onStart();
} catch (Throwable t) {
diff --git a/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerConfig.java b/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerConfig.java
index 8089c7d..9544557 100644
--- a/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerConfig.java
+++ b/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerConfig.java
@@ -16,67 +16,50 @@
package com.android.server.appsearch.contactsindexer;
-import android.provider.DeviceConfig;
-
import java.util.concurrent.TimeUnit;
/**
- * Contains all the keys for flags related to Contacts Indexer.
+ * An interface which exposes config flags to Contacts Indexer.
+ *
+ * <p>Implementations of this interface must be thread-safe.
*
* @hide
*/
-public class ContactsIndexerConfig {
- // LIMIT of -1 means no upper bound (see https://www.sqlite.org/lang_select.html)
- public static final int UPDATE_LIMIT_NONE = -1;
+public interface ContactsIndexerConfig {
+ boolean DEFAULT_CONTACTS_INDEXER_ENABLED = true;
+ int DEFAULT_CONTACTS_FIRST_RUN_INDEXING_LIMIT = 1000;
+ long DEFAULT_CONTACTS_FULL_UPDATE_INTERVAL_MILLIS = TimeUnit.DAYS.toMillis(30); // 30 days.
+ int DEFAULT_CONTACTS_FULL_UPDATE_INDEXING_LIMIT = 10_000;
+ int DEFAULT_CONTACTS_DELTA_UPDATE_INDEXING_LIMIT = 1000;
- private static final String KEY_CONTACTS_INSTANT_INDEXING_LIMIT =
- "contacts_instant_indexing_limit";
- public static final String KEY_CONTACTS_INDEXER_ENABLED = "contacts_indexer_enabled";
- public static final String KEY_CONTACTS_FULL_UPDATE_INTERVAL_MILLIS
- = "contacts_full_update_interval_millis";
- public static final String KEY_CONTACTS_FULL_UPDATE_LIMIT =
- "contacts_indexer_full_update_limit";
- public static final String KEY_CONTACTS_DELTA_UPDATE_LIMIT =
- "contacts_indexer_delta_update_limit";
+ /** Returns whether Contacts Indexer is enabled. */
+ boolean isContactsIndexerEnabled();
- public static boolean isContactsIndexerEnabled() {
- return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_APPSEARCH,
- KEY_CONTACTS_INDEXER_ENABLED,
- /*defaultValue=*/ true);
- }
+ /**
+ * Returns the maximum number of CP2 contacts indexed during first run.
+ *
+ * <p>This value will limit the amount of processing performed when the device upgrades from
+ * Android S to T with Contacts Indexer enabled.
+ */
+ int getContactsFirstRunIndexingLimit();
- public static int getContactsInstantIndexingLimit() {
- return DeviceConfig.getInt(DeviceConfig.NAMESPACE_APPSEARCH,
- KEY_CONTACTS_INSTANT_INDEXING_LIMIT, /*defaultValue=*/ 1000);
- }
-
- public static long getContactsFullUpdateIntervalMillis() {
- return DeviceConfig.getLong(DeviceConfig.NAMESPACE_APPSEARCH,
- KEY_CONTACTS_FULL_UPDATE_INTERVAL_MILLIS,
- /*defaultValue=*/ TimeUnit.DAYS.toMillis(30));
- }
+ /**
+ * Returns the minimum internal in millis for two consecutive full update. This is only checked
+ * once after reach boot.
+ */
+ long getContactsFullUpdateIntervalMillis();
/**
* Returns the maximum number of CP2 contacts indexed during a full update.
*
* <p>The value will be used as a LIMIT for querying CP2 during full update.
*/
- public static int getContactsFullUpdateLimit() {
- return DeviceConfig.getInt(DeviceConfig.NAMESPACE_APPSEARCH,
- KEY_CONTACTS_FULL_UPDATE_LIMIT,
- /*defaultValue=*/ 10_000);
- }
+ int getContactsFullUpdateLimit();
/**
* Returns the maximum number of CP2 contacts indexed during a delta update.
*
* <p>The value will be used as a LIMIT for querying CP2 during the delta update.
*/
- public static int getContactsDeltaUpdateLimit() {
- // TODO(b/227419499) Based on the metrics, we can tweak this number. Right now it is same
- // as the instant indexing limit, which is 1,000. From our stats in GMSCore, 95th
- // percentile for number of contacts on the device is around 2000 contacts.
- return DeviceConfig.getInt(DeviceConfig.NAMESPACE_APPSEARCH,
- KEY_CONTACTS_DELTA_UPDATE_LIMIT, /*defaultValue=*/ 1000);
- }
+ int getContactsDeltaUpdateLimit();
}
diff --git a/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerManagerService.java b/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerManagerService.java
index f83133a..f9bff4f 100644
--- a/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerManagerService.java
+++ b/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerManagerService.java
@@ -56,6 +56,7 @@
"com.android.providers.contacts";
private final Context mContext;
+ private final ContactsIndexerConfig mContactsIndexerConfig;
private final LocalService mLocalService;
// Sparse array of ContactsIndexerUserInstance indexed by the device-user ID.
private final SparseArray<ContactsIndexerUserInstance> mContactsIndexersLocked =
@@ -64,9 +65,11 @@
private String mContactsProviderPackageName;
/** Constructs a {@link ContactsIndexerManagerService}. */
- public ContactsIndexerManagerService(@NonNull Context context) {
+ public ContactsIndexerManagerService(@NonNull Context context,
+ @NonNull ContactsIndexerConfig contactsIndexerConfig) {
super(context);
mContext = Objects.requireNonNull(context);
+ mContactsIndexerConfig = Objects.requireNonNull(contactsIndexerConfig);
mLocalService = new LocalService();
}
@@ -89,7 +92,8 @@
File appSearchDir = AppSearchModule.getAppSearchDir(userHandle);
File contactsDir = new File(appSearchDir, "contacts");
try {
- instance = ContactsIndexerUserInstance.createInstance(userContext, contactsDir);
+ instance = ContactsIndexerUserInstance.createInstance(userContext, contactsDir,
+ mContactsIndexerConfig);
Log.d(TAG, "Created Contacts Indexer instance for user " + userHandle);
} catch (Throwable t) {
Log.e(TAG, "Failed to create Contacts Indexer instance for user "
diff --git a/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerUserInstance.java b/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerUserInstance.java
index 29fb34d..7acb633 100644
--- a/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerUserInstance.java
+++ b/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerUserInstance.java
@@ -67,6 +67,7 @@
private final AppSearchHelper mAppSearchHelper;
private final ContactsIndexerImpl mContactsIndexerImpl;
+ private final ContactsIndexerConfig mContactsIndexerConfig;
/**
* Single threaded executor to make sure there is only one active sync for this {@link
@@ -83,27 +84,30 @@
*/
@NonNull
public static ContactsIndexerUserInstance createInstance(@NonNull Context userContext,
- @NonNull File contactsDir) {
+ @NonNull File contactsDir, @NonNull ContactsIndexerConfig contactsIndexerConfig) {
Objects.requireNonNull(userContext);
Objects.requireNonNull(contactsDir);
+ Objects.requireNonNull(contactsIndexerConfig);
ExecutorService singleThreadedExecutor = Executors.newSingleThreadExecutor();
- return createInstance(userContext, contactsDir, singleThreadedExecutor);
+ return createInstance(userContext, contactsDir, contactsIndexerConfig,
+ singleThreadedExecutor);
}
@VisibleForTesting
@NonNull
/*package*/ static ContactsIndexerUserInstance createInstance(@NonNull Context context,
- @NonNull File contactsDir,
+ @NonNull File contactsDir, @NonNull ContactsIndexerConfig contactsIndexerConfig,
@NonNull ExecutorService executorService) {
Objects.requireNonNull(context);
Objects.requireNonNull(contactsDir);
+ Objects.requireNonNull(contactsIndexerConfig);
Objects.requireNonNull(executorService);
AppSearchHelper appSearchHelper = AppSearchHelper.createAppSearchHelper(context,
executorService);
ContactsIndexerUserInstance indexer = new ContactsIndexerUserInstance(context,
- contactsDir, appSearchHelper, executorService);
+ contactsDir, appSearchHelper, contactsIndexerConfig, executorService);
indexer.loadSettingsAsync();
return indexer;
@@ -112,17 +116,20 @@
/**
* Constructs a {@link ContactsIndexerUserInstance}.
*
- * @param context Context object passed from
- * {@link ContactsIndexerManagerService}
- * @param dataDir data directory for storing contacts indexer state.
- * @param singleThreadedExecutor an {@link ExecutorService} with at most one thread to ensure
- * the thread safety of this class.
+ * @param context Context object passed from
+ * {@link ContactsIndexerManagerService}
+ * @param dataDir data directory for storing contacts indexer state.
+ * @param contactsIndexerConfig configuration for the Contacts Indexer.
+ * @param singleThreadedExecutor an {@link ExecutorService} with at most one thread to ensure
+ * the thread safety of this class.
*/
private ContactsIndexerUserInstance(@NonNull Context context, @NonNull File dataDir,
@NonNull AppSearchHelper appSearchHelper,
+ @NonNull ContactsIndexerConfig contactsIndexerConfig,
@NonNull ExecutorService singleThreadedExecutor) {
mContext = Objects.requireNonNull(context);
mDataDir = Objects.requireNonNull(dataDir);
+ mContactsIndexerConfig = Objects.requireNonNull(contactsIndexerConfig);
mSettings = new ContactsIndexerSettings(mDataDir);
mAppSearchHelper = Objects.requireNonNull(appSearchHelper);
mSingleThreadedExecutor = Objects.requireNonNull(singleThreadedExecutor);
@@ -172,7 +179,7 @@
// TODO(b/222126568): refactor doDeltaUpdateAsync() to return a future value of
// ContactsUpdateStats so that it can be checked and logged here, instead of the
// placeholder exceptionally() block that only logs to the console.
- doDeltaUpdateAsync(ContactsIndexerConfig.getContactsInstantIndexingLimit(),
+ doDeltaUpdateAsync(mContactsIndexerConfig.getContactsFirstRunIndexingLimit(),
new ContactsUpdateStats()).exceptionally(t -> {
Log.d(TAG, "Failed to bootstrap Person corpus with CP2 contacts", t);
return null;
@@ -181,7 +188,8 @@
// If a configurable amount of time has passed since the last full sync, schedule a job
// to do a full update. That is, sync all CP2 contacts into AppSearch.
- long fullUpdateIntervalMillis = ContactsIndexerConfig.getContactsFullUpdateIntervalMillis();
+ long fullUpdateIntervalMillis =
+ mContactsIndexerConfig.getContactsFullUpdateIntervalMillis();
long lastFullUpdateTimestampMillis = mSettings.getLastFullUpdateTimestampMillis();
if (lastFullUpdateTimestampMillis + fullUpdateIntervalMillis
<= System.currentTimeMillis()) {
@@ -216,7 +224,7 @@
// TODO(b/203605504): reconsider whether the most recent
// updated and deleted timestamps are useful.
ContactsProviderUtil.getUpdatedContactIds(mContext, /*sinceFilter=*/ 0,
- ContactsIndexerConfig.getContactsFullUpdateLimit(), cp2ContactIds,
+ mContactsIndexerConfig.getContactsFullUpdateLimit(), cp2ContactIds,
updateStats);
return mAppSearchHelper.getAllContactIdsAsync()
.thenCompose(appsearchContactIds -> {
@@ -288,7 +296,7 @@
// TODO(b/222126568): refactor doDeltaUpdateAsync() to return a future value of
// ContactsUpdateStats so that it can be checked and logged here, instead of the
// placeholder exceptionally() block that only logs to the console.
- doDeltaUpdateAsync(ContactsIndexerConfig.getContactsDeltaUpdateLimit(),
+ doDeltaUpdateAsync(mContactsIndexerConfig.getContactsDeltaUpdateLimit(),
updateStats).exceptionally(t -> {
Log.d(TAG, "Failed to index CP2 change", t);
return null;
diff --git a/service/java/com/android/server/appsearch/contactsindexer/ContactsProviderUtil.java b/service/java/com/android/server/appsearch/contactsindexer/ContactsProviderUtil.java
index ff32bf1..c9886f7 100644
--- a/service/java/com/android/server/appsearch/contactsindexer/ContactsProviderUtil.java
+++ b/service/java/com/android/server/appsearch/contactsindexer/ContactsProviderUtil.java
@@ -40,6 +40,8 @@
public final class ContactsProviderUtil {
private static final String TAG = "ContactsProviderHelper";
+ public static final int UPDATE_LIMIT_NONE = -1;
+
// static final string for querying CP2
private static final String UPDATE_SINCE = Contacts.CONTACT_LAST_UPDATED_TIMESTAMP + ">?";
private static final String UPDATE_ORDER_BY = Contacts.CONTACT_LAST_UPDATED_TIMESTAMP + " DESC";
diff --git a/service/java/com/android/server/appsearch/contactsindexer/FrameworkContactsIndexerConfig.java b/service/java/com/android/server/appsearch/contactsindexer/FrameworkContactsIndexerConfig.java
new file mode 100644
index 0000000..007be78
--- /dev/null
+++ b/service/java/com/android/server/appsearch/contactsindexer/FrameworkContactsIndexerConfig.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2022 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.contactsindexer;
+
+import android.provider.DeviceConfig;
+
+/**
+ * Implementation of {@link ContactsIndexerConfig} using {@link DeviceConfig}.
+ *
+ * <p>It contains all the keys for flags related to Contacts Indexer.
+ *
+ * <p>This class is thread-safe.
+ *
+ * @hide
+ */
+public class FrameworkContactsIndexerConfig implements ContactsIndexerConfig {
+ static final String KEY_CONTACTS_INDEXER_ENABLED = "contacts_indexer_enabled";
+ static final String KEY_CONTACTS_INSTANT_INDEXING_LIMIT = "contacts_instant_indexing_limit";
+ static final String KEY_CONTACTS_FULL_UPDATE_INTERVAL_MILLIS =
+ "contacts_full_update_interval_millis";
+ static final String KEY_CONTACTS_FULL_UPDATE_LIMIT = "contacts_indexer_full_update_limit";
+ static final String KEY_CONTACTS_DELTA_UPDATE_LIMIT = "contacts_indexer_delta_update_limit";
+
+ @Override
+ public boolean isContactsIndexerEnabled() {
+ return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_APPSEARCH,
+ KEY_CONTACTS_INDEXER_ENABLED,
+ DEFAULT_CONTACTS_INDEXER_ENABLED);
+ }
+
+ @Override
+ public int getContactsFirstRunIndexingLimit() {
+ return DeviceConfig.getInt(DeviceConfig.NAMESPACE_APPSEARCH,
+ KEY_CONTACTS_INSTANT_INDEXING_LIMIT, DEFAULT_CONTACTS_FIRST_RUN_INDEXING_LIMIT);
+ }
+
+ @Override
+ public long getContactsFullUpdateIntervalMillis() {
+ return DeviceConfig.getLong(DeviceConfig.NAMESPACE_APPSEARCH,
+ KEY_CONTACTS_FULL_UPDATE_INTERVAL_MILLIS,
+ DEFAULT_CONTACTS_FULL_UPDATE_INTERVAL_MILLIS);
+ }
+
+ @Override
+ public int getContactsFullUpdateLimit() {
+ return DeviceConfig.getInt(DeviceConfig.NAMESPACE_APPSEARCH,
+ KEY_CONTACTS_FULL_UPDATE_LIMIT,
+ DEFAULT_CONTACTS_FULL_UPDATE_INDEXING_LIMIT);
+ }
+
+ @Override
+ public int getContactsDeltaUpdateLimit() {
+ // TODO(b/227419499) Based on the metrics, we can tweak this number. Right now it is same
+ // as the instant indexing limit, which is 1,000. From our stats in GMSCore, 95th
+ // percentile for number of contacts on the device is around 2000 contacts.
+ return DeviceConfig.getInt(DeviceConfig.NAMESPACE_APPSEARCH,
+ KEY_CONTACTS_DELTA_UPDATE_LIMIT,
+ DEFAULT_CONTACTS_DELTA_UPDATE_INDEXING_LIMIT);
+ }
+}
diff --git a/testing/contactsindexertests/Android.bp b/testing/contactsindexertests/Android.bp
index 551c061..6464f40 100644
--- a/testing/contactsindexertests/Android.bp
+++ b/testing/contactsindexertests/Android.bp
@@ -34,14 +34,9 @@
"android.test.mock",
"android.test.base",
],
- // TODO(b/203690505): Move to general-tests when tests no longer need
- // READ_DEVICE_CONFIG permission.
test_suites: [
- "device-tests",
+ "general-tests",
"mts-appsearch",
],
compile_multilib: "both",
- // TODO(b/203690505): Remove the platform certificate when tests no longer
- // need READ_DEVICE_CONFIG permission.
- certificate: "platform",
}
diff --git a/testing/contactsindexertests/AndroidManifest.xml b/testing/contactsindexertests/AndroidManifest.xml
index dfb52ea..3f6bcfb 100644
--- a/testing/contactsindexertests/AndroidManifest.xml
+++ b/testing/contactsindexertests/AndroidManifest.xml
@@ -18,9 +18,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.appsearch.contactsindexertests" >
<uses-sdk android:minSdkVersion="33" android:targetSdkVersion="33" />
- <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
- <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
<application android:label="ContactsIndexerTests"
android:debuggable="true">
diff --git a/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsIndexerImplTest.java b/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsIndexerImplTest.java
index 64dad40..42b9505 100644
--- a/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsIndexerImplTest.java
+++ b/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsIndexerImplTest.java
@@ -97,7 +97,7 @@
List<String> unWantedContactIds = new ArrayList<>();
lastUpdatedTimestamp = ContactsProviderUtil.getUpdatedContactIds(mContext,
- lastUpdatedTimestamp, ContactsIndexerConfig.UPDATE_LIMIT_NONE,
+ lastUpdatedTimestamp, ContactsProviderUtil.UPDATE_LIMIT_NONE,
wantedContactIds, /*stats=*/ null);
lastDeletedTimestamp = ContactsProviderUtil.getDeletedContactIds(mContext,
lastDeletedTimestamp, unWantedContactIds, /*stats=*/ null);
diff --git a/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsIndexerManagerServiceTest.java b/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsIndexerManagerServiceTest.java
index c09a5c7..b52c769 100644
--- a/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsIndexerManagerServiceTest.java
+++ b/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsIndexerManagerServiceTest.java
@@ -41,6 +41,8 @@
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.Manifest.permission.READ_DEVICE_CONFIG;
import com.android.compatibility.common.util.SystemUtil;
import com.android.server.SystemService;
@@ -93,7 +95,11 @@
return getMockContentResolver();
}
};
- mContactsIndexerManagerService = new ContactsIndexerManagerService(mContext);
+ // INTERACT_ACROSS_USERS_FULL: needed when we do registerReceiverForAllUsers for getting
+ // package change notifications.
+ mUiAutomation.adoptShellPermissionIdentity(INTERACT_ACROSS_USERS_FULL);
+ mContactsIndexerManagerService = new ContactsIndexerManagerService(mContext,
+ new TestContactsIndexerConfig());
mContactsIndexerManagerService.onStart();
UserInfo userInfo = new UserInfo(userHandle.getIdentifier(), /*name=*/ "default",
/*flags=*/ 0);
@@ -108,6 +114,7 @@
new AppSearchManager.SearchContext.Builder(AppSearchHelper.DATABASE_NAME).build(),
mSingleThreadedExecutor).get();
db.setSchemaAsync(new SetSchemaRequest.Builder().setForceOverride(true).build()).get();
+ mUiAutomation.dropShellPermissionIdentity();
super.tearDown();
}
diff --git a/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsIndexerUserInstanceTest.java b/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsIndexerUserInstanceTest.java
index a8139b1..fef2f42 100644
--- a/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsIndexerUserInstanceTest.java
+++ b/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsIndexerUserInstanceTest.java
@@ -16,6 +16,7 @@
package com.android.server.appsearch.contactsindexer;
+import static android.Manifest.permission.READ_DEVICE_CONFIG;
import static android.Manifest.permission.WRITE_DEVICE_CONFIG;
import static com.google.common.truth.Truth.assertThat;
@@ -49,6 +50,7 @@
import android.provider.DeviceConfig;
import android.test.ProviderTestCase2;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -81,7 +83,6 @@
// stick to ProviderTestCase2 for now.
@RunWith(AndroidJUnit4.class)
public class ContactsIndexerUserInstanceTest extends ProviderTestCase2<FakeContactsProvider> {
-
@Rule
public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
@@ -92,6 +93,7 @@
private SearchSpec mSpecForQueryAllContacts;
private ContactsIndexerUserInstance mInstance;
private ContactsUpdateStats mUpdateStats;
+ private ContactsIndexerConfig mConfigForTest = new TestContactsIndexerConfig();
public ContactsIndexerUserInstanceTest() {
super(FakeContactsProvider.class, FakeContactsProvider.AUTHORITY);
@@ -115,7 +117,7 @@
.build();
mInstance = ContactsIndexerUserInstance.createInstance(mContext, mContactsDir,
- mSingleThreadedExecutor);
+ mConfigForTest, mSingleThreadedExecutor);
mUpdateStats = new ContactsUpdateStats();
}
@@ -138,7 +140,7 @@
File dataDir = new File(mTemporaryFolder.newFolder(), "contacts");
boolean isDataDirectoryCreatedSynchronously = mSingleThreadedExecutor.submit(() -> {
ContactsIndexerUserInstance unused =
- ContactsIndexerUserInstance.createInstance(mContext, dataDir,
+ ContactsIndexerUserInstance.createInstance(mContext, dataDir, mConfigForTest,
mSingleThreadedExecutor);
// Data directory shouldn't have been created synchronously in createInstance()
return dataDir.exists();
@@ -153,13 +155,15 @@
public void testStart_initialRun_schedulesFullUpdateJob() throws Exception {
JobScheduler mockJobScheduler = mock(JobScheduler.class);
mContextWrapper.setJobScheduler(mockJobScheduler);
- ContactsIndexerUserInstance instance = ContactsIndexerUserInstance.createInstance(mContext,
- mContactsDir, mSingleThreadedExecutor);
+ ContactsIndexerUserInstance instance = ContactsIndexerUserInstance.createInstance(
+ mContext,
+ mContactsDir, mConfigForTest, mSingleThreadedExecutor);
instance.startAsync();
// Wait for all async tasks to complete
- mSingleThreadedExecutor.submit(() -> {}).get();
+ mSingleThreadedExecutor.submit(() -> {
+ }).get();
verify(mockJobScheduler).schedule(any());
}
@@ -172,15 +176,16 @@
JobScheduler mockJobScheduler = mock(JobScheduler.class);
mContextWrapper.setJobScheduler(mockJobScheduler);
- ContactsIndexerUserInstance instance = ContactsIndexerUserInstance.createInstance(mContext,
- mContactsDir, mSingleThreadedExecutor);
+ ContactsIndexerUserInstance instance = ContactsIndexerUserInstance.createInstance(
+ mContext, mContactsDir, mConfigForTest, mSingleThreadedExecutor);
instance.startAsync();
// Wait for all async tasks to complete
- mSingleThreadedExecutor.submit(() -> {}).get();
+ mSingleThreadedExecutor.submit(() -> {
+ }).get();
- verifyZeroInteractions(mockJobScheduler);
+ verifyZeroInteractions(mockJobScheduler);
}
@Test
@@ -429,10 +434,11 @@
@Test
public void testDeltaUpdate_outOfSpaceError_fullUpdateScheduled() throws Exception {
UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
- int maxDocumentCountBeforeTest = FrameworkAppSearchConfig.getInstance(
- mSingleThreadedExecutor).getCachedLimitConfigMaxDocumentCount();
+ int maxDocumentCountBeforeTest = -1;
try {
- uiAutomation.adoptShellPermissionIdentity(WRITE_DEVICE_CONFIG);
+ uiAutomation.adoptShellPermissionIdentity(READ_DEVICE_CONFIG, WRITE_DEVICE_CONFIG);
+ maxDocumentCountBeforeTest = FrameworkAppSearchConfig.getInstance(
+ mSingleThreadedExecutor).getCachedLimitConfigMaxDocumentCount();
int totalContactCount = 250;
int maxDocumentCount = 100;
// Override the configs in AppSearch. This is hard to be mocked since we are not testing
@@ -478,7 +484,7 @@
}
executeAndWaitForCompletion(
- mInstance.doDeltaUpdateAsync(ContactsIndexerConfig.UPDATE_LIMIT_NONE,
+ mInstance.doDeltaUpdateAsync(ContactsProviderUtil.UPDATE_LIMIT_NONE,
mUpdateStats),
mSingleThreadedExecutor);
latch.await(30L, TimeUnit.SECONDS);
@@ -490,9 +496,11 @@
settingsBundle.getLong(ContactsIndexerSettings.LAST_DELTA_UPDATE_TIMESTAMP_KEY))
.isAtLeast(timeBeforeDeltaChangeNotification);
} finally {
- DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
- FrameworkAppSearchConfig.KEY_LIMIT_CONFIG_MAX_DOCUMENT_COUNT,
- String.valueOf(maxDocumentCountBeforeTest), false);
+ if (maxDocumentCountBeforeTest > 0) {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ FrameworkAppSearchConfig.KEY_LIMIT_CONFIG_MAX_DOCUMENT_COUNT,
+ String.valueOf(maxDocumentCountBeforeTest), false);
+ }
uiAutomation.dropShellPermissionIdentity();
}
}
diff --git a/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsProviderUtilTest.java b/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsProviderUtilTest.java
index 93b1c07..5c25b1b 100644
--- a/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsProviderUtilTest.java
+++ b/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/ContactsProviderUtilTest.java
@@ -68,7 +68,7 @@
List<String> ids = new ArrayList<>();
long lastUpdatedTime = ContactsProviderUtil.getUpdatedContactIds(mContext,
- /*sinceFilter=*/ 0, ContactsIndexerConfig.UPDATE_LIMIT_NONE, ids, /*stats=*/ null);
+ /*sinceFilter=*/ 0, ContactsProviderUtil.UPDATE_LIMIT_NONE, ids, /*stats=*/ null);
assertThat(lastUpdatedTime).isEqualTo(
getProvider().getMostRecentContactUpdateTimestampMillis());
@@ -86,7 +86,7 @@
List<String> ids = new ArrayList<>();
long lastUpdatedTime = ContactsProviderUtil.getUpdatedContactIds(mContext,
/*sinceFilter=*/ getProvider().getMostRecentContactUpdateTimestampMillis(),
- ContactsIndexerConfig.UPDATE_LIMIT_NONE, ids, /*stats=*/ null);
+ ContactsProviderUtil.UPDATE_LIMIT_NONE, ids, /*stats=*/ null);
assertThat(lastUpdatedTime).isEqualTo(
getProvider().getMostRecentContactUpdateTimestampMillis());
@@ -108,7 +108,7 @@
List<String> ids = new ArrayList<>();
long lastUpdatedTime = ContactsProviderUtil.getUpdatedContactIds(mContext,
- /*sinceFilter=*/ firstUpdateTimestamp, ContactsIndexerConfig.UPDATE_LIMIT_NONE,
+ /*sinceFilter=*/ firstUpdateTimestamp, ContactsProviderUtil.UPDATE_LIMIT_NONE,
ids, /*stats=*/ null);
assertThat(lastUpdatedTime).isEqualTo(
diff --git a/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/PersonBuilderHelperTest.java b/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/PersonBuilderHelperTest.java
index e004175..b52aacf 100644
--- a/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/PersonBuilderHelperTest.java
+++ b/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/PersonBuilderHelperTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package contactsindexertests.src.com.android.server.appsearch.contactsindexer;
+package com.android.server.appsearch.contactsindexer;
import android.net.Uri;
diff --git a/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/TestContactsIndexerConfig.java b/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/TestContactsIndexerConfig.java
new file mode 100644
index 0000000..7aa31cb
--- /dev/null
+++ b/testing/contactsindexertests/src/com/android/server/appsearch/contactsindexer/TestContactsIndexerConfig.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 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.contactsindexer;
+
+/**
+ * Contacts Indexer configuration for testing.
+ *
+ * <p>It simply returns default values.
+ */
+public class TestContactsIndexerConfig implements ContactsIndexerConfig {
+ @Override
+ public boolean isContactsIndexerEnabled() {
+ return DEFAULT_CONTACTS_INDEXER_ENABLED;
+ }
+
+ @Override
+ public int getContactsFirstRunIndexingLimit() {
+ return DEFAULT_CONTACTS_FIRST_RUN_INDEXING_LIMIT;
+ }
+
+ @Override
+ public long getContactsFullUpdateIntervalMillis() {
+ return DEFAULT_CONTACTS_FULL_UPDATE_INTERVAL_MILLIS;
+ }
+
+ @Override
+ public int getContactsFullUpdateLimit() {
+ return DEFAULT_CONTACTS_FULL_UPDATE_INDEXING_LIMIT;
+ }
+
+ @Override
+ public int getContactsDeltaUpdateLimit() {
+ return DEFAULT_CONTACTS_DELTA_UPDATE_INDEXING_LIMIT;
+ }
+}
diff --git a/testing/mockingservicestests/src/com/android/server/appsearch/ContactsIndexer/FrameworkContactsIndexerConfigTest.java b/testing/mockingservicestests/src/com/android/server/appsearch/ContactsIndexer/FrameworkContactsIndexerConfigTest.java
new file mode 100644
index 0000000..a767510
--- /dev/null
+++ b/testing/mockingservicestests/src/com/android/server/appsearch/ContactsIndexer/FrameworkContactsIndexerConfigTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 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.contactsindexer;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.provider.DeviceConfig;
+
+import com.android.modules.utils.testing.TestableDeviceConfig;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+public class FrameworkContactsIndexerConfigTest {
+ @Rule
+ public final TestableDeviceConfig.TestableDeviceConfigRule
+ mDeviceConfigRule = new TestableDeviceConfig.TestableDeviceConfigRule();
+
+ @Test
+ public void testDefaultValues() {
+ ContactsIndexerConfig contactsIndexerConfig = new FrameworkContactsIndexerConfig();
+
+ assertThat(contactsIndexerConfig.isContactsIndexerEnabled()).isTrue();
+ assertThat(contactsIndexerConfig.getContactsFirstRunIndexingLimit()).isEqualTo(
+ ContactsIndexerConfig.DEFAULT_CONTACTS_FIRST_RUN_INDEXING_LIMIT);
+ assertThat(contactsIndexerConfig.getContactsFullUpdateIntervalMillis()).isEqualTo(
+ ContactsIndexerConfig.DEFAULT_CONTACTS_FULL_UPDATE_INTERVAL_MILLIS);
+ assertThat(contactsIndexerConfig.getContactsFullUpdateLimit()).isEqualTo(
+ ContactsIndexerConfig.DEFAULT_CONTACTS_FULL_UPDATE_INDEXING_LIMIT);
+ assertThat(contactsIndexerConfig.getContactsDeltaUpdateLimit()).isEqualTo(
+ ContactsIndexerConfig.DEFAULT_CONTACTS_DELTA_UPDATE_INDEXING_LIMIT);
+ }
+
+ @Test
+ public void testCustomizedValues() {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ FrameworkContactsIndexerConfig.KEY_CONTACTS_INDEXER_ENABLED,
+ Boolean.toString(false),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ FrameworkContactsIndexerConfig.KEY_CONTACTS_INSTANT_INDEXING_LIMIT,
+ Integer.toString(
+ ContactsIndexerConfig.DEFAULT_CONTACTS_FIRST_RUN_INDEXING_LIMIT + 1),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ FrameworkContactsIndexerConfig.KEY_CONTACTS_FULL_UPDATE_INTERVAL_MILLIS,
+ Long.toString(
+ ContactsIndexerConfig.DEFAULT_CONTACTS_FULL_UPDATE_INTERVAL_MILLIS + 1),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ FrameworkContactsIndexerConfig.KEY_CONTACTS_FULL_UPDATE_LIMIT,
+ Long.toString(
+ ContactsIndexerConfig.DEFAULT_CONTACTS_FULL_UPDATE_INDEXING_LIMIT + 1),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ FrameworkContactsIndexerConfig.KEY_CONTACTS_DELTA_UPDATE_LIMIT,
+ Long.toString(
+ ContactsIndexerConfig.DEFAULT_CONTACTS_DELTA_UPDATE_INDEXING_LIMIT + 1),
+ false);
+
+ ContactsIndexerConfig contactsIndexerConfig = new FrameworkContactsIndexerConfig();
+
+ assertThat(contactsIndexerConfig.isContactsIndexerEnabled()).isFalse();
+ assertThat(contactsIndexerConfig.getContactsFirstRunIndexingLimit()).isEqualTo(
+ ContactsIndexerConfig.DEFAULT_CONTACTS_FIRST_RUN_INDEXING_LIMIT + 1);
+ assertThat(contactsIndexerConfig.getContactsFullUpdateIntervalMillis()).isEqualTo(
+ ContactsIndexerConfig.DEFAULT_CONTACTS_FULL_UPDATE_INTERVAL_MILLIS + 1);
+ assertThat(contactsIndexerConfig.getContactsFullUpdateLimit()).isEqualTo(
+ ContactsIndexerConfig.DEFAULT_CONTACTS_FULL_UPDATE_INDEXING_LIMIT + 1);
+ assertThat(contactsIndexerConfig.getContactsDeltaUpdateLimit()).isEqualTo(
+ ContactsIndexerConfig.DEFAULT_CONTACTS_DELTA_UPDATE_INDEXING_LIMIT + 1);
+ }
+}