diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 9f931b4059c86ddc241dd5482f7e24e6e9b032c3..c012ff34bfabfb2b12b291113ecadc59382fa8ce 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -15279,6 +15279,7 @@ public final class Settings {
          * max_history_files (int)
          * max_history_buffer_kb (int)
          * battery_charged_delay_ms (int)
+         * battery_charging_enforce_level (int)
          * </pre>
          *
          * <p>
@@ -18306,8 +18307,11 @@ public final class Settings {
 
         /**
          * Delay for sending ACTION_CHARGING after device is plugged in.
-         * This is used as an override for constants defined in BatteryStatsImpl for
-         * ease of experimentation.
+         * This is used as an override for constants defined in BatteryStatsImpl. Its purposes are:
+         * <ol>
+         *     <li>Ease of experimentation</li>
+         *     <li>Customization of different device</li>
+         * </ol>
          *
          * @see com.android.internal.os.BatteryStatsImpl.Constants.KEY_BATTERY_CHARGED_DELAY_MS
          * @hide
@@ -18316,6 +18320,22 @@ public final class Settings {
         public static final String BATTERY_CHARGING_STATE_UPDATE_DELAY =
                 "battery_charging_state_update_delay";
 
+        /**
+         * Threshold battery level to enforce battery state as charging. That means when battery
+         * level is equal to or higher than this threshold, it is always considered charging, even
+         * if battery level lowered.
+         * This is used as an override for constants defined in BatteryStatsImpl. Its purposes are:
+         * <ol>
+         *     <li>Ease of experimentation</li>
+         *     <li>Customization of different device</li>
+         * </ol>
+         *
+         * @hide
+         * @see com.android.internal.os.BatteryStatsImpl.Constants.BATTERY_CHARGING_ENFORCE_LEVEL
+         */
+        public static final String BATTERY_CHARGING_STATE_ENFORCE_LEVEL =
+                "battery_charging_state_enforce_level";
+
         /**
          * A serialized string of params that will be loaded into a text classifier action model.
          *
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 4c9436b4e151adf477b668e18b39a8586de5fa67..89a8dd95d3c32e2a099c604b2e3c707e6c03405d 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -327,4 +327,12 @@
 
     <!-- Whether wifi is always requested by default. -->
     <bool name="def_enable_wifi_always_requested">false</bool>
+
+    <!-- Default for Settings.BATTERY_CHARGING_STATE_UPDATE_DELAY in millisecond.
+        -1 means system internal default value is used. -->
+    <integer name="def_battery_charging_state_update_delay_ms">-1</integer>
+
+    <!-- Default for Settings.BATTERY_CHARGING_STATE_ENFORCE_LEVEL.
+        -1 means system internal default value is used. -->
+    <integer name="def_battery_charging_state_enforce_level">-1</integer>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 785003a355fc8c83a4199e6a051698343e842f11..b0abf92ffe08c83d6d61386866a33ce9e6bcbc0a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3792,7 +3792,7 @@ public class SettingsProvider extends ContentProvider {
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 223;
+            private static final int SETTINGS_VERSION = 224;
 
             private final int mUserId;
 
@@ -5965,8 +5965,23 @@ public class SettingsProvider extends ContentProvider {
                             // Do nothing. Leave the value as is.
                         }
                     }
+                }
+
+                currentVersion = 223;
 
-                    currentVersion = 223;
+                // Version 223: make charging constraint update criteria customizable.
+                if (currentVersion == 223) {
+                    initGlobalSettingsDefaultValLocked(
+                            Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
+                            getContext().getResources().getInteger(
+                                    R.integer.def_battery_charging_state_update_delay_ms));
+
+                    initGlobalSettingsDefaultValLocked(
+                            Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL,
+                            getContext().getResources().getInteger(
+                                    R.integer.def_battery_charging_state_enforce_level)
+                    );
+                    currentVersion = 224;
                 }
 
                 // vXXX: Add new settings above this point.
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 1f171ba4834346ab7e3d27298e2df3ba54265782..2e174e267bde377f6e1abf74c5029419afc22224 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -145,6 +145,7 @@ public class SettingsBackupTest {
                     Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
                     Settings.Global.AUTO_TIME_ZONE_EXPLICIT,
                     Settings.Global.AVERAGE_TIME_TO_DISCHARGE,
+                    Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL,
                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
                     Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME,
                     Settings.Global.BROADCAST_BG_CONSTANTS,
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index a6558e07b2aa13be3e3e70aada2675725564911b..eea13f179b9eccd5b113fc4baf695d32686d2bb0 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -14575,9 +14575,10 @@ public class BatteryStatsImpl extends BatteryStats {
                     mModStepMode = 0;
                 }
             } else {
-                if (level >= 90) {
-                    // If the battery level is at least 90%, always consider the device to be
-                    // charging even if it happens to go down a level.
+                if (level >= mConstants.BATTERY_CHARGING_ENFORCE_LEVEL) {
+                    // If the battery level is at least Constants.BATTERY_CHARGING_ENFORCE_LEVEL,
+                    // always consider the device to be charging even if it happens to go down a
+                    // level.
                     changed |= setChargingLocked(true);
                 } else if (!mCharging) {
                     if (mLastChargeStepLevel < level) {
@@ -15313,6 +15314,8 @@ public class BatteryStatsImpl extends BatteryStats {
         public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
         public static final String KEY_BATTERY_CHARGED_DELAY_MS =
                 "battery_charged_delay_ms";
+        public static final String KEY_BATTERY_CHARGING_ENFORCE_LEVEL =
+                "battery_charging_enforce_level";
         public static final String KEY_PER_UID_MODEM_POWER_MODEL =
                 "per_uid_modem_power_model";
         public static final String KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION =
@@ -15363,6 +15366,7 @@ public class BatteryStatsImpl extends BatteryStats {
         private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
         private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
         private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
+        private static final int DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL = 90;
         @PerUidModemPowerModel
         private static final int DEFAULT_PER_UID_MODEM_MODEL =
                 PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX;
@@ -15384,6 +15388,7 @@ public class BatteryStatsImpl extends BatteryStats {
         public int MAX_HISTORY_FILES;
         public int MAX_HISTORY_BUFFER; /*Bytes*/
         public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
+        public int BATTERY_CHARGING_ENFORCE_LEVEL = DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL;
         public int PER_UID_MODEM_MODEL = DEFAULT_PER_UID_MODEM_MODEL;
         public boolean PHONE_ON_EXTERNAL_STATS_COLLECTION =
                 DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION;
@@ -15412,6 +15417,9 @@ public class BatteryStatsImpl extends BatteryStats {
             mResolver.registerContentObserver(
                     Settings.Global.getUriFor(Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY),
                     false /* notifyForDescendants */, this);
+            mResolver.registerContentObserver(Settings.Global.getUriFor(
+                            Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL),
+                    false /* notifyForDescendants */, this);
             updateConstants();
         }
 
@@ -15424,6 +15432,12 @@ public class BatteryStatsImpl extends BatteryStats {
                     updateBatteryChargedDelayMsLocked();
                 }
                 return;
+            } else if (uri.equals(Settings.Global.getUriFor(
+                    Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL))) {
+                synchronized (BatteryStatsImpl.this) {
+                    updateBatteryChargingEnforceLevelLocked();
+                }
+                return;
             }
             updateConstants();
         }
@@ -15477,6 +15491,7 @@ public class BatteryStatsImpl extends BatteryStats {
                         DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS);
 
                 updateBatteryChargedDelayMsLocked();
+                updateBatteryChargingEnforceLevelLocked();
 
                 onChange();
             }
@@ -15507,6 +15522,21 @@ public class BatteryStatsImpl extends BatteryStats {
             }
         }
 
+        private void updateBatteryChargingEnforceLevelLocked() {
+            int lastChargingEnforceLevel = BATTERY_CHARGING_ENFORCE_LEVEL;
+            final int level = Settings.Global.getInt(mResolver,
+                    Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL,
+                    -1);
+
+            BATTERY_CHARGING_ENFORCE_LEVEL = level >= 0 ? level : mParser.getInt(
+                    KEY_BATTERY_CHARGING_ENFORCE_LEVEL, DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL);
+
+            if (BATTERY_CHARGING_ENFORCE_LEVEL <= mLastChargeStepLevel
+                    && mLastChargeStepLevel < lastChargingEnforceLevel) {
+                setChargingLocked(true);
+            }
+        }
+
         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
             if (oldTimeMs != newTimeMs) {
@@ -15541,6 +15571,8 @@ public class BatteryStatsImpl extends BatteryStats {
             pw.println(MAX_HISTORY_BUFFER/1024);
             pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
             pw.println(BATTERY_CHARGED_DELAY_MS);
+            pw.print(KEY_BATTERY_CHARGING_ENFORCE_LEVEL); pw.print("=");
+            pw.println(BATTERY_CHARGING_ENFORCE_LEVEL);
             pw.print(KEY_PER_UID_MODEM_POWER_MODEL); pw.print("=");
             pw.println(getPerUidModemModelName(PER_UID_MODEM_MODEL));
             pw.print(KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION); pw.print("=");