diff options
10 files changed, 803 insertions, 357 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index 158d914575c6..e6c94d896e50 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -32,6 +32,7 @@ import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.app.BroadcastOptions; import android.content.BroadcastReceiver; +import android.content.ContentResolver; import android.content.Context; import android.content.IIntentReceiver; import android.content.Intent; @@ -41,6 +42,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; import android.content.res.Resources; +import android.database.ContentObserver; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; @@ -81,6 +83,7 @@ import android.os.Trace; import android.os.UserHandle; import android.os.WearModeManagerInternal; import android.provider.DeviceConfig; +import android.provider.Settings; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.telephony.emergency.EmergencyNumber; @@ -109,6 +112,7 @@ import com.android.server.deviceidle.DeviceIdleConstraintTracker; import com.android.server.deviceidle.IDeviceIdleConstraint; import com.android.server.deviceidle.TvConstraintController; import com.android.server.net.NetworkPolicyManagerInternal; +import com.android.server.utils.UserSettingDeviceConfigMediator; import com.android.server.wm.ActivityTaskManagerInternal; import org.xmlpull.v1.XmlPullParser; @@ -1020,7 +1024,8 @@ public class DeviceIdleController extends SystemService * global Settings. Any access to this class or its fields should be done while * holding the DeviceIdleController lock. */ - public final class Constants implements DeviceConfig.OnPropertiesChangedListener { + public final class Constants extends ContentObserver + implements DeviceConfig.OnPropertiesChangedListener { // Key names stored in the settings value. private static final String KEY_FLEX_TIME_SHORT = "flex_time_short"; private static final String KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = @@ -1396,6 +1401,7 @@ public class DeviceIdleController extends SystemService /** * Amount of time we would like to whitelist an app that is handling a * {@link android.app.PendingIntent} triggered by a {@link android.app.Notification}. + * * @see #KEY_NOTIFICATION_ALLOWLIST_DURATION_MS */ public long NOTIFICATION_ALLOWLIST_DURATION_MS = mDefaultNotificationAllowlistDurationMs; @@ -1413,9 +1419,14 @@ public class DeviceIdleController extends SystemService */ public boolean USE_MODE_MANAGER = mDefaultUseModeManager; + private final ContentResolver mResolver; private final boolean mSmallBatteryDevice; + private final UserSettingDeviceConfigMediator mUserSettingDeviceConfigMediator = + new UserSettingDeviceConfigMediator.SettingsOverridesIndividualMediator(','); - public Constants() { + public Constants(Handler handler, ContentResolver resolver) { + super(handler); + mResolver = resolver; initDefault(); mSmallBatteryDevice = ActivityManager.isSmallBatteryDevice(); if (mSmallBatteryDevice) { @@ -1424,8 +1435,14 @@ public class DeviceIdleController extends SystemService } DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DEVICE_IDLE, AppSchedulingModuleThread.getExecutor(), this); + mResolver.registerContentObserver( + Settings.Global.getUriFor(Settings.Global.DEVICE_IDLE_CONSTANTS), + false, this); // Load all the constants. - onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_DEVICE_IDLE)); + updateSettingsConstantLocked(); + mUserSettingDeviceConfigMediator.setDeviceConfigProperties( + DeviceConfig.getProperties(DeviceConfig.NAMESPACE_DEVICE_IDLE)); + updateConstantsLocked(); } private void initDefault() { @@ -1574,188 +1591,166 @@ public class DeviceIdleController extends SystemService return (!COMPRESS_TIME || defTimeout < compTimeout) ? defTimeout : compTimeout; } + @Override + public void onChange(boolean selfChange, Uri uri) { + synchronized (DeviceIdleController.this) { + updateSettingsConstantLocked(); + updateConstantsLocked(); + } + } + + private void updateSettingsConstantLocked() { + try { + mUserSettingDeviceConfigMediator.setSettingsString( + Settings.Global.getString(mResolver, + Settings.Global.DEVICE_IDLE_CONSTANTS)); + } catch (IllegalArgumentException e) { + // Failed to parse the settings string, log this and move on with previous values. + Slog.e(TAG, "Bad device idle settings", e); + } + } @Override public void onPropertiesChanged(DeviceConfig.Properties properties) { synchronized (DeviceIdleController.this) { - for (String name : properties.getKeyset()) { - if (name == null) { - continue; - } - switch (name) { - case KEY_FLEX_TIME_SHORT: - FLEX_TIME_SHORT = properties.getLong( - KEY_FLEX_TIME_SHORT, mDefaultFlexTimeShort); - break; - case KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT: - LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = properties.getLong( - KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT, - mDefaultLightIdleAfterInactiveTimeout); - break; - case KEY_LIGHT_IDLE_TIMEOUT: - LIGHT_IDLE_TIMEOUT = properties.getLong( - KEY_LIGHT_IDLE_TIMEOUT, mDefaultLightIdleTimeout); - break; - case KEY_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX: - LIGHT_IDLE_TIMEOUT_INITIAL_FLEX = properties.getLong( - KEY_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX, - mDefaultLightIdleTimeoutInitialFlex); - break; - case KEY_LIGHT_IDLE_TIMEOUT_MAX_FLEX: - LIGHT_IDLE_TIMEOUT_MAX_FLEX = properties.getLong( - KEY_LIGHT_IDLE_TIMEOUT_MAX_FLEX, - mDefaultLightIdleTimeoutMaxFlex); - break; - case KEY_LIGHT_IDLE_FACTOR: - LIGHT_IDLE_FACTOR = Math.max(1, properties.getFloat( - KEY_LIGHT_IDLE_FACTOR, mDefaultLightIdleFactor)); - break; - case KEY_LIGHT_IDLE_INCREASE_LINEARLY: - LIGHT_IDLE_INCREASE_LINEARLY = properties.getBoolean( - KEY_LIGHT_IDLE_INCREASE_LINEARLY, - mDefaultLightIdleIncreaseLinearly); - break; - case KEY_LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS: - LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS = properties.getLong( - KEY_LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS, - mDefaultLightIdleLinearIncreaseFactorMs); - break; - case KEY_LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS: - LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS = properties.getLong( - KEY_LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS, - mDefaultLightIdleFlexLinearIncreaseFactorMs); - break; - case KEY_LIGHT_MAX_IDLE_TIMEOUT: - LIGHT_MAX_IDLE_TIMEOUT = properties.getLong( - KEY_LIGHT_MAX_IDLE_TIMEOUT, mDefaultLightMaxIdleTimeout); - break; - case KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET: - LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = properties.getLong( - KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET, - mDefaultLightIdleMaintenanceMinBudget); - break; - case KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET: - LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = properties.getLong( - KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET, - mDefaultLightIdleMaintenanceMaxBudget); - break; - case KEY_MIN_LIGHT_MAINTENANCE_TIME: - MIN_LIGHT_MAINTENANCE_TIME = properties.getLong( - KEY_MIN_LIGHT_MAINTENANCE_TIME, - mDefaultMinLightMaintenanceTime); - break; - case KEY_MIN_DEEP_MAINTENANCE_TIME: - MIN_DEEP_MAINTENANCE_TIME = properties.getLong( - KEY_MIN_DEEP_MAINTENANCE_TIME, - mDefaultMinDeepMaintenanceTime); - break; - case KEY_INACTIVE_TIMEOUT: - final long defaultInactiveTimeout = mSmallBatteryDevice - ? DEFAULT_INACTIVE_TIMEOUT_SMALL_BATTERY - : mDefaultInactiveTimeout; - INACTIVE_TIMEOUT = properties.getLong( - KEY_INACTIVE_TIMEOUT, defaultInactiveTimeout); - break; - case KEY_SENSING_TIMEOUT: - SENSING_TIMEOUT = properties.getLong( - KEY_SENSING_TIMEOUT, mDefaultSensingTimeout); - break; - case KEY_LOCATING_TIMEOUT: - LOCATING_TIMEOUT = properties.getLong( - KEY_LOCATING_TIMEOUT, mDefaultLocatingTimeout); - break; - case KEY_LOCATION_ACCURACY: - LOCATION_ACCURACY = properties.getFloat( - KEY_LOCATION_ACCURACY, mDefaultLocationAccuracy); - break; - case KEY_MOTION_INACTIVE_TIMEOUT: - MOTION_INACTIVE_TIMEOUT = properties.getLong( - KEY_MOTION_INACTIVE_TIMEOUT, mDefaultMotionInactiveTimeout); - break; - case KEY_MOTION_INACTIVE_TIMEOUT_FLEX: - MOTION_INACTIVE_TIMEOUT_FLEX = properties.getLong( - KEY_MOTION_INACTIVE_TIMEOUT_FLEX, - mDefaultMotionInactiveTimeoutFlex); - break; - case KEY_IDLE_AFTER_INACTIVE_TIMEOUT: - final long defaultIdleAfterInactiveTimeout = mSmallBatteryDevice - ? DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT_SMALL_BATTERY - : mDefaultIdleAfterInactiveTimeout; - IDLE_AFTER_INACTIVE_TIMEOUT = properties.getLong( - KEY_IDLE_AFTER_INACTIVE_TIMEOUT, - defaultIdleAfterInactiveTimeout); - break; - case KEY_IDLE_PENDING_TIMEOUT: - IDLE_PENDING_TIMEOUT = properties.getLong( - KEY_IDLE_PENDING_TIMEOUT, mDefaultIdlePendingTimeout); - break; - case KEY_MAX_IDLE_PENDING_TIMEOUT: - MAX_IDLE_PENDING_TIMEOUT = properties.getLong( - KEY_MAX_IDLE_PENDING_TIMEOUT, mDefaultMaxIdlePendingTimeout); - break; - case KEY_IDLE_PENDING_FACTOR: - IDLE_PENDING_FACTOR = properties.getFloat( - KEY_IDLE_PENDING_FACTOR, mDefaultIdlePendingFactor); - break; - case KEY_QUICK_DOZE_DELAY_TIMEOUT: - QUICK_DOZE_DELAY_TIMEOUT = properties.getLong( - KEY_QUICK_DOZE_DELAY_TIMEOUT, mDefaultQuickDozeDelayTimeout); - break; - case KEY_IDLE_TIMEOUT: - IDLE_TIMEOUT = properties.getLong( - KEY_IDLE_TIMEOUT, mDefaultIdleTimeout); - break; - case KEY_MAX_IDLE_TIMEOUT: - MAX_IDLE_TIMEOUT = properties.getLong( - KEY_MAX_IDLE_TIMEOUT, mDefaultMaxIdleTimeout); - break; - case KEY_IDLE_FACTOR: - IDLE_FACTOR = properties.getFloat(KEY_IDLE_FACTOR, mDefaultIdleFactor); - break; - case KEY_MIN_TIME_TO_ALARM: - MIN_TIME_TO_ALARM = properties.getLong( - KEY_MIN_TIME_TO_ALARM, mDefaultMinTimeToAlarm); - break; - case KEY_MAX_TEMP_APP_ALLOWLIST_DURATION_MS: - MAX_TEMP_APP_ALLOWLIST_DURATION_MS = properties.getLong( - KEY_MAX_TEMP_APP_ALLOWLIST_DURATION_MS, - mDefaultMaxTempAppAllowlistDurationMs); - break; - case KEY_MMS_TEMP_APP_ALLOWLIST_DURATION_MS: - MMS_TEMP_APP_ALLOWLIST_DURATION_MS = properties.getLong( - KEY_MMS_TEMP_APP_ALLOWLIST_DURATION_MS, - mDefaultMmsTempAppAllowlistDurationMs); - break; - case KEY_SMS_TEMP_APP_ALLOWLIST_DURATION_MS: - SMS_TEMP_APP_ALLOWLIST_DURATION_MS = properties.getLong( - KEY_SMS_TEMP_APP_ALLOWLIST_DURATION_MS, - mDefaultSmsTempAppAllowlistDurationMs); - break; - case KEY_NOTIFICATION_ALLOWLIST_DURATION_MS: - NOTIFICATION_ALLOWLIST_DURATION_MS = properties.getLong( - KEY_NOTIFICATION_ALLOWLIST_DURATION_MS, - mDefaultNotificationAllowlistDurationMs); - break; - case KEY_WAIT_FOR_UNLOCK: - WAIT_FOR_UNLOCK = properties.getBoolean( - KEY_WAIT_FOR_UNLOCK, mDefaultWaitForUnlock); - break; - case KEY_USE_WINDOW_ALARMS: - USE_WINDOW_ALARMS = properties.getBoolean( - KEY_USE_WINDOW_ALARMS, mDefaultUseWindowAlarms); - break; - case KEY_USE_MODE_MANAGER: - USE_MODE_MANAGER = properties.getBoolean( - KEY_USE_MODE_MANAGER, mDefaultUseModeManager); - break; - default: - Slog.e(TAG, "Unknown configuration key: " + name); - break; - } - } + mUserSettingDeviceConfigMediator.setDeviceConfigProperties(properties); + updateConstantsLocked(); } } + private void updateConstantsLocked() { + if (mSmallBatteryDevice) return; + FLEX_TIME_SHORT = mUserSettingDeviceConfigMediator.getLong( + KEY_FLEX_TIME_SHORT, mDefaultFlexTimeShort); + + LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = mUserSettingDeviceConfigMediator.getLong( + KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT, + mDefaultLightIdleAfterInactiveTimeout); + + LIGHT_IDLE_TIMEOUT = mUserSettingDeviceConfigMediator.getLong( + KEY_LIGHT_IDLE_TIMEOUT, mDefaultLightIdleTimeout); + + LIGHT_IDLE_TIMEOUT_INITIAL_FLEX = mUserSettingDeviceConfigMediator.getLong( + KEY_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX, + mDefaultLightIdleTimeoutInitialFlex); + + LIGHT_IDLE_TIMEOUT_MAX_FLEX = mUserSettingDeviceConfigMediator.getLong( + KEY_LIGHT_IDLE_TIMEOUT_MAX_FLEX, + mDefaultLightIdleTimeoutMaxFlex); + + LIGHT_IDLE_FACTOR = Math.max(1, mUserSettingDeviceConfigMediator.getFloat( + KEY_LIGHT_IDLE_FACTOR, mDefaultLightIdleFactor)); + + LIGHT_IDLE_INCREASE_LINEARLY = mUserSettingDeviceConfigMediator.getBoolean( + KEY_LIGHT_IDLE_INCREASE_LINEARLY, + mDefaultLightIdleIncreaseLinearly); + + LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS = mUserSettingDeviceConfigMediator.getLong( + KEY_LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS, + mDefaultLightIdleLinearIncreaseFactorMs); + + LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS = mUserSettingDeviceConfigMediator.getLong( + KEY_LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS, + mDefaultLightIdleFlexLinearIncreaseFactorMs); + + LIGHT_MAX_IDLE_TIMEOUT = mUserSettingDeviceConfigMediator.getLong( + KEY_LIGHT_MAX_IDLE_TIMEOUT, mDefaultLightMaxIdleTimeout); + + LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = mUserSettingDeviceConfigMediator.getLong( + KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET, + mDefaultLightIdleMaintenanceMinBudget); + + LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = mUserSettingDeviceConfigMediator.getLong( + KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET, + mDefaultLightIdleMaintenanceMaxBudget); + + MIN_LIGHT_MAINTENANCE_TIME = mUserSettingDeviceConfigMediator.getLong( + KEY_MIN_LIGHT_MAINTENANCE_TIME, + mDefaultMinLightMaintenanceTime); + + MIN_DEEP_MAINTENANCE_TIME = mUserSettingDeviceConfigMediator.getLong( + KEY_MIN_DEEP_MAINTENANCE_TIME, + mDefaultMinDeepMaintenanceTime); + + final long defaultInactiveTimeout = mSmallBatteryDevice + ? DEFAULT_INACTIVE_TIMEOUT_SMALL_BATTERY + : mDefaultInactiveTimeout; + INACTIVE_TIMEOUT = mUserSettingDeviceConfigMediator.getLong( + KEY_INACTIVE_TIMEOUT, defaultInactiveTimeout); + + SENSING_TIMEOUT = mUserSettingDeviceConfigMediator.getLong( + KEY_SENSING_TIMEOUT, mDefaultSensingTimeout); + + LOCATING_TIMEOUT = mUserSettingDeviceConfigMediator.getLong( + KEY_LOCATING_TIMEOUT, mDefaultLocatingTimeout); + + LOCATION_ACCURACY = mUserSettingDeviceConfigMediator.getFloat( + KEY_LOCATION_ACCURACY, mDefaultLocationAccuracy); + + MOTION_INACTIVE_TIMEOUT = mUserSettingDeviceConfigMediator.getLong( + KEY_MOTION_INACTIVE_TIMEOUT, mDefaultMotionInactiveTimeout); + + MOTION_INACTIVE_TIMEOUT_FLEX = mUserSettingDeviceConfigMediator.getLong( + KEY_MOTION_INACTIVE_TIMEOUT_FLEX, + mDefaultMotionInactiveTimeoutFlex); + + final long defaultIdleAfterInactiveTimeout = mSmallBatteryDevice + ? DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT_SMALL_BATTERY + : mDefaultIdleAfterInactiveTimeout; + IDLE_AFTER_INACTIVE_TIMEOUT = mUserSettingDeviceConfigMediator.getLong( + KEY_IDLE_AFTER_INACTIVE_TIMEOUT, + defaultIdleAfterInactiveTimeout); + + IDLE_PENDING_TIMEOUT = mUserSettingDeviceConfigMediator.getLong( + KEY_IDLE_PENDING_TIMEOUT, mDefaultIdlePendingTimeout); + + MAX_IDLE_PENDING_TIMEOUT = mUserSettingDeviceConfigMediator.getLong( + KEY_MAX_IDLE_PENDING_TIMEOUT, mDefaultMaxIdlePendingTimeout); + + IDLE_PENDING_FACTOR = mUserSettingDeviceConfigMediator.getFloat( + KEY_IDLE_PENDING_FACTOR, mDefaultIdlePendingFactor); + + QUICK_DOZE_DELAY_TIMEOUT = mUserSettingDeviceConfigMediator.getLong( + KEY_QUICK_DOZE_DELAY_TIMEOUT, mDefaultQuickDozeDelayTimeout); + + IDLE_TIMEOUT = mUserSettingDeviceConfigMediator.getLong( + KEY_IDLE_TIMEOUT, mDefaultIdleTimeout); + + MAX_IDLE_TIMEOUT = mUserSettingDeviceConfigMediator.getLong( + KEY_MAX_IDLE_TIMEOUT, mDefaultMaxIdleTimeout); + + IDLE_FACTOR = mUserSettingDeviceConfigMediator.getFloat(KEY_IDLE_FACTOR, + mDefaultIdleFactor); + + MIN_TIME_TO_ALARM = mUserSettingDeviceConfigMediator.getLong( + KEY_MIN_TIME_TO_ALARM, mDefaultMinTimeToAlarm); + + MAX_TEMP_APP_ALLOWLIST_DURATION_MS = mUserSettingDeviceConfigMediator.getLong( + KEY_MAX_TEMP_APP_ALLOWLIST_DURATION_MS, + mDefaultMaxTempAppAllowlistDurationMs); + + MMS_TEMP_APP_ALLOWLIST_DURATION_MS = mUserSettingDeviceConfigMediator.getLong( + KEY_MMS_TEMP_APP_ALLOWLIST_DURATION_MS, + mDefaultMmsTempAppAllowlistDurationMs); + + SMS_TEMP_APP_ALLOWLIST_DURATION_MS = mUserSettingDeviceConfigMediator.getLong( + KEY_SMS_TEMP_APP_ALLOWLIST_DURATION_MS, + mDefaultSmsTempAppAllowlistDurationMs); + + NOTIFICATION_ALLOWLIST_DURATION_MS = mUserSettingDeviceConfigMediator.getLong( + KEY_NOTIFICATION_ALLOWLIST_DURATION_MS, + mDefaultNotificationAllowlistDurationMs); + + WAIT_FOR_UNLOCK = mUserSettingDeviceConfigMediator.getBoolean( + KEY_WAIT_FOR_UNLOCK, mDefaultWaitForUnlock); + + USE_WINDOW_ALARMS = mUserSettingDeviceConfigMediator.getBoolean( + KEY_USE_WINDOW_ALARMS, mDefaultUseWindowAlarms); + + USE_MODE_MANAGER = mUserSettingDeviceConfigMediator.getBoolean( + KEY_USE_MODE_MANAGER, mDefaultUseModeManager); + } + void dump(PrintWriter pw) { pw.println(" Settings:"); @@ -2490,9 +2485,10 @@ public class DeviceIdleController extends SystemService return mConnectivityManager; } - Constants getConstants(DeviceIdleController controller) { + Constants getConstants(DeviceIdleController controller, Handler handler, + ContentResolver resolver) { if (mConstants == null) { - mConstants = controller.new Constants(); + mConstants = controller.new Constants(handler, resolver); } return mConstants; } @@ -2650,7 +2646,7 @@ public class DeviceIdleController extends SystemService } } - mConstants = mInjector.getConstants(this); + mConstants = mInjector.getConstants(this, mHandler, getContext().getContentResolver()); readConfigFileLocked(); updateWhitelistAppIdsLocked(); diff --git a/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java index d2150b80761f..8381d1a322e0 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java @@ -109,7 +109,6 @@ import android.annotation.Nullable; import android.content.ContentResolver; import android.provider.DeviceConfig; import android.util.IndentingPrintWriter; -import android.util.KeyValueListParser; import android.util.Slog; import android.util.SparseArray; @@ -154,7 +153,6 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { private long mMinSatiatedConsumptionLimit; private long mMaxSatiatedConsumptionLimit; - private final KeyValueListParser mParser = new KeyValueListParser(','); private final Injector mInjector; private final SparseArray<Action> mActions = new SparseArray<>(); @@ -241,35 +239,36 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { mRewards.clear(); try { - mParser.setString(policyValuesString); + mUserSettingDeviceConfigMediator.setSettingsString(policyValuesString); + mUserSettingDeviceConfigMediator.setDeviceConfigProperties(properties); } catch (IllegalArgumentException e) { Slog.e(TAG, "Global setting key incorrect: ", e); } - mMinSatiatedBalanceOther = getConstantAsCake(mParser, properties, + mMinSatiatedBalanceOther = getConstantAsCake( KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP, DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP_CAKES); - mMinSatiatedBalanceHeadlessSystemApp = getConstantAsCake(mParser, properties, + mMinSatiatedBalanceHeadlessSystemApp = getConstantAsCake( KEY_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP, DEFAULT_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP_CAKES, mMinSatiatedBalanceOther); - mMinSatiatedBalanceExempted = getConstantAsCake(mParser, properties, + mMinSatiatedBalanceExempted = getConstantAsCake( KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED, DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED_CAKES, mMinSatiatedBalanceHeadlessSystemApp); - mMaxSatiatedBalance = getConstantAsCake(mParser, properties, + mMaxSatiatedBalance = getConstantAsCake( KEY_AM_MAX_SATIATED_BALANCE, DEFAULT_AM_MAX_SATIATED_BALANCE_CAKES, Math.max(arcToCake(1), mMinSatiatedBalanceExempted)); - mMinSatiatedConsumptionLimit = getConstantAsCake(mParser, properties, + mMinSatiatedConsumptionLimit = getConstantAsCake( KEY_AM_MIN_CONSUMPTION_LIMIT, DEFAULT_AM_MIN_CONSUMPTION_LIMIT_CAKES, arcToCake(1)); - mInitialSatiatedConsumptionLimit = getConstantAsCake(mParser, properties, + mInitialSatiatedConsumptionLimit = getConstantAsCake( KEY_AM_INITIAL_CONSUMPTION_LIMIT, DEFAULT_AM_INITIAL_CONSUMPTION_LIMIT_CAKES, mMinSatiatedConsumptionLimit); - mMaxSatiatedConsumptionLimit = getConstantAsCake(mParser, properties, + mMaxSatiatedConsumptionLimit = getConstantAsCake( KEY_AM_MAX_CONSUMPTION_LIMIT, DEFAULT_AM_MAX_CONSUMPTION_LIMIT_CAKES, mInitialSatiatedConsumptionLimit); - final long exactAllowWhileIdleWakeupBasePrice = getConstantAsCake(mParser, properties, + final long exactAllowWhileIdleWakeupBasePrice = getConstantAsCake( KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE, DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE_CAKES); @@ -279,49 +278,49 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { // run out of credits, and not when the system has run out of stock. mActions.put(ACTION_ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE, new Action(ACTION_ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP, DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP_CAKES), exactAllowWhileIdleWakeupBasePrice, /* respectsStockLimit */ false)); mActions.put(ACTION_ALARM_WAKEUP_EXACT, new Action(ACTION_ALARM_WAKEUP_EXACT, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_ACTION_ALARM_EXACT_WAKEUP_CTP, DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE, DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES), /* respectsStockLimit */ false)); final long inexactAllowWhileIdleWakeupBasePrice = - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE, DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE_CAKES); mActions.put(ACTION_ALARM_WAKEUP_INEXACT_ALLOW_WHILE_IDLE, new Action(ACTION_ALARM_WAKEUP_INEXACT_ALLOW_WHILE_IDLE, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP, DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP_CAKES), inexactAllowWhileIdleWakeupBasePrice, /* respectsStockLimit */ false)); mActions.put(ACTION_ALARM_WAKEUP_INEXACT, new Action(ACTION_ALARM_WAKEUP_INEXACT, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP, DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE, DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE_CAKES), /* respectsStockLimit */ false)); - final long exactAllowWhileIdleNonWakeupBasePrice = getConstantAsCake(mParser, properties, + final long exactAllowWhileIdleNonWakeupBasePrice = getConstantAsCake( KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_BASE_PRICE, DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE_CAKES); mActions.put(ACTION_ALARM_NONWAKEUP_EXACT_ALLOW_WHILE_IDLE, new Action(ACTION_ALARM_NONWAKEUP_EXACT_ALLOW_WHILE_IDLE, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP, DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP_CAKES), exactAllowWhileIdleNonWakeupBasePrice, @@ -329,18 +328,18 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { mActions.put(ACTION_ALARM_NONWAKEUP_EXACT, new Action(ACTION_ALARM_NONWAKEUP_EXACT, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP, DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE, DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE_CAKES), /* respectsStockLimit */ false)); - final long inexactAllowWhileIdleNonWakeupBasePrice = getConstantAsCake(mParser, properties, + final long inexactAllowWhileIdleNonWakeupBasePrice = getConstantAsCake( KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE, DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE_CAKES); - final long inexactAllowWhileIdleNonWakeupCtp = getConstantAsCake(mParser, properties, + final long inexactAllowWhileIdleNonWakeupCtp = getConstantAsCake( KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP, DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP_CAKES); mActions.put(ACTION_ALARM_NONWAKEUP_INEXACT_ALLOW_WHILE_IDLE, @@ -350,72 +349,72 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { mActions.put(ACTION_ALARM_NONWAKEUP_INEXACT, new Action(ACTION_ALARM_NONWAKEUP_INEXACT, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP, DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE, DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE_CAKES))); mActions.put(ACTION_ALARM_CLOCK, new Action(ACTION_ALARM_CLOCK, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_ACTION_ALARM_ALARMCLOCK_CTP, DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE, DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE_CAKES), /* respectsStockLimit */ false)); mRewards.put(REWARD_TOP_ACTIVITY, new Reward(REWARD_TOP_ACTIVITY, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_TOP_ACTIVITY_INSTANT, DEFAULT_AM_REWARD_TOP_ACTIVITY_INSTANT_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_TOP_ACTIVITY_ONGOING, DEFAULT_AM_REWARD_TOP_ACTIVITY_ONGOING_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_TOP_ACTIVITY_MAX, DEFAULT_AM_REWARD_TOP_ACTIVITY_MAX_CAKES))); mRewards.put(REWARD_NOTIFICATION_SEEN, new Reward(REWARD_NOTIFICATION_SEEN, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_NOTIFICATION_SEEN_INSTANT, DEFAULT_AM_REWARD_NOTIFICATION_SEEN_INSTANT_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_NOTIFICATION_SEEN_ONGOING, DEFAULT_AM_REWARD_NOTIFICATION_SEEN_ONGOING_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_NOTIFICATION_SEEN_MAX, DEFAULT_AM_REWARD_NOTIFICATION_SEEN_MAX_CAKES))); mRewards.put(REWARD_NOTIFICATION_INTERACTION, new Reward(REWARD_NOTIFICATION_INTERACTION, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT, DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING, DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_NOTIFICATION_INTERACTION_MAX, DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_MAX_CAKES))); mRewards.put(REWARD_WIDGET_INTERACTION, new Reward(REWARD_WIDGET_INTERACTION, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_WIDGET_INTERACTION_INSTANT, DEFAULT_AM_REWARD_WIDGET_INTERACTION_INSTANT_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_WIDGET_INTERACTION_ONGOING, DEFAULT_AM_REWARD_WIDGET_INTERACTION_ONGOING_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_WIDGET_INTERACTION_MAX, DEFAULT_AM_REWARD_WIDGET_INTERACTION_MAX_CAKES))); mRewards.put(REWARD_OTHER_USER_INTERACTION, new Reward(REWARD_OTHER_USER_INTERACTION, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_OTHER_USER_INTERACTION_INSTANT, DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_INSTANT_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_OTHER_USER_INTERACTION_ONGOING, DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_AM_REWARD_OTHER_USER_INTERACTION_MAX, DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_MAX_CAKES))); } diff --git a/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java index a4043dd8ba78..61096b9fa179 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java @@ -33,9 +33,9 @@ import android.content.ContentResolver; import android.provider.DeviceConfig; import android.provider.Settings; import android.util.IndentingPrintWriter; -import android.util.KeyValueListParser; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.utils.UserSettingDeviceConfigMediator; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -197,10 +197,17 @@ public abstract class EconomicPolicy { } protected final InternalResourceService mIrs; + protected final UserSettingDeviceConfigMediator mUserSettingDeviceConfigMediator; private static final Modifier[] COST_MODIFIER_BY_INDEX = new Modifier[NUM_COST_MODIFIERS]; EconomicPolicy(@NonNull InternalResourceService irs) { mIrs = irs; + // Don't cross the streams! Mixing Settings/local user config changes with DeviceConfig + // config can cause issues since the scales may be different, so use one or the other. + // If user settings exist, then just stick with the Settings constants, even if there + // are invalid values. + mUserSettingDeviceConfigMediator = + new UserSettingDeviceConfigMediator.SettingsOverridesAllMediator(','); for (int mId : getCostModifiers()) { initModifier(mId, irs); } @@ -464,28 +471,14 @@ public abstract class EconomicPolicy { return "UNKNOWN_REWARD:" + Integer.toHexString(eventId); } - protected long getConstantAsCake(@NonNull KeyValueListParser parser, - @Nullable DeviceConfig.Properties properties, String key, long defaultValCake) { - return getConstantAsCake(parser, properties, key, defaultValCake, 0); + protected long getConstantAsCake(String key, long defaultValCake) { + return getConstantAsCake(key, defaultValCake, 0); } - protected long getConstantAsCake(@NonNull KeyValueListParser parser, - @Nullable DeviceConfig.Properties properties, String key, long defaultValCake, - long minValCake) { - // Don't cross the streams! Mixing Settings/local user config changes with DeviceConfig - // config can cause issues since the scales may be different, so use one or the other. - if (parser.size() > 0) { - // User settings take precedence. Just stick with the Settings constants, even if there - // are invalid values. It's not worth the time to evaluate all the key/value pairs to - // make sure there are valid ones before deciding. - return Math.max(minValCake, - parseCreditValue(parser.getString(key, null), defaultValCake)); - } - if (properties != null) { - return Math.max(minValCake, - parseCreditValue(properties.getString(key, null), defaultValCake)); - } - return Math.max(minValCake, defaultValCake); + protected long getConstantAsCake(String key, long defaultValCake, long minValCake) { + return Math.max(minValCake, + parseCreditValue( + mUserSettingDeviceConfigMediator.getString(key, null), defaultValCake)); } @VisibleForTesting diff --git a/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java index 91a291fe20db..69e57365b6e0 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java @@ -127,7 +127,6 @@ import android.annotation.Nullable; import android.content.ContentResolver; import android.provider.DeviceConfig; import android.util.IndentingPrintWriter; -import android.util.KeyValueListParser; import android.util.Slog; import android.util.SparseArray; @@ -168,7 +167,6 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { private long mMinSatiatedConsumptionLimit; private long mMaxSatiatedConsumptionLimit; - private final KeyValueListParser mParser = new KeyValueListParser(','); private final Injector mInjector; private final SparseArray<Action> mActions = new SparseArray<>(); @@ -274,176 +272,177 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { mRewards.clear(); try { - mParser.setString(policyValuesString); + mUserSettingDeviceConfigMediator.setSettingsString(policyValuesString); + mUserSettingDeviceConfigMediator.setDeviceConfigProperties(properties); } catch (IllegalArgumentException e) { Slog.e(TAG, "Global setting key incorrect: ", e); } - mMinSatiatedBalanceOther = getConstantAsCake(mParser, properties, + mMinSatiatedBalanceOther = getConstantAsCake( KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP, DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP_CAKES); - mMinSatiatedBalanceHeadlessSystemApp = getConstantAsCake(mParser, properties, + mMinSatiatedBalanceHeadlessSystemApp = getConstantAsCake( KEY_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP, DEFAULT_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP_CAKES, mMinSatiatedBalanceOther); - mMinSatiatedBalanceExempted = getConstantAsCake(mParser, properties, + mMinSatiatedBalanceExempted = getConstantAsCake( KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED, DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES, mMinSatiatedBalanceHeadlessSystemApp); - mMinSatiatedBalanceIncrementalAppUpdater = getConstantAsCake(mParser, properties, + mMinSatiatedBalanceIncrementalAppUpdater = getConstantAsCake( KEY_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER, DEFAULT_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER_CAKES); - mMaxSatiatedBalance = getConstantAsCake(mParser, properties, + mMaxSatiatedBalance = getConstantAsCake( KEY_JS_MAX_SATIATED_BALANCE, DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES, Math.max(arcToCake(1), mMinSatiatedBalanceExempted)); - mMinSatiatedConsumptionLimit = getConstantAsCake(mParser, properties, + mMinSatiatedConsumptionLimit = getConstantAsCake( KEY_JS_MIN_CONSUMPTION_LIMIT, DEFAULT_JS_MIN_CONSUMPTION_LIMIT_CAKES, arcToCake(1)); - mInitialSatiatedConsumptionLimit = getConstantAsCake(mParser, properties, + mInitialSatiatedConsumptionLimit = getConstantAsCake( KEY_JS_INITIAL_CONSUMPTION_LIMIT, DEFAULT_JS_INITIAL_CONSUMPTION_LIMIT_CAKES, mMinSatiatedConsumptionLimit); - mMaxSatiatedConsumptionLimit = getConstantAsCake(mParser, properties, + mMaxSatiatedConsumptionLimit = getConstantAsCake( KEY_JS_MAX_CONSUMPTION_LIMIT, DEFAULT_JS_MAX_CONSUMPTION_LIMIT_CAKES, mInitialSatiatedConsumptionLimit); mActions.put(ACTION_JOB_MAX_START, new Action(ACTION_JOB_MAX_START, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_MAX_START_CTP, DEFAULT_JS_ACTION_JOB_MAX_START_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_MAX_START_BASE_PRICE, DEFAULT_JS_ACTION_JOB_MAX_START_BASE_PRICE_CAKES))); mActions.put(ACTION_JOB_MAX_RUNNING, new Action(ACTION_JOB_MAX_RUNNING, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_MAX_RUNNING_CTP, DEFAULT_JS_ACTION_JOB_MAX_RUNNING_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE, DEFAULT_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE_CAKES))); mActions.put(ACTION_JOB_HIGH_START, new Action(ACTION_JOB_HIGH_START, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_HIGH_START_CTP, DEFAULT_JS_ACTION_JOB_HIGH_START_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_HIGH_START_BASE_PRICE, DEFAULT_JS_ACTION_JOB_HIGH_START_BASE_PRICE_CAKES))); mActions.put(ACTION_JOB_HIGH_RUNNING, new Action(ACTION_JOB_HIGH_RUNNING, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_HIGH_RUNNING_CTP, DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE, DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE_CAKES))); mActions.put(ACTION_JOB_DEFAULT_START, new Action(ACTION_JOB_DEFAULT_START, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_DEFAULT_START_CTP, DEFAULT_JS_ACTION_JOB_DEFAULT_START_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE, DEFAULT_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE_CAKES))); mActions.put(ACTION_JOB_DEFAULT_RUNNING, new Action(ACTION_JOB_DEFAULT_RUNNING, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_DEFAULT_RUNNING_CTP, DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE, DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE_CAKES))); mActions.put(ACTION_JOB_LOW_START, new Action(ACTION_JOB_LOW_START, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_LOW_START_CTP, DEFAULT_JS_ACTION_JOB_LOW_START_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_LOW_START_BASE_PRICE, DEFAULT_JS_ACTION_JOB_LOW_START_BASE_PRICE_CAKES))); mActions.put(ACTION_JOB_LOW_RUNNING, new Action(ACTION_JOB_LOW_RUNNING, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_LOW_RUNNING_CTP, DEFAULT_JS_ACTION_JOB_LOW_RUNNING_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE, DEFAULT_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE_CAKES))); mActions.put(ACTION_JOB_MIN_START, new Action(ACTION_JOB_MIN_START, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_MIN_START_CTP, DEFAULT_JS_ACTION_JOB_MIN_START_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_MIN_START_BASE_PRICE, DEFAULT_JS_ACTION_JOB_MIN_START_BASE_PRICE_CAKES))); mActions.put(ACTION_JOB_MIN_RUNNING, new Action(ACTION_JOB_MIN_RUNNING, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_MIN_RUNNING_CTP, DEFAULT_JS_ACTION_JOB_MIN_RUNNING_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE, DEFAULT_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE_CAKES))); mActions.put(ACTION_JOB_TIMEOUT, new Action(ACTION_JOB_TIMEOUT, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP, DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE, DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE_CAKES))); mRewards.put(REWARD_TOP_ACTIVITY, new Reward(REWARD_TOP_ACTIVITY, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_TOP_ACTIVITY_INSTANT, DEFAULT_JS_REWARD_TOP_ACTIVITY_INSTANT_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_TOP_ACTIVITY_ONGOING, DEFAULT_JS_REWARD_TOP_ACTIVITY_ONGOING_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_TOP_ACTIVITY_MAX, DEFAULT_JS_REWARD_TOP_ACTIVITY_MAX_CAKES))); mRewards.put(REWARD_NOTIFICATION_SEEN, new Reward(REWARD_NOTIFICATION_SEEN, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_NOTIFICATION_SEEN_INSTANT, DEFAULT_JS_REWARD_NOTIFICATION_SEEN_INSTANT_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_NOTIFICATION_SEEN_ONGOING, DEFAULT_JS_REWARD_NOTIFICATION_SEEN_ONGOING_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_NOTIFICATION_SEEN_MAX, DEFAULT_JS_REWARD_NOTIFICATION_SEEN_MAX_CAKES))); mRewards.put(REWARD_NOTIFICATION_INTERACTION, new Reward(REWARD_NOTIFICATION_INTERACTION, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT, DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING, DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_NOTIFICATION_INTERACTION_MAX, DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_MAX_CAKES))); mRewards.put(REWARD_WIDGET_INTERACTION, new Reward(REWARD_WIDGET_INTERACTION, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_WIDGET_INTERACTION_INSTANT, DEFAULT_JS_REWARD_WIDGET_INTERACTION_INSTANT_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_WIDGET_INTERACTION_ONGOING, DEFAULT_JS_REWARD_WIDGET_INTERACTION_ONGOING_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_WIDGET_INTERACTION_MAX, DEFAULT_JS_REWARD_WIDGET_INTERACTION_MAX_CAKES))); mRewards.put(REWARD_OTHER_USER_INTERACTION, new Reward(REWARD_OTHER_USER_INTERACTION, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_OTHER_USER_INTERACTION_INSTANT, DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_INSTANT_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_OTHER_USER_INTERACTION_ONGOING, DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_OTHER_USER_INTERACTION_MAX, DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_MAX_CAKES))); mRewards.put(REWARD_APP_INSTALL, new Reward(REWARD_APP_INSTALL, - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_APP_INSTALL_INSTANT, DEFAULT_JS_REWARD_APP_INSTALL_INSTANT_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_APP_INSTALL_ONGOING, DEFAULT_JS_REWARD_APP_INSTALL_ONGOING_CAKES), - getConstantAsCake(mParser, properties, + getConstantAsCake( KEY_JS_REWARD_APP_INSTALL_MAX, DEFAULT_JS_REWARD_APP_INSTALL_MAX_CAKES))); } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 33c15d775ff1..6bb3a53016dc 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -14943,6 +14943,38 @@ public final class Settings { public static final String APP_OPS_CONSTANTS = "app_ops_constants"; /** + * Device Idle (Doze) specific settings. + * This is encoded as a key=value list, separated by commas. Ex: + * + * "inactive_to=60000,sensing_to=400000" + * + * The following keys are supported: + * + * <pre> + * inactive_to (long) + * sensing_to (long) + * motion_inactive_to (long) + * idle_after_inactive_to (long) + * idle_pending_to (long) + * max_idle_pending_to (long) + * idle_pending_factor (float) + * quick_doze_delay_to (long) + * idle_to (long) + * max_idle_to (long) + * idle_factor (float) + * min_time_to_alarm (long) + * max_temp_app_whitelist_duration (long) + * notification_whitelist_duration (long) + * </pre> + * + * <p> + * Type: string + * @hide + * @see com.android.server.DeviceIdleController.Constants + */ + public static final String DEVICE_IDLE_CONSTANTS = "device_idle_constants"; + + /** * Battery Saver specific settings * This is encoded as a key=value list, separated by commas. Ex: * diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index f1b53edbb1cd..4052336340cf 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -235,6 +235,7 @@ public class SettingsBackupTest { Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, Settings.Global.DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH, Settings.Global.DEVICE_DEMO_MODE, + Settings.Global.DEVICE_IDLE_CONSTANTS, Settings.Global.DISABLE_WINDOW_BLURS, Settings.Global.BATTERY_SAVER_CONSTANTS, Settings.Global.BATTERY_TIP_CONSTANTS, diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java index e3f36385ef6c..5d9085144334 100644 --- a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java +++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java @@ -32,7 +32,6 @@ import android.provider.Settings; import android.text.TextUtils; import android.util.ArrayMap; import android.util.IndentingPrintWriter; -import android.util.KeyValueListParser; import android.util.Slog; import android.view.accessibility.AccessibilityManager; @@ -41,6 +40,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.BackgroundThread; import com.android.internal.util.ConcurrentUtils; +import com.android.server.utils.UserSettingDeviceConfigMediator; import java.io.PrintWriter; import java.lang.annotation.Retention; @@ -809,12 +809,13 @@ public class BatterySaverPolicy extends ContentObserver implements private static Policy fromSettings(String settings, String deviceSpecificSettings, DeviceConfig.Properties properties, String configSuffix, Policy defaultPolicy) { - final KeyValueListParser parser = new KeyValueListParser(','); + final UserSettingDeviceConfigMediator userSettingDeviceConfigMediator = + new UserSettingDeviceConfigMediator.SettingsOverridesIndividualMediator(','); configSuffix = TextUtils.emptyIfNull(configSuffix); // Device-specific parameters. try { - parser.setString(deviceSpecificSettings == null ? "" : deviceSpecificSettings); + userSettingDeviceConfigMediator.setSettingsString(deviceSpecificSettings); } catch (IllegalArgumentException e) { Slog.wtf(TAG, "Bad device specific battery saver constants: " + deviceSpecificSettings); @@ -822,68 +823,58 @@ public class BatterySaverPolicy extends ContentObserver implements // Non-device-specific parameters. try { - parser.setString(settings == null ? "" : settings); + userSettingDeviceConfigMediator.setSettingsString(settings); + userSettingDeviceConfigMediator.setDeviceConfigProperties(properties); } catch (IllegalArgumentException e) { Slog.wtf(TAG, "Bad battery saver constants: " + settings); } // The Settings value overrides everything, since that will be set by the user. // The DeviceConfig value takes second place, with the default as the last choice. - final float adjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR, - properties.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR + configSuffix, - defaultPolicy.adjustBrightnessFactor)); - final boolean advertiseIsEnabled = parser.getBoolean(KEY_ADVERTISE_IS_ENABLED, - properties.getBoolean(KEY_ADVERTISE_IS_ENABLED + configSuffix, - defaultPolicy.advertiseIsEnabled)); - final boolean deferFullBackup = parser.getBoolean(KEY_DEFER_FULL_BACKUP, - properties.getBoolean(KEY_DEFER_FULL_BACKUP + configSuffix, - defaultPolicy.deferFullBackup)); - final boolean deferKeyValueBackup = parser.getBoolean(KEY_DEFER_KEYVALUE_BACKUP, - properties.getBoolean(KEY_DEFER_KEYVALUE_BACKUP + configSuffix, - defaultPolicy.deferKeyValueBackup)); - final boolean disableAnimation = parser.getBoolean(KEY_DISABLE_ANIMATION, - properties.getBoolean(KEY_DISABLE_ANIMATION + configSuffix, - defaultPolicy.disableAnimation)); - final boolean disableAod = parser.getBoolean(KEY_DISABLE_AOD, - properties.getBoolean(KEY_DISABLE_AOD + configSuffix, - defaultPolicy.disableAod)); - final boolean disableLaunchBoost = parser.getBoolean(KEY_DISABLE_LAUNCH_BOOST, - properties.getBoolean(KEY_DISABLE_LAUNCH_BOOST + configSuffix, - defaultPolicy.disableLaunchBoost)); - final boolean disableOptionalSensors = parser.getBoolean(KEY_DISABLE_OPTIONAL_SENSORS, - properties.getBoolean(KEY_DISABLE_OPTIONAL_SENSORS + configSuffix, - defaultPolicy.disableOptionalSensors)); - final boolean disableVibrationConfig = parser.getBoolean(KEY_DISABLE_VIBRATION, - properties.getBoolean(KEY_DISABLE_VIBRATION + configSuffix, - defaultPolicy.disableVibration)); - final boolean enableBrightnessAdjustment = parser.getBoolean( - KEY_ENABLE_BRIGHTNESS_ADJUSTMENT, - properties.getBoolean(KEY_ENABLE_BRIGHTNESS_ADJUSTMENT + configSuffix, - defaultPolicy.enableAdjustBrightness)); - final boolean enableDataSaver = parser.getBoolean(KEY_ENABLE_DATASAVER, - properties.getBoolean(KEY_ENABLE_DATASAVER + configSuffix, - defaultPolicy.enableDataSaver)); - final boolean enableFirewall = parser.getBoolean(KEY_ENABLE_FIREWALL, - properties.getBoolean(KEY_ENABLE_FIREWALL + configSuffix, - defaultPolicy.enableFirewall)); - final boolean enableNightMode = parser.getBoolean(KEY_ENABLE_NIGHT_MODE, - properties.getBoolean(KEY_ENABLE_NIGHT_MODE + configSuffix, - defaultPolicy.enableNightMode)); - final boolean enableQuickDoze = parser.getBoolean(KEY_ENABLE_QUICK_DOZE, - properties.getBoolean(KEY_ENABLE_QUICK_DOZE + configSuffix, - defaultPolicy.enableQuickDoze)); - final boolean forceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY, - properties.getBoolean(KEY_FORCE_ALL_APPS_STANDBY + configSuffix, - defaultPolicy.forceAllAppsStandby)); - final boolean forceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK, - properties.getBoolean(KEY_FORCE_BACKGROUND_CHECK + configSuffix, - defaultPolicy.forceBackgroundCheck)); - final int locationMode = parser.getInt(KEY_LOCATION_MODE, - properties.getInt(KEY_LOCATION_MODE + configSuffix, - defaultPolicy.locationMode)); - final int soundTriggerMode = parser.getInt(KEY_SOUNDTRIGGER_MODE, - properties.getInt(KEY_SOUNDTRIGGER_MODE + configSuffix, - defaultPolicy.soundTriggerMode)); + final float adjustBrightnessFactor = userSettingDeviceConfigMediator.getFloat( + KEY_ADJUST_BRIGHTNESS_FACTOR + configSuffix, + defaultPolicy.adjustBrightnessFactor); + final boolean advertiseIsEnabled = userSettingDeviceConfigMediator.getBoolean( + KEY_ADVERTISE_IS_ENABLED + configSuffix, + defaultPolicy.advertiseIsEnabled); + final boolean deferFullBackup = userSettingDeviceConfigMediator.getBoolean( + KEY_DEFER_FULL_BACKUP + configSuffix, defaultPolicy.deferFullBackup); + final boolean deferKeyValueBackup = userSettingDeviceConfigMediator.getBoolean( + KEY_DEFER_KEYVALUE_BACKUP + configSuffix, + defaultPolicy.deferKeyValueBackup); + final boolean disableAnimation = userSettingDeviceConfigMediator.getBoolean( + KEY_DISABLE_ANIMATION + configSuffix, defaultPolicy.disableAnimation); + final boolean disableAod = userSettingDeviceConfigMediator.getBoolean( + KEY_DISABLE_AOD + configSuffix, defaultPolicy.disableAod); + final boolean disableLaunchBoost = userSettingDeviceConfigMediator.getBoolean( + KEY_DISABLE_LAUNCH_BOOST + configSuffix, + defaultPolicy.disableLaunchBoost); + final boolean disableOptionalSensors = userSettingDeviceConfigMediator.getBoolean( + KEY_DISABLE_OPTIONAL_SENSORS + configSuffix, + defaultPolicy.disableOptionalSensors); + final boolean disableVibrationConfig = userSettingDeviceConfigMediator.getBoolean( + KEY_DISABLE_VIBRATION + configSuffix, defaultPolicy.disableVibration); + final boolean enableBrightnessAdjustment = userSettingDeviceConfigMediator.getBoolean( + KEY_ENABLE_BRIGHTNESS_ADJUSTMENT + configSuffix, + defaultPolicy.enableAdjustBrightness); + final boolean enableDataSaver = userSettingDeviceConfigMediator.getBoolean( + KEY_ENABLE_DATASAVER + configSuffix, defaultPolicy.enableDataSaver); + final boolean enableFirewall = userSettingDeviceConfigMediator.getBoolean( + KEY_ENABLE_FIREWALL + configSuffix, defaultPolicy.enableFirewall); + final boolean enableNightMode = userSettingDeviceConfigMediator.getBoolean( + KEY_ENABLE_NIGHT_MODE + configSuffix, defaultPolicy.enableNightMode); + final boolean enableQuickDoze = userSettingDeviceConfigMediator.getBoolean( + KEY_ENABLE_QUICK_DOZE + configSuffix, defaultPolicy.enableQuickDoze); + final boolean forceAllAppsStandby = userSettingDeviceConfigMediator.getBoolean( + KEY_FORCE_ALL_APPS_STANDBY + configSuffix, + defaultPolicy.forceAllAppsStandby); + final boolean forceBackgroundCheck = userSettingDeviceConfigMediator.getBoolean( + KEY_FORCE_BACKGROUND_CHECK + configSuffix, + defaultPolicy.forceBackgroundCheck); + final int locationMode = userSettingDeviceConfigMediator.getInt( + KEY_LOCATION_MODE + configSuffix, defaultPolicy.locationMode); + final int soundTriggerMode = userSettingDeviceConfigMediator.getInt( + KEY_SOUNDTRIGGER_MODE + configSuffix, defaultPolicy.soundTriggerMode); return new Policy( adjustBrightnessFactor, advertiseIsEnabled, diff --git a/services/core/java/com/android/server/utils/UserSettingDeviceConfigMediator.java b/services/core/java/com/android/server/utils/UserSettingDeviceConfigMediator.java new file mode 100644 index 000000000000..e5423496fb0e --- /dev/null +++ b/services/core/java/com/android/server/utils/UserSettingDeviceConfigMediator.java @@ -0,0 +1,194 @@ +/* + * 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.utils; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.provider.DeviceConfig; +import android.util.KeyValueListParser; + +/** + * Helper class to mediate the value to use when a constant exists in both a key=value pair Settings + * constant (that can be parsed by {@link KeyValueListParser}) + * and the {@link DeviceConfig} properties. + */ +public abstract class UserSettingDeviceConfigMediator { + private static final String TAG = UserSettingDeviceConfigMediator.class.getSimpleName(); + + @Nullable + protected DeviceConfig.Properties mProperties; + @NonNull + protected final KeyValueListParser mSettingsParser; + + /** + * @param keyValueListDelimiter The delimiter passed into the {@link KeyValueListParser}. + */ + protected UserSettingDeviceConfigMediator(char keyValueListDelimiter) { + mSettingsParser = new KeyValueListParser(keyValueListDelimiter); + } + + /** + * Sets the key=value list string to read from. Setting {@code null} will clear any previously + * set string. + */ + public void setSettingsString(@Nullable String settings) { + mSettingsParser.setString(settings); + } + + /** + * Sets the DeviceConfig Properties to read from. Setting {@code null} will clear any previously + * set properties. + */ + public void setDeviceConfigProperties(@Nullable DeviceConfig.Properties properties) { + mProperties = properties; + } + + /** + * Get the value for key as a boolean. + * + * @param key The key to lookup. + * @param defaultValue The value to return if the key was not found, or not properly defined. + */ + public abstract boolean getBoolean(@NonNull String key, boolean defaultValue); + + /** + * Get the value for key as a float. + * + * @param key The key to lookup. + * @param defaultValue The value to return if the key was not found, or not properly defined. + */ + public abstract float getFloat(@NonNull String key, float defaultValue); + + /** + * Get the value for key as an int. + * + * @param key The key to lookup. + * @param defaultValue The value to return if the key was not found, or not properly defined. + */ + public abstract int getInt(@NonNull String key, int defaultValue); + + /** + * Get the value for key as a long. + * + * @param key The key to lookup. + * @param defaultValue The value to return if the key was not found, or not properly defined. + */ + public abstract long getLong(@NonNull String key, long defaultValue); + + /** + * Get the value for key as a String. + * + * @param key The key to lookup. + * @param defaultValue The value to return if the key was not found, or not properly defined. + */ + public abstract String getString(@NonNull String key, @Nullable String defaultValue); + + /** + * A mediator in which the existence of a single settings key-value pair will override usage + * of DeviceConfig properties. That is, if the Settings constant has any values set, + * then everything in the DeviceConfig namespace will be ignored. + */ + public static class SettingsOverridesAllMediator extends UserSettingDeviceConfigMediator { + public SettingsOverridesAllMediator(char keyValueListDelimiter) { + super(keyValueListDelimiter); + } + + @Override + public boolean getBoolean(@NonNull String key, boolean defaultValue) { + if (mSettingsParser.size() == 0) { + return mProperties == null + ? defaultValue : mProperties.getBoolean(key, defaultValue); + } + return mSettingsParser.getBoolean(key, defaultValue); + } + + @Override + public float getFloat(@NonNull String key, float defaultValue) { + if (mSettingsParser.size() == 0) { + return mProperties == null ? defaultValue : mProperties.getFloat(key, defaultValue); + } + return mSettingsParser.getFloat(key, defaultValue); + } + + @Override + public int getInt(@NonNull String key, int defaultValue) { + if (mSettingsParser.size() == 0) { + return mProperties == null ? defaultValue : mProperties.getInt(key, defaultValue); + } + return mSettingsParser.getInt(key, defaultValue); + } + + @Override + public long getLong(@NonNull String key, long defaultValue) { + if (mSettingsParser.size() == 0) { + return mProperties == null ? defaultValue : mProperties.getLong(key, defaultValue); + } + return mSettingsParser.getLong(key, defaultValue); + } + + @Override + public String getString(@NonNull String key, @Nullable String defaultValue) { + if (mSettingsParser.size() == 0) { + return mProperties == null + ? defaultValue : mProperties.getString(key, defaultValue); + } + return mSettingsParser.getString(key, defaultValue); + } + } + + /** + * A mediator in which only individual keys in the DeviceConfig namespace will be overridden + * by the same key in the Settings constant. If the Settings constant does not have a specific + * key set, then the DeviceConfig value will be used instead. + */ + public static class SettingsOverridesIndividualMediator + extends UserSettingDeviceConfigMediator { + public SettingsOverridesIndividualMediator(char keyValueListDelimiter) { + super(keyValueListDelimiter); + } + + @Override + public boolean getBoolean(@NonNull String key, boolean defaultValue) { + return mSettingsParser.getBoolean(key, + mProperties == null ? defaultValue : mProperties.getBoolean(key, defaultValue)); + } + + @Override + public float getFloat(@NonNull String key, float defaultValue) { + return mSettingsParser.getFloat(key, + mProperties == null ? defaultValue : mProperties.getFloat(key, defaultValue)); + } + + @Override + public int getInt(@NonNull String key, int defaultValue) { + return mSettingsParser.getInt(key, + mProperties == null ? defaultValue : mProperties.getInt(key, defaultValue)); + } + + @Override + public long getLong(@NonNull String key, long defaultValue) { + return mSettingsParser.getLong(key, + mProperties == null ? defaultValue : mProperties.getLong(key, defaultValue)); + } + + @Override + public String getString(@NonNull String key, @Nullable String defaultValue) { + return mSettingsParser.getString(key, + mProperties == null ? defaultValue : mProperties.getString(key, defaultValue)); + } + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java index be29163e7677..1a3a6a388392 100644 --- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java @@ -46,6 +46,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; @@ -61,6 +62,7 @@ import static org.mockito.Mockito.verify; import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.app.IActivityManager; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.hardware.Sensor; @@ -128,6 +130,8 @@ public class DeviceIdleControllerTest { @Mock private ConnectivityManager mConnectivityManager; @Mock + private ContentResolver mContentResolver; + @Mock private IActivityManager mIActivityManager; @Mock private LocationManager mLocationManager; @@ -332,7 +336,7 @@ public class DeviceIdleControllerTest { anyString(), any(Executor.class), any(DeviceConfig.OnPropertiesChangedListener.class))); doAnswer((Answer<DeviceConfig.Properties>) invocationOnMock - -> mock(DeviceConfig.Properties.class)) + -> new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_DEVICE_IDLE).build()) .when(() -> DeviceConfig.getProperties( anyString(), ArgumentMatchers.<String>any())); when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(mWakeLock); @@ -347,6 +351,7 @@ public class DeviceIdleControllerTest { mAppStateTracker = new AppStateTrackerForTest(getContext(), Looper.getMainLooper()); mAnyMotionDetector = new AnyMotionDetectorForTest(); mInjector = new InjectorForTest(getContext()); + doNothing().when(mContentResolver).registerContentObserver(any(), anyBoolean(), any()); doReturn(mWearModeManagerInternal) .when(() -> LocalServices.getService(WearModeManagerInternal.class)); @@ -366,7 +371,8 @@ public class DeviceIdleControllerTest { mDeviceIdleController.setLightEnabledForTest(true); // Get the same Constants object that mDeviceIdleController got. - mConstants = mInjector.getConstants(mDeviceIdleController); + mConstants = mInjector.getConstants(mDeviceIdleController, + mInjector.getHandler(mDeviceIdleController), mContentResolver); final ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor = ArgumentCaptor.forClass(TelephonyCallback.class); diff --git a/services/tests/servicestests/src/com/android/server/utils/UserSettingDeviceConfigMediatorTest.java b/services/tests/servicestests/src/com/android/server/utils/UserSettingDeviceConfigMediatorTest.java new file mode 100644 index 000000000000..377e4c3d6810 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/utils/UserSettingDeviceConfigMediatorTest.java @@ -0,0 +1,235 @@ +/* + * 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.utils; + +import static org.junit.Assert.assertEquals; + +import android.provider.DeviceConfig; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Unit tests for {@link UserSettingDeviceConfigMediator} + */ +@RunWith(AndroidJUnit4.class) +public class UserSettingDeviceConfigMediatorTest { + @Test + public void testDeviceConfigOnly() { + UserSettingDeviceConfigMediator mediator = + new UserSettingDeviceConfigMediator.SettingsOverridesIndividualMediator(','); + + DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder("test") + .setInt("int", 1) + .setFloat("float", .5f) + .setBoolean("boolean", true) + .setLong("long", 123456789) + .setString("string", "abc123") + .build(); + + mediator.setDeviceConfigProperties(properties); + + assertEquals(1, mediator.getInt("int", 123)); + assertEquals(123, mediator.getInt("invalidKey", 123)); + assertEquals(.5f, mediator.getFloat("float", .8f), 0.001); + assertEquals(.8f, mediator.getFloat("invalidKey", .8f), 0.001); + assertEquals(true, mediator.getBoolean("boolean", false)); + assertEquals(true, mediator.getBoolean("invalidKey", true)); + assertEquals(123456789, mediator.getLong("long", 987654321)); + assertEquals(987654321, mediator.getInt("invalidKey", 987654321)); + assertEquals("abc123", mediator.getString("string", "xyz987")); + assertEquals("xyz987", mediator.getString("invalidKey", "xyz987")); + + // Clear the properties + mediator.setDeviceConfigProperties(null); + + assertEquals(123, mediator.getInt("int", 123)); + assertEquals(123, mediator.getInt("invalidKey", 123)); + assertEquals(.8f, mediator.getFloat("float", .8f), 0.001); + assertEquals(.8f, mediator.getFloat("invalidKey", .8f), 0.001); + assertEquals(false, mediator.getBoolean("boolean", false)); + assertEquals(true, mediator.getBoolean("invalidKey", true)); + assertEquals(987654321, mediator.getLong("long", 987654321)); + assertEquals(987654321, mediator.getInt("invalidKey", 987654321)); + assertEquals("xyz987", mediator.getString("string", "xyz987")); + assertEquals("xyz987", mediator.getString("invalidKey", "xyz987")); + } + + @Test + public void testSettingsOnly() { + UserSettingDeviceConfigMediator mediator = + new UserSettingDeviceConfigMediator.SettingsOverridesIndividualMediator(','); + + String settings = "int=1,float=.5f,boolean=true,long=123456789,string=abc123"; + + mediator.setSettingsString(settings); + + assertEquals(1, mediator.getInt("int", 123)); + assertEquals(123, mediator.getInt("invalidKey", 123)); + assertEquals(.5f, mediator.getFloat("float", .8f), 0.001); + assertEquals(.8f, mediator.getFloat("invalidKey", .8f), 0.001); + assertEquals(true, mediator.getBoolean("boolean", false)); + assertEquals(true, mediator.getBoolean("invalidKey", true)); + assertEquals(123456789, mediator.getLong("long", 987654321)); + assertEquals(987654321, mediator.getInt("invalidKey", 987654321)); + assertEquals("abc123", mediator.getString("string", "xyz987")); + assertEquals("xyz987", mediator.getString("invalidKey", "xyz987")); + + // Clear the settings + mediator.setSettingsString(null); + + assertEquals(123, mediator.getInt("int", 123)); + assertEquals(123, mediator.getInt("invalidKey", 123)); + assertEquals(.8f, mediator.getFloat("float", .8f), 0.001); + assertEquals(.8f, mediator.getFloat("invalidKey", .8f), 0.001); + assertEquals(false, mediator.getBoolean("boolean", false)); + assertEquals(true, mediator.getBoolean("invalidKey", true)); + assertEquals(987654321, mediator.getLong("long", 987654321)); + assertEquals(987654321, mediator.getInt("invalidKey", 987654321)); + assertEquals("xyz987", mediator.getString("string", "xyz987")); + assertEquals("xyz987", mediator.getString("invalidKey", "xyz987")); + } + + @Test + public void testSettingsOverridesAll() { + UserSettingDeviceConfigMediator mediator = + new UserSettingDeviceConfigMediator.SettingsOverridesAllMediator(','); + + String settings = "int=1,float=.5f,boolean=true,long=123456789,string=abc123," + + "intOnlyInSettings=9,floatOnlyInSettings=.25f,booleanOnlyInSettings=true," + + "longOnlyInSettings=53771465,stringOnlyInSettings=settingsString"; + DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder("test") + .setInt("int", 10) + .setInt("intOnlyInDeviceConfig", 9001) + .setFloat("float", .7f) + .setFloat("floatOnlyInDeviceConfig", .9f) + .setBoolean("boolean", false) + .setBoolean("booleanOnlyInDeviceConfig", true) + .setLong("long", 60000001) + .setLong("longOnlyInDeviceConfig", 7357) + .setString("string", "xyz987") + .setString("stringOnlyInDeviceConfig", "deviceConfigString") + .build(); + + mediator.setSettingsString(settings); + mediator.setDeviceConfigProperties(properties); + + // Since settings overrides all, anything in DeviceConfig should be ignored, + // even if settings doesn't have a value for it. + assertEquals(1, mediator.getInt("int", 123)); + assertEquals(9, mediator.getInt("intOnlyInSettings", 123)); + assertEquals(123, mediator.getInt("intOnlyInDeviceConfig", 123)); + assertEquals(.5f, mediator.getFloat("float", .8f), 0.001); + assertEquals(.25f, mediator.getFloat("floatOnlyInSettings", .8f), 0.001); + assertEquals(.8f, mediator.getFloat("floatOnlyInDeviceConfig", .8f), 0.001); + assertEquals(true, mediator.getBoolean("boolean", false)); + assertEquals(true, mediator.getBoolean("booleanOnlyInSettings", false)); + assertEquals(false, mediator.getBoolean("booleanOnlyInDeviceConfig", false)); + assertEquals(123456789, mediator.getLong("long", 987654321)); + assertEquals(53771465, mediator.getLong("longOnlyInSettings", 987654321)); + assertEquals(987654321, mediator.getLong("longOnlyInDeviceConfig", 987654321)); + assertEquals("abc123", mediator.getString("string", "default")); + assertEquals("settingsString", mediator.getString("stringOnlyInSettings", "default")); + assertEquals("default", mediator.getString("stringOnlyInDeviceConfig", "default")); + + // Nothing in settings, do DeviceConfig can be used. + mediator.setSettingsString(""); + + assertEquals(10, mediator.getInt("int", 123)); + assertEquals(123, mediator.getInt("intOnlyInSettings", 123)); + assertEquals(9001, mediator.getInt("intOnlyInDeviceConfig", 123)); + assertEquals(.7f, mediator.getFloat("float", .8f), 0.001); + assertEquals(.8f, mediator.getFloat("floatOnlyInSettings", .8f), 0.001); + assertEquals(.9f, mediator.getFloat("floatOnlyInDeviceConfig", .8f), 0.001); + assertEquals(false, mediator.getBoolean("boolean", false)); + assertEquals(false, mediator.getBoolean("booleanOnlyInSettings", false)); + assertEquals(true, mediator.getBoolean("booleanOnlyInDeviceConfig", false)); + assertEquals(60000001, mediator.getLong("long", 987654321)); + assertEquals(987654321, mediator.getLong("longOnlyInSettings", 987654321)); + assertEquals(7357, mediator.getLong("longOnlyInDeviceConfig", 987654321)); + assertEquals("xyz987", mediator.getString("string", "default")); + assertEquals("default", mediator.getString("stringOnlyInSettings", "default")); + assertEquals("deviceConfigString", + mediator.getString("stringOnlyInDeviceConfig", "default")); + + // Nothing in settings, do DeviceConfig can be used. + mediator.setSettingsString(null); + + assertEquals(10, mediator.getInt("int", 123)); + assertEquals(123, mediator.getInt("intOnlyInSettings", 123)); + assertEquals(9001, mediator.getInt("intOnlyInDeviceConfig", 123)); + assertEquals(.7f, mediator.getFloat("float", .8f), 0.001); + assertEquals(.8f, mediator.getFloat("floatOnlyInSettings", .8f), 0.001); + assertEquals(.9f, mediator.getFloat("floatOnlyInDeviceConfig", .8f), 0.001); + assertEquals(false, mediator.getBoolean("boolean", false)); + assertEquals(false, mediator.getBoolean("booleanOnlyInSettings", false)); + assertEquals(true, mediator.getBoolean("booleanOnlyInDeviceConfig", false)); + assertEquals(60000001, mediator.getLong("long", 987654321)); + assertEquals(987654321, mediator.getLong("longOnlyInSettings", 987654321)); + assertEquals(7357, mediator.getLong("longOnlyInDeviceConfig", 987654321)); + assertEquals("xyz987", mediator.getString("string", "default")); + assertEquals("default", mediator.getString("stringOnlyInSettings", "default")); + assertEquals("deviceConfigString", + mediator.getString("stringOnlyInDeviceConfig", "default")); + } + + @Test + public void testSettingsOverridesIndividual() { + UserSettingDeviceConfigMediator mediator = + new UserSettingDeviceConfigMediator.SettingsOverridesIndividualMediator(','); + + String settings = "int=1,float=.5f,boolean=true,long=123456789,string=abc123," + + "intOnlyInSettings=9,floatOnlyInSettings=.25f,booleanOnlyInSettings=true," + + "longOnlyInSettings=53771465,stringOnlyInSettings=settingsString"; + DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder("test") + .setInt("int", 10) + .setInt("intOnlyInDeviceConfig", 9001) + .setFloat("float", .7f) + .setFloat("floatOnlyInDeviceConfig", .9f) + .setBoolean("boolean", false) + .setBoolean("booleanOnlyInDeviceConfig", true) + .setLong("long", 60000001) + .setLong("longOnlyInDeviceConfig", 7357) + .setString("string", "xyz987") + .setString("stringOnlyInDeviceConfig", "deviceConfigString") + .build(); + + mediator.setSettingsString(settings); + mediator.setDeviceConfigProperties(properties); + + // Since settings overrides individual, anything in DeviceConfig that doesn't exist in + // settings should be used. + assertEquals(1, mediator.getInt("int", 123)); + assertEquals(9, mediator.getInt("intOnlyInSettings", 123)); + assertEquals(9001, mediator.getInt("intOnlyInDeviceConfig", 123)); + assertEquals(.5f, mediator.getFloat("float", .8f), 0.001); + assertEquals(.25f, mediator.getFloat("floatOnlyInSettings", .8f), 0.001); + assertEquals(.9f, mediator.getFloat("floatOnlyInDeviceConfig", .8f), 0.001); + assertEquals(true, mediator.getBoolean("boolean", false)); + assertEquals(true, mediator.getBoolean("booleanOnlyInSettings", false)); + assertEquals(true, mediator.getBoolean("booleanOnlyInDeviceConfig", false)); + assertEquals(123456789, mediator.getLong("long", 987654321)); + assertEquals(53771465, mediator.getLong("longOnlyInSettings", 987654321)); + assertEquals(7357, mediator.getLong("longOnlyInDeviceConfig", 987654321)); + assertEquals("abc123", mediator.getString("string", "default")); + assertEquals("settingsString", mediator.getString("stringOnlyInSettings", "default")); + assertEquals("deviceConfigString", + mediator.getString("stringOnlyInDeviceConfig", "default")); + } +} |