Merge "Update VisibilityStore to handle role-based system visibility." into sc-dev
diff --git a/service/java/com/android/server/appsearch/AppSearchConfig.java b/service/java/com/android/server/appsearch/AppSearchConfig.java
new file mode 100644
index 0000000..6e81afc
--- /dev/null
+++ b/service/java/com/android/server/appsearch/AppSearchConfig.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 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;
+
+import android.annotation.NonNull;
+import android.os.Bundle;
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfig.OnPropertiesChangedListener;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+/**
+ * It contains all the keys for the flags, as well as caches some of latest flag values from
+ * DeviceConfig.
+ *
+ * <p>Though the latest flag values can always be retrieved by calling {@code
+ * DeviceConfig.getProperty}, we want to cache some of those values. For example, the sampling
+ * intervals for logging, they are needed for each api call and it would be a little expensive to
+ * call
+ * {@code DeviceConfig.getProperty} every time.
+ *
+ * <p>Listener is registered to DeviceConfig keep the cached value up to date.
+ *
+ * <p>This class is thread-safe.
+ *
+ * @hide
+ */
+public final class AppSearchConfig implements AutoCloseable {
+ /**
+ * It would be used as default min time interval between samples in millis if there is no value
+ * set for {@link AppSearchConfig#KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS} in DeviceConfig.
+ */
+ @VisibleForTesting
+ static final long DEFAULT_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS = 50;
+
+ /**
+ * It would be used as default sampling interval if there is no value
+ * set for {@link AppSearchConfig#KEY_SAMPLING_INTERVAL_DEFAULT} in DeviceConfig.
+ */
+ @VisibleForTesting
+ static final int DEFAULT_SAMPLING_INTERVAL = 10;
+
+ /*
+ * Keys for ALL the flags stored in DeviceConfig.
+ */
+ public static final String KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS =
+ "min_time_interval_between_samples_millis";
+ public static final String KEY_SAMPLING_INTERVAL_DEFAULT = "sampling_interval_default";
+ public static final String KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS =
+ "sampling_interval_for_batch_call_stats";
+ public static final String KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS =
+ "sampling_interval_for_put_document_stats";
+
+ // Array contains all the corresponding keys for the cached values.
+ private static final String[] KEYS_TO_ALL_CACHED_VALUES = {
+ KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
+ KEY_SAMPLING_INTERVAL_DEFAULT,
+ KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
+ KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS
+ };
+
+ // Lock needed for all the operations in this class.
+ private final Object mLock = new Object();
+
+ /**
+ * Bundle to hold all the cached flag values corresponding to
+ * {@link AppSearchConfig#KEYS_TO_ALL_CACHED_VALUES}.
+ */
+ @GuardedBy("mLock")
+ private final Bundle mBundleLocked = new Bundle();
+
+
+ @GuardedBy("mLock")
+ private boolean mIsClosedLocked = false;
+
+ /** Listener to update cached flag values from DeviceConfig. */
+ private final OnPropertiesChangedListener mOnDeviceConfigChangedListener =
+ properties -> {
+ if (!properties.getNamespace().equals(DeviceConfig.NAMESPACE_APPSEARCH)) {
+ return;
+ }
+
+ updateCachedValues(properties);
+ };
+
+ /**
+ * Creates an instance of {@link AppSearchConfig}.
+ *
+ * @param executor used to fetch and cache the flag values from DeviceConfig during creation or
+ * config change.
+ */
+ @NonNull
+ public static AppSearchConfig create(@NonNull Executor executor) {
+ Objects.requireNonNull(executor);
+ AppSearchConfig configManager = new AppSearchConfig();
+ configManager.initialize(executor);
+ return configManager;
+ }
+
+ private AppSearchConfig() {
+ }
+
+ /**
+ * Initializes the {@link AppSearchConfig}
+ *
+ * <p>It fetches the custom properties from DeviceConfig if available.
+ *
+ * @param executor listener would be run on to handle P/H flag change.
+ */
+ private void initialize(@NonNull Executor executor) {
+ executor.execute(() -> {
+ // Attach the callback to get updates on those properties.
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_APPSEARCH,
+ executor,
+ mOnDeviceConfigChangedListener);
+
+ DeviceConfig.Properties properties = DeviceConfig.getProperties(
+ DeviceConfig.NAMESPACE_APPSEARCH, KEYS_TO_ALL_CACHED_VALUES);
+ updateCachedValues(properties);
+ });
+ }
+
+ // TODO(b/173532925) check this will be called. If we have a singleton instance for this
+ // class, probably we don't need it.
+ @Override
+ public void close() {
+ synchronized (mLock) {
+ if (mIsClosedLocked) {
+ return;
+ }
+
+ DeviceConfig.removeOnPropertiesChangedListener(mOnDeviceConfigChangedListener);
+ mIsClosedLocked = true;
+ }
+ }
+
+ /** Returns cached value for minTimeIntervalBetweenSamplesMillis. */
+ public long getCachedMinTimeIntervalBetweenSamplesMillis() {
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ return mBundleLocked.getLong(KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
+ DEFAULT_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS);
+ }
+ }
+
+ /**
+ * Returns cached value for default sampling interval for all the stats NOT listed in
+ * the configuration.
+ *
+ * <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
+ */
+ public int getCachedSamplingIntervalDefault() {
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_DEFAULT, DEFAULT_SAMPLING_INTERVAL);
+ }
+ }
+
+ /**
+ * Returns cached value for sampling interval for batch calls.
+ *
+ * <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
+ */
+ public int getCachedSamplingIntervalForBatchCallStats() {
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
+ getCachedSamplingIntervalDefault());
+ }
+ }
+
+ /**
+ * Returns cached value for sampling interval for putDocument.
+ *
+ * <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
+ */
+ public int getCachedSamplingIntervalForPutDocumentStats() {
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ getCachedSamplingIntervalDefault());
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void throwIfClosedLocked() {
+ if (mIsClosedLocked) {
+ throw new IllegalStateException("Trying to use a closed AppSearchConfig instance.");
+ }
+ }
+
+ private void updateCachedValues(@NonNull DeviceConfig.Properties properties) {
+ for (String key : properties.getKeyset()) {
+ updateCachedValue(key, properties);
+ }
+ }
+
+ private void updateCachedValue(@NonNull String key,
+ @NonNull DeviceConfig.Properties properties) {
+ if (properties.getString(key, /*defaultValue=*/ null) == null) {
+ // Key is missing or value is just null. That is not expected if the key is
+ // defined in the configuration.
+ //
+ // We choose NOT to put the default value in the bundle.
+ // Instead, we let the getters handle what default value should be returned.
+ //
+ // Also we keep the old value in the bundle. So getters can still
+ // return last valid value.
+ return;
+ }
+
+ switch (key) {
+ case KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS:
+ synchronized (mLock) {
+ mBundleLocked.putLong(key,
+ properties.getLong(key,
+ DEFAULT_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS));
+ }
+ break;
+ case KEY_SAMPLING_INTERVAL_DEFAULT:
+ case KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS:
+ case KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS:
+ synchronized (mLock) {
+ mBundleLocked.putInt(key, properties.getInt(key, DEFAULT_SAMPLING_INTERVAL));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/service/java/com/android/server/appsearch/stats/PlatformLogger.java b/service/java/com/android/server/appsearch/stats/PlatformLogger.java
index abcf161..7d0ce41 100644
--- a/service/java/com/android/server/appsearch/stats/PlatformLogger.java
+++ b/service/java/com/android/server/appsearch/stats/PlatformLogger.java
@@ -72,7 +72,7 @@
*
* <p> We can have correct extrapolated number by adding those counts back when we log
* the same type of stats next time. E.g. the true count of an event could be estimated as:
- * SUM(sampling_ratio * (num_skipped_sample + 1)) as est_count
+ * SUM(sampling_interval * (num_skipped_sample + 1)) as est_count
*
* <p>The key to the SparseArray is {@link CallStats.CallType}
*/
@@ -105,42 +105,42 @@
// logging again.
private final long mMinTimeIntervalBetweenSamplesMillis;
- // Default sampling ratio for all types of stats
- private final int mDefaultSamplingRatio;
+ // Default sampling interval for all types of stats
+ private final int mDefaultSamplingInterval;
/**
- * Sampling ratios for different types of stats
+ * Sampling intervals for different types of stats
*
* <p>This SparseArray is passed by client and is READ-ONLY. The key to that SparseArray is
* {@link CallStats.CallType}
*
- * <p>If sampling ratio is missing for certain stats type,
- * {@link Config#mDefaultSamplingRatio} will be used.
+ * <p>If sampling interval is missing for certain stats type,
+ * {@link Config#mDefaultSamplingInterval} will be used.
*
- * <p>E.g. sampling ratio=10 means that one out of every 10 stats was logged. If sampling
- * ratio is 1, we will log each sample and it acts as if the sampling is disabled.
+ * <p>E.g. sampling interval=10 means that one out of every 10 stats was logged. If sampling
+ * interval is 1, we will log each sample and it acts as if the sampling is disabled.
*/
@NonNull
- private final SparseIntArray mSamplingRatios;
+ private final SparseIntArray mSamplingIntervals;
/**
* Configuration for {@link PlatformLogger}
*
* @param minTimeIntervalBetweenSamplesMillis minimum time interval apart in Milliseconds
* required for two consecutive stats logged
- * @param defaultSamplingRatio default sampling ratio
- * @param samplingRatios SparseArray to customize sampling ratio for
+ * @param defaultSamplingInterval default sampling interval
+ * @param samplingIntervals SparseArray to customize sampling interval for
* different stat types
*/
public Config(long minTimeIntervalBetweenSamplesMillis,
- int defaultSamplingRatio,
- @NonNull SparseIntArray samplingRatios) {
+ int defaultSamplingInterval,
+ @NonNull SparseIntArray samplingIntervals) {
// TODO(b/173532925) Probably we can get rid of those three after we have p/h flags
// for them.
- // e.g. we can just call DeviceConfig.get(SAMPLING_RATIO_FOR_PUT_DOCUMENTS).
+ // e.g. we can just call DeviceConfig.get(SAMPLING_INTERVAL_FOR_PUT_DOCUMENTS).
mMinTimeIntervalBetweenSamplesMillis = minTimeIntervalBetweenSamplesMillis;
- mDefaultSamplingRatio = defaultSamplingRatio;
- mSamplingRatios = samplingRatios;
+ mDefaultSamplingInterval = defaultSamplingInterval;
+ mSamplingIntervals = samplingIntervals;
}
}
@@ -150,14 +150,14 @@
static final class ExtraStats {
// UID for the calling package of the stats.
final int mPackageUid;
- // sampling ratio for the call type of the stats.
- final int mSamplingRatio;
+ // sampling interval for the call type of the stats.
+ final int mSamplingInterval;
// number of samplings skipped before the current one for the same call type.
final int mSkippedSampleCount;
- ExtraStats(int packageUid, int samplingRatio, int skippedSampleCount) {
+ ExtraStats(int packageUid, int samplingInterval, int skippedSampleCount) {
mPackageUid = packageUid;
- mSamplingRatio = samplingRatio;
+ mSamplingInterval = samplingInterval;
mSkippedSampleCount = skippedSampleCount;
}
}
@@ -224,7 +224,7 @@
*
* @return removed UID for the package, or {@code INVALID_UID} if package was not previously
* cached.
- */
+ */
public int removeCachedUidForPackage(@NonNull String packageName) {
// TODO(b/173532925) This needs to be called when we get PACKAGE_REMOVED intent
Objects.requireNonNull(packageName);
@@ -243,7 +243,7 @@
try {
int hashCodeForDatabase = calculateHashCodeMd5(database);
AppSearchStatsLog.write(AppSearchStatsLog.APP_SEARCH_CALL_STATS_REPORTED,
- extraStats.mSamplingRatio,
+ extraStats.mSamplingInterval,
extraStats.mSkippedSampleCount,
extraStats.mPackageUid,
hashCodeForDatabase,
@@ -275,7 +275,7 @@
try {
int hashCodeForDatabase = calculateHashCodeMd5(database);
AppSearchStatsLog.write(AppSearchStatsLog.APP_SEARCH_PUT_DOCUMENT_STATS_REPORTED,
- extraStats.mSamplingRatio,
+ extraStats.mSamplingInterval,
extraStats.mSkippedSampleCount,
extraStats.mPackageUid,
hashCodeForDatabase,
@@ -312,7 +312,7 @@
try {
int hashCodeForDatabase = calculateHashCodeMd5(database);
AppSearchStatsLog.write(AppSearchStatsLog.APP_SEARCH_QUERY_STATS_REPORTED,
- extraStats.mSamplingRatio,
+ extraStats.mSamplingInterval,
extraStats.mSkippedSampleCount,
extraStats.mPackageUid,
hashCodeForDatabase,
@@ -355,7 +355,7 @@
ExtraStats extraStats = createExtraStatsLocked(/*packageName=*/ null,
CallStats.CALL_TYPE_INITIALIZE);
AppSearchStatsLog.write(AppSearchStatsLog.APP_SEARCH_INITIALIZE_STATS_REPORTED,
- extraStats.mSamplingRatio,
+ extraStats.mSamplingInterval,
extraStats.mSkippedSampleCount,
extraStats.mPackageUid,
stats.getStatusCode(),
@@ -428,14 +428,14 @@
packageUid = getPackageUidAsUserLocked(packageName);
}
- int samplingRatio = mConfig.mSamplingRatios.get(callType,
- mConfig.mDefaultSamplingRatio);
+ int samplingInterval = mConfig.mSamplingIntervals.get(callType,
+ mConfig.mDefaultSamplingInterval);
int skippedSampleCount = mSkippedSampleCountLocked.get(callType,
/*valueOfKeyIfNotFound=*/ 0);
mSkippedSampleCountLocked.put(callType, 0);
- return new ExtraStats(packageUid, samplingRatio, skippedSampleCount);
+ return new ExtraStats(packageUid, samplingInterval, skippedSampleCount);
}
/**
@@ -450,11 +450,11 @@
// rate limiting.
@VisibleForTesting
boolean shouldLogForTypeLocked(@CallStats.CallType int callType) {
- int samplingRatio = mConfig.mSamplingRatios.get(callType,
- mConfig.mDefaultSamplingRatio);
+ int samplingInterval = mConfig.mSamplingIntervals.get(callType,
+ mConfig.mDefaultSamplingInterval);
// Sampling
- if (!shouldSample(samplingRatio)) {
+ if (!shouldSample(samplingInterval)) {
return false;
}
@@ -475,15 +475,15 @@
/**
* Checks if the stats should be "sampled"
*
- * @param samplingRatio sampling ratio
+ * @param samplingInterval sampling interval
* @return if the stats should be sampled
*/
- private boolean shouldSample(int samplingRatio) {
- if (samplingRatio <= 0) {
+ private boolean shouldSample(int samplingInterval) {
+ if (samplingInterval <= 0) {
return false;
}
- return mRng.nextInt((int) samplingRatio) == 0;
+ return mRng.nextInt((int) samplingInterval) == 0;
}
/**
diff --git a/testing/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java b/testing/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java
new file mode 100644
index 0000000..c486028
--- /dev/null
+++ b/testing/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 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;
+
+import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.provider.DeviceConfig;
+
+import com.android.server.testables.TestableDeviceConfig;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+
+/**
+ * Tests for {@link AppSearchConfig}.
+ *
+ * <p>Build/Install/Run: atest FrameworksMockingServicesTests:AppSearchConfigTest
+ */
+public class AppSearchConfigTest {
+ @Rule
+ public final TestableDeviceConfig.TestableDeviceConfigRule
+ mDeviceConfigRule = new TestableDeviceConfig.TestableDeviceConfigRule();
+
+ @Test
+ public void testDefaultValues_allCachedValue() {
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ assertThat(appSearchConfig.getCachedMinTimeIntervalBetweenSamplesMillis()).isEqualTo(
+ AppSearchConfig.DEFAULT_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS);
+ assertThat(appSearchConfig.getCachedSamplingIntervalDefault()).isEqualTo(
+ AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
+ AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
+ AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+ }
+
+ @Test
+ public void testCustomizedValue_minTimeIntervalBetweenSamplesMillis() {
+ final long minTimeIntervalBetweenSamplesMillis = -1;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
+ Long.toString(minTimeIntervalBetweenSamplesMillis),
+ false);
+
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ assertThat(appSearchConfig.getCachedMinTimeIntervalBetweenSamplesMillis()).isEqualTo(
+ minTimeIntervalBetweenSamplesMillis);
+ }
+
+ @Test
+ public void testCustomizedValueOverride_minTimeIntervalBetweenSamplesMillis() {
+ long minTimeIntervalBetweenSamplesMillis = -1;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
+ Long.toString(minTimeIntervalBetweenSamplesMillis),
+ false);
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ minTimeIntervalBetweenSamplesMillis = -2;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
+ Long.toString(minTimeIntervalBetweenSamplesMillis),
+ false);
+
+ assertThat(appSearchConfig.getCachedMinTimeIntervalBetweenSamplesMillis()).isEqualTo(
+ minTimeIntervalBetweenSamplesMillis);
+ }
+
+ @Test
+ public void testCustomizedValue_allSamplingIntervals() {
+ final int samplingIntervalDefault = -1;
+ final int samplingIntervalPutDocumentStats = -2;
+ final int samplingIntervalBatchCallStats = -3;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(samplingIntervalPutDocumentStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
+ Integer.toString(samplingIntervalBatchCallStats),
+ false);
+
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ assertThat(appSearchConfig.getCachedSamplingIntervalDefault()).isEqualTo(
+ samplingIntervalDefault);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
+ samplingIntervalPutDocumentStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
+ samplingIntervalBatchCallStats);
+ }
+
+ @Test
+ public void testCustomizedValueOverride_allSamplingIntervals() {
+ int samplingIntervalDefault = -1;
+ int samplingIntervalPutDocumentStats = -2;
+ int samplingIntervalBatchCallStats = -3;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(samplingIntervalPutDocumentStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
+ Integer.toString(samplingIntervalBatchCallStats),
+ false);
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ // Overrides
+ samplingIntervalDefault = -4;
+ samplingIntervalPutDocumentStats = -5;
+ samplingIntervalBatchCallStats = -6;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(samplingIntervalPutDocumentStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
+ Integer.toString(samplingIntervalBatchCallStats),
+ false);
+
+ assertThat(appSearchConfig.getCachedSamplingIntervalDefault()).isEqualTo(
+ samplingIntervalDefault);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
+ samplingIntervalPutDocumentStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
+ samplingIntervalBatchCallStats);
+ }
+
+ /**
+ * Tests if we fall back to {@link AppSearchConfig#DEFAULT_SAMPLING_INTERVAL} if both default
+ * sampling
+ * interval and custom value are not set in DeviceConfig, and there is some other sampling
+ * interval
+ * set.
+ */
+ @Test
+ public void testFallbackToDefaultSamplingValue_useHardCodedDefault() {
+ final int samplingIntervalPutDocumentStats = -1;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(samplingIntervalPutDocumentStats),
+ false);
+
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
+ samplingIntervalPutDocumentStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
+ AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+ }
+
+ // Tests if we fall back to configured default sampling interval if custom value is not set in
+ // DeviceConfig.
+ @Test
+ public void testFallbackDefaultSamplingValue_useConfiguredDefault() {
+ final int samplingIntervalPutDocumentStats = -1;
+ final int samplingIntervalDefault = -2;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(samplingIntervalPutDocumentStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
+ samplingIntervalPutDocumentStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
+ samplingIntervalDefault);
+ }
+
+ // Tests that cached values should reflect latest values in DeviceConfig.
+ @Test
+ public void testFallbackDefaultSamplingValue_defaultValueChanged() {
+ int samplingIntervalPutDocumentStats = -1;
+ int samplingIntervalDefault = -2;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(samplingIntervalPutDocumentStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ // Sampling values changed.
+ samplingIntervalPutDocumentStats = -3;
+ samplingIntervalDefault = -4;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(samplingIntervalPutDocumentStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+
+ assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
+ samplingIntervalPutDocumentStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
+ samplingIntervalDefault);
+ }
+
+ // Tests default sampling interval won't affect custom sampling intervals if they are set.
+ @Test
+ public void testShouldNotFallBack_ifValueConfigured() {
+ int samplingIntervalDefault = -1;
+ int samplingIntervalBatchCallStats = -2;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
+ Integer.toString(samplingIntervalBatchCallStats),
+ false);
+
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ // Default sampling interval changed.
+ samplingIntervalDefault = -3;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+
+ assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
+ samplingIntervalBatchCallStats);
+ }
+
+ @Test
+ public void testNotUsable_afterClose() {
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ appSearchConfig.close();
+
+ Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+ IllegalStateException.class,
+ () -> appSearchConfig.getCachedMinTimeIntervalBetweenSamplesMillis());
+ Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+ IllegalStateException.class,
+ () -> appSearchConfig.getCachedSamplingIntervalDefault());
+ Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+ IllegalStateException.class,
+ () -> appSearchConfig.getCachedSamplingIntervalForBatchCallStats());
+ Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+ IllegalStateException.class,
+ () -> appSearchConfig.getCachedSamplingIntervalForPutDocumentStats());
+ }
+}
diff --git a/testing/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java b/testing/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
index 747dd1d..734f05a 100644
--- a/testing/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
+++ b/testing/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
@@ -46,7 +46,7 @@
public class PlatformLoggerTest {
private static final int TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS = 100;
- private static final int TEST_DEFAULT_SAMPLING_RATIO = 10;
+ private static final int TEST_DEFAULT_SAMPLING_INTERVAL = 10;
private static final String TEST_PACKAGE_NAME = "packageName";
private MockPackageManager mMockPackageManager = new MockPackageManager();
private Context mContext;
@@ -72,63 +72,63 @@
}
@Test
- public void testCreateExtraStatsLocked_nullSamplingRatioMap_returnsDefaultSamplingRatio() {
+ public void testCreateExtraStatsLocked_nullSamplingIntervalMap_returnsDefault() {
PlatformLogger logger = new PlatformLogger(
ApplicationProvider.getApplicationContext(),
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- TEST_DEFAULT_SAMPLING_RATIO,
- /*samplingRatios=*/ new SparseIntArray()));
+ TEST_DEFAULT_SAMPLING_INTERVAL,
+ /*samplingIntervals=*/ new SparseIntArray()));
- // Make sure default sampling ratio is used if samplingMap is not provided.
+ // Make sure default sampling interval is used if samplingMap is not provided.
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_UNKNOWN).mSamplingRatio).isEqualTo(
- TEST_DEFAULT_SAMPLING_RATIO);
+ CallStats.CALL_TYPE_UNKNOWN).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_INITIALIZE).mSamplingRatio).isEqualTo(
- TEST_DEFAULT_SAMPLING_RATIO);
+ CallStats.CALL_TYPE_INITIALIZE).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_SEARCH).mSamplingRatio).isEqualTo(
- TEST_DEFAULT_SAMPLING_RATIO);
+ CallStats.CALL_TYPE_SEARCH).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_FLUSH).mSamplingRatio).isEqualTo(
- TEST_DEFAULT_SAMPLING_RATIO);
+ CallStats.CALL_TYPE_FLUSH).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
}
@Test
- public void testCreateExtraStatsLocked_with_samplingRatioMap_returnsConfiguredSamplingRatio() {
- int putDocumentSamplingRatio = 1;
- int querySamplingRatio = 2;
- final SparseIntArray samplingRatios = new SparseIntArray();
- samplingRatios.put(CallStats.CALL_TYPE_PUT_DOCUMENT, putDocumentSamplingRatio);
- samplingRatios.put(CallStats.CALL_TYPE_SEARCH, querySamplingRatio);
+ public void testCreateExtraStatsLocked_with_samplingIntervalMap_returnsConfigured() {
+ int putDocumentSamplingInterval = 1;
+ int querySamplingInterval = 2;
+ final SparseIntArray samplingIntervals = new SparseIntArray();
+ samplingIntervals.put(CallStats.CALL_TYPE_PUT_DOCUMENT, putDocumentSamplingInterval);
+ samplingIntervals.put(CallStats.CALL_TYPE_SEARCH, querySamplingInterval);
PlatformLogger logger = new PlatformLogger(
ApplicationProvider.getApplicationContext(),
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- TEST_DEFAULT_SAMPLING_RATIO,
- samplingRatios));
+ TEST_DEFAULT_SAMPLING_INTERVAL,
+ samplingIntervals));
- // The default sampling ratio should be used if no sampling ratio is
+ // The default sampling interval should be used if no sampling interval is
// provided for certain call type.
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_INITIALIZE).mSamplingRatio).isEqualTo(
- TEST_DEFAULT_SAMPLING_RATIO);
+ CallStats.CALL_TYPE_INITIALIZE).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_FLUSH).mSamplingRatio).isEqualTo(
- TEST_DEFAULT_SAMPLING_RATIO);
+ CallStats.CALL_TYPE_FLUSH).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
- // The configured sampling ratio is used if sampling ratio is available
+ // The configured sampling interval is used if sampling interval is available
// for certain call type.
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_PUT_DOCUMENT).mSamplingRatio).isEqualTo(
- putDocumentSamplingRatio);
+ CallStats.CALL_TYPE_PUT_DOCUMENT).mSamplingInterval).isEqualTo(
+ putDocumentSamplingInterval);
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_SEARCH).mSamplingRatio).isEqualTo(
- querySamplingRatio);
+ CallStats.CALL_TYPE_SEARCH).mSamplingInterval).isEqualTo(
+ querySamplingInterval);
}
@Test
@@ -202,16 +202,16 @@
}
@Test
- public void testShouldLogForTypeLocked_trueWhenSampleRatioIsOne() {
- final int samplingRatio = 1;
+ public void testShouldLogForTypeLocked_trueWhenSampleIntervalIsOne() {
+ final int samplingInterval = 1;
final String testPackageName = "packageName";
PlatformLogger logger = new PlatformLogger(
ApplicationProvider.getApplicationContext(),
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- samplingRatio,
- /*samplingRatios=*/ new SparseIntArray()));
+ samplingInterval,
+ /*samplingIntervals=*/ new SparseIntArray()));
// Sample should always be logged for the first time if sampling is disabled(value is one).
assertThat(logger.shouldLogForTypeLocked(CallStats.CALL_TYPE_PUT_DOCUMENT)).isTrue();
@@ -220,18 +220,18 @@
}
@Test
- public void testShouldLogForTypeLocked_falseWhenSampleRatioIsNegative() {
- final int samplingRatio = -1;
+ public void testShouldLogForTypeLocked_falseWhenSampleIntervalIsNegative() {
+ final int samplingInterval = -1;
final String testPackageName = "packageName";
PlatformLogger logger = new PlatformLogger(
ApplicationProvider.getApplicationContext(),
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- samplingRatio,
- /*samplingRatios=*/ new SparseIntArray()));
+ samplingInterval,
+ /*samplingIntervals=*/ new SparseIntArray()));
- // Makes sure sample will be excluded due to sampling if sample ratio is negative.
+ // Makes sure sample will be excluded due to sampling if sample interval is negative.
assertThat(logger.shouldLogForTypeLocked(CallStats.CALL_TYPE_PUT_DOCUMENT)).isFalse();
// Skipped count should be 0 since it doesn't pass the sampling.
assertThat(logger.createExtraStatsLocked(testPackageName,
@@ -241,7 +241,7 @@
@Test
public void testShouldLogForTypeLocked_falseWhenWithinCoolOffInterval() {
// Next sample won't be excluded due to sampling.
- final int samplingRatio = 1;
+ final int samplingInterval = 1;
// Next sample would guaranteed to be too close.
final int minTimeIntervalBetweenSamplesMillis = Integer.MAX_VALUE;
final String testPackageName = "packageName";
@@ -250,8 +250,8 @@
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
minTimeIntervalBetweenSamplesMillis,
- samplingRatio,
- /*samplingRatios=*/ new SparseIntArray()));
+ samplingInterval,
+ /*samplingIntervals=*/ new SparseIntArray()));
logger.setLastPushTimeMillisLocked(SystemClock.elapsedRealtime());
// Makes sure sample will be excluded due to rate limiting if samples are too close.
@@ -263,7 +263,7 @@
@Test
public void testShouldLogForTypeLocked_trueWhenOutsideOfCoolOffInterval() {
// Next sample won't be excluded due to sampling.
- final int samplingRatio = 1;
+ final int samplingInterval = 1;
// Next sample would guaranteed to be included.
final int minTimeIntervalBetweenSamplesMillis = 0;
final String testPackageName = "packageName";
@@ -272,8 +272,8 @@
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
minTimeIntervalBetweenSamplesMillis,
- samplingRatio,
- /*samplingRatios=*/ new SparseIntArray()));
+ samplingInterval,
+ /*samplingIntervals=*/ new SparseIntArray()));
logger.setLastPushTimeMillisLocked(SystemClock.elapsedRealtime());
// Makes sure sample will be logged if it is not too close to previous sample.
@@ -292,8 +292,8 @@
mContext.getUser(),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- TEST_DEFAULT_SAMPLING_RATIO,
- /*samplingRatios=*/ new SparseIntArray()));
+ TEST_DEFAULT_SAMPLING_INTERVAL,
+ /*samplingIntervals=*/ new SparseIntArray()));
mMockPackageManager.mockGetPackageUidAsUser(testPackageName, mContext.getUserId(), testUid);
//