blob: 5251636b860dc20dacc60bd1d57451a444facfff [file] [log] [blame]
/*
* Copyright (C) 2023 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.healthconnect;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.content.Context;
import android.health.connect.ratelimiter.RateLimiter;
import android.health.connect.ratelimiter.RateLimiter.QuotaBucket;
import android.provider.DeviceConfig;
import android.util.ArraySet;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Singleton class to provide values and listen changes of settings flags.
*
* @hide
*/
@SuppressLint("MissingPermission")
public class HealthConnectDeviceConfigManager implements DeviceConfig.OnPropertiesChangedListener {
private static Set<String> sFlagsToTrack = new ArraySet<>();
private static final String EXERCISE_ROUTE_FEATURE_FLAG = "exercise_routes_enable";
public static final String ENABLE_RATE_LIMITER_FLAG = "enable_rate_limiter";
private static final String MAX_READ_REQUESTS_PER_24H_FOREGROUND_FLAG =
"max_read_requests_per_24h_foreground";
private static final String MAX_READ_REQUESTS_PER_24H_BACKGROUND_FLAG =
"max_read_requests_per_24h_background";
private static final String MAX_READ_REQUESTS_PER_15M_FOREGROUND_FLAG =
"max_read_requests_per_15m_foreground";
private static final String MAX_READ_REQUESTS_PER_15M_BACKGROUND_FLAG =
"max_read_requests_per_15m_background";
private static final String MAX_WRITE_REQUESTS_PER_24H_FOREGROUND_FLAG =
"max_write_requests_per_24h_foreground";
private static final String MAX_WRITE_REQUESTS_PER_24H_BACKGROUND_FLAG =
"max_write_requests_per_24h_background";
private static final String MAX_WRITE_REQUESTS_PER_15M_FOREGROUND_FLAG =
"max_write_requests_per_15m_foreground";
private static final String MAX_WRITE_REQUESTS_PER_15M_BACKGROUND_FLAG =
"max_write_requests_per_15m_background";
private static final String MAX_DATA_PUSH_LIMIT_PER_APP_15M_BACKGROUND_FLAG =
"max_data_push_limit_per_app_15m_background";
private static final String MAX_DATA_PUSH_LIMIT_ACROSS_APPS_15M_BACKGROUND_FLAG =
"max_data_push_limit_across_apps_15m_background";
private static final String MAX_WRITE_CHUNK_SIZE_FLAG = "max_write_chunk_size";
private static final String MAX_WRITE_SINGLE_RECORD_SIZE_FLAG = "max_write_single_record_size";
// Flag to enable/disable sleep and exercise sessions.
private static final String SESSION_DATATYPE_FEATURE_FLAG = "session_types_enable";
@VisibleForTesting
public static final String COUNT_MIGRATION_STATE_IN_PROGRESS_FLAG =
"count_migration_state_in_progress";
@VisibleForTesting
public static final String COUNT_MIGRATION_STATE_ALLOWED_FLAG = "count_migration_state_allowed";
@VisibleForTesting
public static final String MAX_START_MIGRATION_CALLS_ALLOWED_FLAG =
"max_start_migration_calls_allowed";
@VisibleForTesting
public static final String IDLE_STATE_TIMEOUT_DAYS_FLAG = "idle_state_timeout_days";
@VisibleForTesting
public static final String NON_IDLE_STATE_TIMEOUT_DAYS_FLAG = "non_idle_state_timeout_days";
@VisibleForTesting
public static final String IN_PROGRESS_STATE_TIMEOUT_HOURS_FLAG =
"in_progress_state_timeout_hours";
@VisibleForTesting
public static final String EXECUTION_TIME_BUFFER_MINUTES_FLAG = "execution_time_buffer_minutes";
@VisibleForTesting
public static final String MIGRATION_COMPLETION_JOB_RUN_INTERVAL_DAYS_FLAG =
"migration_completion_job_run_interval_days";
@VisibleForTesting
public static final String MIGRATION_PAUSE_JOB_RUN_INTERVAL_HOURS_FLAG =
"migration_pause_job_run_interval_hours";
@VisibleForTesting
public static final String ENABLE_PAUSE_STATE_CHANGE_JOBS_FLAG =
"enable_pause_state_change_jobs";
@VisibleForTesting
public static final String ENABLE_COMPLETE_STATE_CHANGE_JOBS_FLAG =
"enable_complete_state_change_jobs";
@VisibleForTesting
public static final String ENABLE_MIGRATION_NOTIFICATIONS_FLAG =
"enable_migration_notifications";
@VisibleForTesting
public static final String BACKGROUND_READ_FEATURE_FLAG = "background_read_enable";
@VisibleForTesting
public static final String ENABLE_AGGREGATION_SOURCE_CONTROLS_FLAG =
"aggregation_source_controls_enable";
private static final boolean SESSION_DATATYPE_DEFAULT_FLAG_VALUE = true;
private static final boolean EXERCISE_ROUTE_DEFAULT_FLAG_VALUE = true;
public static final boolean ENABLE_RATE_LIMITER_DEFAULT_FLAG_VALUE = true;
public static final int QUOTA_BUCKET_PER_15M_FOREGROUND_DEFAULT_FLAG_VALUE = 1000;
public static final int QUOTA_BUCKET_PER_24H_FOREGROUND_DEFAULT_FLAG_VALUE = 8000;
public static final int QUOTA_BUCKET_PER_15M_BACKGROUND_DEFAULT_FLAG_VALUE = 1000;
public static final int QUOTA_BUCKET_PER_24H_BACKGROUND_DEFAULT_FLAG_VALUE = 8000;
public static final int CHUNK_SIZE_LIMIT_IN_BYTES_DEFAULT_FLAG_VALUE = 5000000;
public static final int RECORD_SIZE_LIMIT_IN_BYTES_DEFAULT_FLAG_VALUE = 1000000;
public static final int DATA_PUSH_LIMIT_PER_APP_15M_DEFAULT_FLAG_VALUE = 35000000;
public static final int DATA_PUSH_LIMIT_ACROSS_APPS_15M_DEFAULT_FLAG_VALUE = 100000000;
@VisibleForTesting
public static final int MIGRATION_STATE_IN_PROGRESS_COUNT_DEFAULT_FLAG_VALUE = 5;
@VisibleForTesting public static final int MIGRATION_STATE_ALLOWED_COUNT_DEFAULT_FLAG_VALUE = 5;
@VisibleForTesting public static final int MAX_START_MIGRATION_CALLS_DEFAULT_FLAG_VALUE = 6;
@VisibleForTesting public static final int IDLE_STATE_TIMEOUT_DAYS_DEFAULT_FLAG_VALUE = 120;
@VisibleForTesting public static final int NON_IDLE_STATE_TIMEOUT_DAYS_DEFAULT_FLAG_VALUE = 15;
@VisibleForTesting
public static final int IN_PROGRESS_STATE_TIMEOUT_HOURS_DEFAULT_FLAG_VALUE = 12;
@VisibleForTesting
public static final int EXECUTION_TIME_BUFFER_MINUTES_DEFAULT_FLAG_VALUE = 30;
@VisibleForTesting
public static final int MIGRATION_COMPLETION_JOB_RUN_INTERVAL_DAYS_DEFAULT_FLAG_VALUE = 1;
@VisibleForTesting
public static final int MIGRATION_PAUSE_JOB_RUN_INTERVAL_HOURS_DEFAULT_FLAG_VALUE = 4;
@VisibleForTesting
public static final boolean ENABLE_PAUSE_STATE_CHANGE_JOB_DEFAULT_FLAG_VALUE = true;
@VisibleForTesting
public static final boolean ENABLE_COMPLETE_STATE_CHANGE_JOB_DEFAULT_FLAG_VALUE = false;
@VisibleForTesting
public static final boolean ENABLE_MIGRATION_NOTIFICATIONS_DEFAULT_FLAG_VALUE = true;
@VisibleForTesting public static final boolean BACKGROUND_READ_DEFAULT_FLAG_VALUE = false;
@VisibleForTesting
public static final boolean ENABLE_AGGREGATION_SOURCE_CONTROLS_DEFAULT_FLAG_VALUE = false;
private static HealthConnectDeviceConfigManager sDeviceConfigManager;
private final ReentrantReadWriteLock mLock = new ReentrantReadWriteLock();
private static final String HEALTH_FITNESS_NAMESPACE = DeviceConfig.NAMESPACE_HEALTH_FITNESS;
@GuardedBy("mLock")
private boolean mExerciseRouteEnabled =
DeviceConfig.getBoolean(
HEALTH_FITNESS_NAMESPACE,
EXERCISE_ROUTE_FEATURE_FLAG,
EXERCISE_ROUTE_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private boolean mSessionDatatypeEnabled =
DeviceConfig.getBoolean(
HEALTH_FITNESS_NAMESPACE,
SESSION_DATATYPE_FEATURE_FLAG,
SESSION_DATATYPE_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private int mMigrationStateInProgressCount =
DeviceConfig.getInt(
HEALTH_FITNESS_NAMESPACE,
COUNT_MIGRATION_STATE_IN_PROGRESS_FLAG,
MIGRATION_STATE_IN_PROGRESS_COUNT_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private int mMigrationStateAllowedCount =
DeviceConfig.getInt(
HEALTH_FITNESS_NAMESPACE,
COUNT_MIGRATION_STATE_ALLOWED_FLAG,
MIGRATION_STATE_ALLOWED_COUNT_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private int mMaxStartMigrationCalls =
DeviceConfig.getInt(
HEALTH_FITNESS_NAMESPACE,
MAX_START_MIGRATION_CALLS_ALLOWED_FLAG,
MAX_START_MIGRATION_CALLS_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private int mIdleStateTimeoutPeriod =
DeviceConfig.getInt(
HEALTH_FITNESS_NAMESPACE,
IDLE_STATE_TIMEOUT_DAYS_FLAG,
IDLE_STATE_TIMEOUT_DAYS_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private int mNonIdleStateTimeoutPeriod =
DeviceConfig.getInt(
HEALTH_FITNESS_NAMESPACE,
NON_IDLE_STATE_TIMEOUT_DAYS_FLAG,
NON_IDLE_STATE_TIMEOUT_DAYS_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private int mInProgressStateTimeoutPeriod =
DeviceConfig.getInt(
HEALTH_FITNESS_NAMESPACE,
IN_PROGRESS_STATE_TIMEOUT_HOURS_FLAG,
IN_PROGRESS_STATE_TIMEOUT_HOURS_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private int mExecutionTimeBuffer =
DeviceConfig.getInt(
HEALTH_FITNESS_NAMESPACE,
EXECUTION_TIME_BUFFER_MINUTES_FLAG,
EXECUTION_TIME_BUFFER_MINUTES_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private int mMigrationCompletionJobRunInterval =
DeviceConfig.getInt(
HEALTH_FITNESS_NAMESPACE,
MIGRATION_COMPLETION_JOB_RUN_INTERVAL_DAYS_FLAG,
MIGRATION_COMPLETION_JOB_RUN_INTERVAL_DAYS_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private int mMigrationPauseJobRunInterval =
DeviceConfig.getInt(
HEALTH_FITNESS_NAMESPACE,
MIGRATION_PAUSE_JOB_RUN_INTERVAL_HOURS_FLAG,
MIGRATION_PAUSE_JOB_RUN_INTERVAL_HOURS_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private boolean mEnablePauseStateChangeJob =
DeviceConfig.getBoolean(
HEALTH_FITNESS_NAMESPACE,
ENABLE_PAUSE_STATE_CHANGE_JOBS_FLAG,
ENABLE_PAUSE_STATE_CHANGE_JOB_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private boolean mEnableCompleteStateChangeJob =
DeviceConfig.getBoolean(
HEALTH_FITNESS_NAMESPACE,
ENABLE_COMPLETE_STATE_CHANGE_JOBS_FLAG,
ENABLE_COMPLETE_STATE_CHANGE_JOB_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private boolean mEnableMigrationNotifications =
DeviceConfig.getBoolean(
HEALTH_FITNESS_NAMESPACE,
ENABLE_MIGRATION_NOTIFICATIONS_FLAG,
ENABLE_MIGRATION_NOTIFICATIONS_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private boolean mBackgroundReadFeatureEnabled =
DeviceConfig.getBoolean(
HEALTH_FITNESS_NAMESPACE,
BACKGROUND_READ_FEATURE_FLAG,
BACKGROUND_READ_DEFAULT_FLAG_VALUE);
@GuardedBy("mLock")
private boolean mAggregationSourceControlsEnabled =
DeviceConfig.getBoolean(
HEALTH_FITNESS_NAMESPACE,
ENABLE_AGGREGATION_SOURCE_CONTROLS_FLAG,
ENABLE_AGGREGATION_SOURCE_CONTROLS_DEFAULT_FLAG_VALUE);
@NonNull
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public static void initializeInstance(Context context) {
if (sDeviceConfigManager == null) {
sDeviceConfigManager = new HealthConnectDeviceConfigManager();
DeviceConfig.addOnPropertiesChangedListener(
HEALTH_FITNESS_NAMESPACE, context.getMainExecutor(), sDeviceConfigManager);
addFlagsToTrack();
}
}
/** Returns initialised instance of this class. */
@NonNull
public static HealthConnectDeviceConfigManager getInitialisedInstance() {
Objects.requireNonNull(sDeviceConfigManager);
return sDeviceConfigManager;
}
/** Adds flags that need to be updated if their values are changed on the server. */
private static void addFlagsToTrack() {
sFlagsToTrack.add(EXERCISE_ROUTE_FEATURE_FLAG);
sFlagsToTrack.add(SESSION_DATATYPE_FEATURE_FLAG);
sFlagsToTrack.add(ENABLE_RATE_LIMITER_FLAG);
sFlagsToTrack.add(COUNT_MIGRATION_STATE_IN_PROGRESS_FLAG);
sFlagsToTrack.add(COUNT_MIGRATION_STATE_ALLOWED_FLAG);
sFlagsToTrack.add(MAX_START_MIGRATION_CALLS_ALLOWED_FLAG);
sFlagsToTrack.add(IDLE_STATE_TIMEOUT_DAYS_FLAG);
sFlagsToTrack.add(NON_IDLE_STATE_TIMEOUT_DAYS_FLAG);
sFlagsToTrack.add(IN_PROGRESS_STATE_TIMEOUT_HOURS_FLAG);
sFlagsToTrack.add(EXECUTION_TIME_BUFFER_MINUTES_FLAG);
sFlagsToTrack.add(MIGRATION_COMPLETION_JOB_RUN_INTERVAL_DAYS_FLAG);
sFlagsToTrack.add(MIGRATION_PAUSE_JOB_RUN_INTERVAL_HOURS_FLAG);
sFlagsToTrack.add(ENABLE_PAUSE_STATE_CHANGE_JOBS_FLAG);
sFlagsToTrack.add(ENABLE_COMPLETE_STATE_CHANGE_JOBS_FLAG);
sFlagsToTrack.add(ENABLE_MIGRATION_NOTIFICATIONS_FLAG);
sFlagsToTrack.add(BACKGROUND_READ_FEATURE_FLAG);
sFlagsToTrack.add(ENABLE_AGGREGATION_SOURCE_CONTROLS_FLAG);
}
/** Returns if operations with exercise route are enabled. */
public boolean isExerciseRouteFeatureEnabled() {
mLock.readLock().lock();
try {
return mExerciseRouteEnabled;
} finally {
mLock.readLock().unlock();
}
}
@GuardedBy("mLock")
private boolean mRateLimiterEnabled =
DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_HEALTH_FITNESS,
ENABLE_RATE_LIMITER_FLAG,
ENABLE_RATE_LIMITER_DEFAULT_FLAG_VALUE);
/** Returns if operations with sessions datatypes are enabled. */
public boolean isSessionDatatypeFeatureEnabled() {
mLock.readLock().lock();
try {
return mSessionDatatypeEnabled;
} finally {
mLock.readLock().unlock();
}
}
/**
* Returns the required count for {@link
* android.health.connect.HealthConnectDataState.MIGRATION_STATE_IN_PROGRESS}.
*/
public int getMigrationStateInProgressCount() {
mLock.readLock().lock();
try {
return mMigrationStateInProgressCount;
} finally {
mLock.readLock().unlock();
}
}
/**
* Returns the required count for {@link
* android.health.connect.HealthConnectDataState.MIGRATION_STATE_ALLOWED}.
*/
public int getMigrationStateAllowedCount() {
mLock.readLock().lock();
try {
return mMigrationStateAllowedCount;
} finally {
mLock.readLock().unlock();
}
}
/** Returns the maximum number of start migration calls allowed. */
public int getMaxStartMigrationCalls() {
mLock.readLock().lock();
try {
return mMaxStartMigrationCalls;
} finally {
mLock.readLock().unlock();
}
}
/**
* Returns the timeout period of {@link
* android.health.connect.HealthConnectDataState.MIGRATION_STATE_IDLE}.
*/
public Duration getIdleStateTimeoutPeriod() {
mLock.readLock().lock();
try {
return Duration.ofDays(mIdleStateTimeoutPeriod);
} finally {
mLock.readLock().unlock();
}
}
/** Returns the timeout period of non-idle migration states. */
public Duration getNonIdleStateTimeoutPeriod() {
mLock.readLock().lock();
try {
return Duration.ofDays(mNonIdleStateTimeoutPeriod);
} finally {
mLock.readLock().unlock();
}
}
/**
* Returns the timeout period of {@link
* android.health.connect.HealthConnectDataState.MIGRATION_STATE_IN_PROGRESS}.
*/
public Duration getInProgressStateTimeoutPeriod() {
mLock.readLock().lock();
try {
return Duration.ofHours(mInProgressStateTimeoutPeriod);
} finally {
mLock.readLock().unlock();
}
}
/** Returns the time buffer kept to ensure that job execution is not skipped. */
public long getExecutionTimeBuffer() {
mLock.readLock().lock();
try {
return TimeUnit.MINUTES.toMillis(mExecutionTimeBuffer);
} finally {
mLock.readLock().unlock();
}
}
/** Returns the time interval at which the migration completion job will run periodically. */
public long getMigrationCompletionJobRunInterval() {
mLock.readLock().lock();
try {
return TimeUnit.DAYS.toMillis(mMigrationCompletionJobRunInterval);
} finally {
mLock.readLock().unlock();
}
}
/** Returns the time interval at which the migration pause job will run periodically. */
public long getMigrationPauseJobRunInterval() {
mLock.readLock().lock();
try {
return TimeUnit.HOURS.toMillis(mMigrationPauseJobRunInterval);
} finally {
mLock.readLock().unlock();
}
}
/** Returns if migration pause change jobs are enabled. */
public boolean isPauseStateChangeJobEnabled() {
mLock.readLock().lock();
try {
return mEnablePauseStateChangeJob;
} finally {
mLock.readLock().unlock();
}
}
/** Returns if migration completion jobs are enabled. */
public boolean isCompleteStateChangeJobEnabled() {
mLock.readLock().lock();
try {
return mEnableCompleteStateChangeJob;
} finally {
mLock.readLock().unlock();
}
}
/** Returns if migration notifications are enabled. */
public boolean areMigrationNotificationsEnabled() {
mLock.readLock().lock();
try {
return mEnableMigrationNotifications;
} finally {
mLock.readLock().unlock();
}
}
/** Returns whether reading in background is enabled or not. */
public boolean isBackgroundReadFeatureEnabled() {
mLock.readLock().lock();
try {
return mBackgroundReadFeatureEnabled;
} finally {
mLock.readLock().unlock();
}
}
/** Returns whether the new aggregation source control feature is enabled or not. */
public boolean isAggregationSourceControlsEnabled() {
mLock.readLock().lock();
try {
return mAggregationSourceControlsEnabled;
} finally {
mLock.readLock().unlock();
}
}
/** Updates rate limiting quota values. */
public void updateRateLimiterValues() {
Map<Integer, Integer> quotaBucketToMaxRollingQuotaMap = new HashMap<>();
Map<String, Integer> quotaBucketToMaxMemoryQuotaMap = new HashMap<>();
quotaBucketToMaxRollingQuotaMap.put(
QuotaBucket.QUOTA_BUCKET_READS_PER_24H_FOREGROUND,
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_HEALTH_FITNESS,
MAX_READ_REQUESTS_PER_24H_FOREGROUND_FLAG,
QUOTA_BUCKET_PER_24H_FOREGROUND_DEFAULT_FLAG_VALUE));
quotaBucketToMaxRollingQuotaMap.put(
QuotaBucket.QUOTA_BUCKET_READS_PER_24H_BACKGROUND,
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_HEALTH_FITNESS,
MAX_READ_REQUESTS_PER_24H_BACKGROUND_FLAG,
QUOTA_BUCKET_PER_24H_BACKGROUND_DEFAULT_FLAG_VALUE));
quotaBucketToMaxRollingQuotaMap.put(
QuotaBucket.QUOTA_BUCKET_READS_PER_15M_FOREGROUND,
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_HEALTH_FITNESS,
MAX_READ_REQUESTS_PER_15M_FOREGROUND_FLAG,
QUOTA_BUCKET_PER_15M_FOREGROUND_DEFAULT_FLAG_VALUE));
quotaBucketToMaxRollingQuotaMap.put(
QuotaBucket.QUOTA_BUCKET_READS_PER_15M_BACKGROUND,
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_HEALTH_FITNESS,
MAX_READ_REQUESTS_PER_15M_BACKGROUND_FLAG,
QUOTA_BUCKET_PER_15M_BACKGROUND_DEFAULT_FLAG_VALUE));
quotaBucketToMaxRollingQuotaMap.put(
QuotaBucket.QUOTA_BUCKET_WRITES_PER_24H_FOREGROUND,
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_HEALTH_FITNESS,
MAX_WRITE_REQUESTS_PER_24H_FOREGROUND_FLAG,
QUOTA_BUCKET_PER_24H_FOREGROUND_DEFAULT_FLAG_VALUE));
quotaBucketToMaxRollingQuotaMap.put(
QuotaBucket.QUOTA_BUCKET_WRITES_PER_24H_BACKGROUND,
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_HEALTH_FITNESS,
MAX_WRITE_REQUESTS_PER_24H_BACKGROUND_FLAG,
QUOTA_BUCKET_PER_24H_BACKGROUND_DEFAULT_FLAG_VALUE));
quotaBucketToMaxRollingQuotaMap.put(
QuotaBucket.QUOTA_BUCKET_WRITES_PER_15M_FOREGROUND,
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_HEALTH_FITNESS,
MAX_WRITE_REQUESTS_PER_15M_FOREGROUND_FLAG,
QUOTA_BUCKET_PER_15M_FOREGROUND_DEFAULT_FLAG_VALUE));
quotaBucketToMaxRollingQuotaMap.put(
QuotaBucket.QUOTA_BUCKET_WRITES_PER_15M_BACKGROUND,
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_HEALTH_FITNESS,
MAX_WRITE_REQUESTS_PER_15M_BACKGROUND_FLAG,
QUOTA_BUCKET_PER_15M_BACKGROUND_DEFAULT_FLAG_VALUE));
quotaBucketToMaxRollingQuotaMap.put(
QuotaBucket.QUOTA_BUCKET_DATA_PUSH_LIMIT_PER_APP_15M,
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_HEALTH_FITNESS,
MAX_DATA_PUSH_LIMIT_PER_APP_15M_BACKGROUND_FLAG,
DATA_PUSH_LIMIT_PER_APP_15M_DEFAULT_FLAG_VALUE));
quotaBucketToMaxRollingQuotaMap.put(
QuotaBucket.QUOTA_BUCKET_DATA_PUSH_LIMIT_ACROSS_APPS_15M,
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_HEALTH_FITNESS,
MAX_DATA_PUSH_LIMIT_ACROSS_APPS_15M_BACKGROUND_FLAG,
DATA_PUSH_LIMIT_ACROSS_APPS_15M_DEFAULT_FLAG_VALUE));
quotaBucketToMaxMemoryQuotaMap.put(
RateLimiter.CHUNK_SIZE_LIMIT_IN_BYTES,
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_HEALTH_FITNESS,
MAX_WRITE_CHUNK_SIZE_FLAG,
CHUNK_SIZE_LIMIT_IN_BYTES_DEFAULT_FLAG_VALUE));
quotaBucketToMaxMemoryQuotaMap.put(
RateLimiter.RECORD_SIZE_LIMIT_IN_BYTES,
DeviceConfig.getInt(
DeviceConfig.NAMESPACE_HEALTH_FITNESS,
MAX_WRITE_SINGLE_RECORD_SIZE_FLAG,
RECORD_SIZE_LIMIT_IN_BYTES_DEFAULT_FLAG_VALUE));
RateLimiter.updateMaxRollingQuotaMap(quotaBucketToMaxRollingQuotaMap);
RateLimiter.updateMemoryQuotaMap(quotaBucketToMaxMemoryQuotaMap);
mLock.readLock().lock();
try {
RateLimiter.updateEnableRateLimiterFlag(mRateLimiterEnabled);
} finally {
mLock.readLock().unlock();
}
}
@Override
public void onPropertiesChanged(DeviceConfig.Properties properties) {
if (!properties.getNamespace().equals(HEALTH_FITNESS_NAMESPACE)) {
return;
}
Set<String> changedFlags = new ArraySet<>(properties.getKeyset());
changedFlags.retainAll(sFlagsToTrack);
for (String name : changedFlags) {
try {
mLock.writeLock().lock();
switch (name) {
case EXERCISE_ROUTE_FEATURE_FLAG:
mExerciseRouteEnabled =
properties.getBoolean(
EXERCISE_ROUTE_FEATURE_FLAG,
EXERCISE_ROUTE_DEFAULT_FLAG_VALUE);
break;
case SESSION_DATATYPE_FEATURE_FLAG:
mSessionDatatypeEnabled =
properties.getBoolean(
SESSION_DATATYPE_FEATURE_FLAG,
SESSION_DATATYPE_DEFAULT_FLAG_VALUE);
break;
case ENABLE_RATE_LIMITER_FLAG:
mRateLimiterEnabled =
properties.getBoolean(
ENABLE_RATE_LIMITER_FLAG,
ENABLE_RATE_LIMITER_DEFAULT_FLAG_VALUE);
RateLimiter.updateEnableRateLimiterFlag(mRateLimiterEnabled);
break;
case COUNT_MIGRATION_STATE_IN_PROGRESS_FLAG:
mMigrationStateInProgressCount =
properties.getInt(
COUNT_MIGRATION_STATE_IN_PROGRESS_FLAG,
MIGRATION_STATE_IN_PROGRESS_COUNT_DEFAULT_FLAG_VALUE);
break;
case COUNT_MIGRATION_STATE_ALLOWED_FLAG:
mMigrationStateAllowedCount =
properties.getInt(
COUNT_MIGRATION_STATE_ALLOWED_FLAG,
MIGRATION_STATE_ALLOWED_COUNT_DEFAULT_FLAG_VALUE);
break;
case MAX_START_MIGRATION_CALLS_ALLOWED_FLAG:
mMaxStartMigrationCalls =
properties.getInt(
MAX_START_MIGRATION_CALLS_ALLOWED_FLAG,
MAX_START_MIGRATION_CALLS_DEFAULT_FLAG_VALUE);
break;
case IDLE_STATE_TIMEOUT_DAYS_FLAG:
mIdleStateTimeoutPeriod =
properties.getInt(
IDLE_STATE_TIMEOUT_DAYS_FLAG,
IDLE_STATE_TIMEOUT_DAYS_DEFAULT_FLAG_VALUE);
break;
case NON_IDLE_STATE_TIMEOUT_DAYS_FLAG:
mNonIdleStateTimeoutPeriod =
properties.getInt(
NON_IDLE_STATE_TIMEOUT_DAYS_FLAG,
NON_IDLE_STATE_TIMEOUT_DAYS_DEFAULT_FLAG_VALUE);
break;
case IN_PROGRESS_STATE_TIMEOUT_HOURS_FLAG:
mInProgressStateTimeoutPeriod =
properties.getInt(
IN_PROGRESS_STATE_TIMEOUT_HOURS_FLAG,
IN_PROGRESS_STATE_TIMEOUT_HOURS_DEFAULT_FLAG_VALUE);
break;
case EXECUTION_TIME_BUFFER_MINUTES_FLAG:
mExecutionTimeBuffer =
properties.getInt(
EXECUTION_TIME_BUFFER_MINUTES_FLAG,
EXECUTION_TIME_BUFFER_MINUTES_DEFAULT_FLAG_VALUE);
break;
case MIGRATION_COMPLETION_JOB_RUN_INTERVAL_DAYS_FLAG:
mMigrationCompletionJobRunInterval =
properties.getInt(
MIGRATION_COMPLETION_JOB_RUN_INTERVAL_DAYS_FLAG,
MIGRATION_COMPLETION_JOB_RUN_INTERVAL_DAYS_DEFAULT_FLAG_VALUE);
break;
case MIGRATION_PAUSE_JOB_RUN_INTERVAL_HOURS_FLAG:
mMigrationPauseJobRunInterval =
properties.getInt(
MIGRATION_PAUSE_JOB_RUN_INTERVAL_HOURS_FLAG,
MIGRATION_PAUSE_JOB_RUN_INTERVAL_HOURS_DEFAULT_FLAG_VALUE);
break;
case ENABLE_PAUSE_STATE_CHANGE_JOBS_FLAG:
mEnablePauseStateChangeJob =
properties.getBoolean(
ENABLE_PAUSE_STATE_CHANGE_JOBS_FLAG,
ENABLE_PAUSE_STATE_CHANGE_JOB_DEFAULT_FLAG_VALUE);
break;
case ENABLE_COMPLETE_STATE_CHANGE_JOBS_FLAG:
mEnableCompleteStateChangeJob =
properties.getBoolean(
ENABLE_COMPLETE_STATE_CHANGE_JOBS_FLAG,
ENABLE_COMPLETE_STATE_CHANGE_JOB_DEFAULT_FLAG_VALUE);
break;
case ENABLE_MIGRATION_NOTIFICATIONS_FLAG:
mEnableMigrationNotifications =
properties.getBoolean(
ENABLE_MIGRATION_NOTIFICATIONS_FLAG,
ENABLE_MIGRATION_NOTIFICATIONS_DEFAULT_FLAG_VALUE);
break;
case BACKGROUND_READ_FEATURE_FLAG:
mBackgroundReadFeatureEnabled =
properties.getBoolean(
BACKGROUND_READ_FEATURE_FLAG,
BACKGROUND_READ_DEFAULT_FLAG_VALUE);
break;
case ENABLE_AGGREGATION_SOURCE_CONTROLS_FLAG:
mAggregationSourceControlsEnabled =
properties.getBoolean(
ENABLE_AGGREGATION_SOURCE_CONTROLS_FLAG,
ENABLE_AGGREGATION_SOURCE_CONTROLS_DEFAULT_FLAG_VALUE);
}
} finally {
mLock.writeLock().unlock();
}
}
}
}