Merge "Run lock before fingerprint enroll" into tm-qpr-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b7007c4..fde4f26 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6646,6 +6646,8 @@
     <string name="battery_not_usage_24hr">No usage for past 24 hr</string>
     <!-- Description for no usage time but have battery usage [CHAR LIMIT=120] -->
     <string name="battery_usage_without_time"></string>
+    <!-- Description for other users aggregated battery usage data [CHAR LIMIT=120] -->
+    <string name="battery_usage_other_users">Other users</string>
 
     <!-- Graph subtext displayed to user when enhanced battery estimate is being used [CHAR LIMIT=120] -->
     <string name="advanced_battery_graph_subtext">Battery left estimate is based on your device usage</string>
diff --git a/res/xml/privacy_controls_settings.xml b/res/xml/privacy_controls_settings.xml
index a477dc2..cc88e0c 100644
--- a/res/xml/privacy_controls_settings.xml
+++ b/res/xml/privacy_controls_settings.xml
@@ -34,12 +34,6 @@
         android:summary="@string/mic_toggle_description"
         settings:controller="com.android.settings.privacy.MicToggleController"/>
 
-    <!-- Location toggle -->
-    <com.android.settingslib.RestrictedSwitchPreference
-        android:key="privacy_location_toggle"
-        android:title="@string/location_toggle_title"
-        android:summary="@string/perm_toggle_description"/>
-
     <!-- Clipboard access notifications -->
     <SwitchPreference
         android:key="show_clip_access_notification"
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index bf04d5f..26a661a 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -115,6 +115,7 @@
 
     private FingerprintManager mFingerprintManager;
     private boolean mCanAssumeUdfps;
+    private boolean mCanAssumeSidefps;
     @Nullable private ProgressBar mProgressBar;
     private ObjectAnimator mProgressAnim;
     private TextView mDescriptionText;
@@ -156,7 +157,8 @@
         mFingerprintManager = getSystemService(FingerprintManager.class);
         final List<FingerprintSensorPropertiesInternal> props =
                 mFingerprintManager.getSensorPropertiesInternal();
-        mCanAssumeUdfps = props.size() == 1 && props.get(0).isAnyUdfpsType();
+        mCanAssumeUdfps = props != null && props.size() == 1 && props.get(0).isAnyUdfpsType();
+        mCanAssumeSidefps = props != null && props.size() == 1 && props.get(0).isAnySidefpsType();
 
         mAccessibilityManager = getSystemService(AccessibilityManager.class);
         mIsAccessibilityEnabled = mAccessibilityManager.isEnabled();
@@ -567,7 +569,7 @@
     }
 
     private void showError(CharSequence error) {
-        if (mCanAssumeUdfps) {
+        if (mCanAssumeUdfps || mCanAssumeSidefps) {
             setHeaderText(error);
             // Show nothing for subtitle when getting an error message.
             setDescriptionText("");
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
index 8ce3845..71d0c8e 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
@@ -241,6 +241,8 @@
         final boolean isSetupWizard = WizardManagerHelper.isAnySetupWizard(getIntent());
         final boolean isDeferredSetupWizard =
                 WizardManagerHelper.isDeferredSetupWizard(getIntent());
+        final boolean isPortalSetupWizard =
+                WizardManagerHelper.isPortalSetupWizard(getIntent());
         if (mFingerprintManager != null) {
             final List<FingerprintSensorPropertiesInternal> props =
                     mFingerprintManager.getSensorPropertiesInternal();
@@ -252,7 +254,7 @@
                     getApplicationContext()
                             .getResources()
                             .getInteger(R.integer.suw_max_fingerprints_enrollable);
-            if (isSetupWizard && !isDeferredSetupWizard) {
+            if (isSetupWizard && !isDeferredSetupWizard && !isPortalSetupWizard) {
                 if (numEnrolledFingerprints >= maxFingerprintsEnrollableIfSUW) {
                     return R.string.fingerprint_intro_error_max;
                 } else {
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index 3f6c165..a6c48a4 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -69,6 +69,8 @@
     public static final int UID_REMOVED_APPS = -4;
     /** Special UID value for data usage by tethering. */
     public static final int UID_TETHERING = -5;
+    /** Special UID for aggregated other users. */
+    public static final long UID_OTHER_USERS = Long.MIN_VALUE;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({StatusType.SCREEN_USAGE,
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index ee53d7f..83d7a33 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -150,6 +150,11 @@
     Map<Long, Map<String, BatteryHistEntry>> getBatteryHistory(Context context);
 
     /**
+     * Returns battery history data since last full charge with corresponding timestamp key.
+     */
+    Map<Long, Map<String, BatteryHistEntry>> getBatteryHistorySinceLastFullCharge(Context context);
+
+    /**
      * Returns {@link Uri} to monitor battery history data is update.
      */
     Uri getBatteryHistoryUri();
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index 8c8fd96..1262641 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -166,6 +166,12 @@
     }
 
     @Override
+    public Map<Long, Map<String, BatteryHistEntry>> getBatteryHistorySinceLastFullCharge(
+            Context context) {
+        return null;
+    }
+
+    @Override
     public Uri getBatteryHistoryUri() {
         return null;
     }
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java
index 8b995c8..d4d7a00 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java
@@ -113,6 +113,9 @@
 
     /** Gets the app label name for this entry. */
     public String getAppLabel() {
+        if (isOtherUsers()) {
+            return mContext.getString(R.string.battery_usage_other_users);
+        }
         loadLabelAndIcon();
         // Returns default applicationn label if we cannot find it.
         return mAppLabel == null || mAppLabel.length() == 0
@@ -122,6 +125,9 @@
 
     /** Gets the app icon {@link Drawable} for this entry. */
     public Drawable getAppIcon() {
+        if (isOtherUsers()) {
+            return mContext.getDrawable(R.drawable.ic_power_system);
+        }
         loadLabelAndIcon();
         return mAppIcon != null && mAppIcon.getConstantState() != null
                 ? mAppIcon.getConstantState().newDrawable()
@@ -156,6 +162,9 @@
 
     /** Whether the current BatteryDiffEntry is system component or not. */
     public boolean isSystemEntry() {
+        if (isOtherUsers()) {
+            return true;
+        }
         switch (mBatteryHistEntry.mConsumerType) {
             case ConvertUtils.CONSUMER_TYPE_USER_BATTERY:
             case ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY:
@@ -175,6 +184,11 @@
         return false;
     }
 
+    private boolean isOtherUsers() {
+        return mBatteryHistEntry.mConsumerType == ConvertUtils.CONSUMER_TYPE_UID_BATTERY
+                && mBatteryHistEntry.mUid == BatteryUtils.UID_OTHER_USERS;
+    }
+
     void loadLabelAndIcon() {
         if (mIsLoaded) {
             return;
diff --git a/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java b/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
index 76f9419..168fe0f 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
@@ -21,6 +21,7 @@
 import android.os.BatteryUsageStats;
 import android.os.LocaleList;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.text.format.DateFormat;
 import android.text.format.DateUtils;
 import android.util.ArraySet;
@@ -28,6 +29,8 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import com.android.settings.Utils;
+import com.android.settings.fuelgauge.BatteryUtils;
 import com.android.settings.overlay.FeatureFactory;
 
 import java.lang.annotation.Retention;
@@ -265,17 +268,55 @@
             }
         }
         insert24HoursData(BatteryChartView.SELECTED_INDEX_ALL, resultMap);
+        resolveMultiUsersData(context, resultMap);
         if (purgeLowPercentageAndFakeData) {
             purgeLowPercentageAndFakeData(context, resultMap);
         }
         return resultMap;
     }
 
+    @VisibleForTesting
+    static void resolveMultiUsersData(
+            final Context context,
+            final Map<Integer, List<BatteryDiffEntry>> indexedUsageMap) {
+        final int currentUserId = context.getUserId();
+        final UserHandle userHandle =
+                Utils.getManagedProfile(context.getSystemService(UserManager.class));
+        final int workProfileUserId =
+                userHandle != null ? userHandle.getIdentifier() : Integer.MIN_VALUE;
+        // Loops for all BatteryDiffEntry in the different slots.
+        for (List<BatteryDiffEntry> entryList : indexedUsageMap.values()) {
+            double consumePowerFromOtherUsers = 0f;
+            double consumePercentageFromOtherUsers = 0f;
+            final Iterator<BatteryDiffEntry> iterator = entryList.iterator();
+            while (iterator.hasNext()) {
+                final BatteryDiffEntry entry = iterator.next();
+                final BatteryHistEntry batteryHistEntry = entry.mBatteryHistEntry;
+                if (batteryHistEntry.mConsumerType != CONSUMER_TYPE_UID_BATTERY) {
+                    continue;
+                }
+                // Whether the BatteryHistEntry represents the current user data?
+                if (batteryHistEntry.mUserId == currentUserId
+                        || batteryHistEntry.mUserId == workProfileUserId) {
+                    continue;
+                }
+                // Removes and aggregates non-current users data from the list.
+                iterator.remove();
+                consumePowerFromOtherUsers += entry.mConsumePower;
+                consumePercentageFromOtherUsers += entry.getPercentOfTotal();
+            }
+            if (consumePercentageFromOtherUsers != 0) {
+                entryList.add(createOtherUsersEntry(context, consumePowerFromOtherUsers,
+                        consumePercentageFromOtherUsers));
+            }
+        }
+    }
+
     private static void insert24HoursData(
             final int desiredIndex,
             final Map<Integer, List<BatteryDiffEntry>> indexedUsageMap) {
         final Map<String, BatteryDiffEntry> resultMap = new HashMap<>();
-        double totalConsumePower = 0.0;
+        double totalConsumePower = 0f;
         // Loops for all BatteryDiffEntry and aggregate them together.
         for (List<BatteryDiffEntry> entryList : indexedUsageMap.values()) {
             for (BatteryDiffEntry entry : entryList) {
@@ -361,4 +402,22 @@
         return locales != null && !locales.isEmpty() ? locales.get(0)
                 : Locale.getDefault();
     }
+
+    private static BatteryDiffEntry createOtherUsersEntry(
+            Context context, double consumePower, double consumePercentage) {
+        final ContentValues values = new ContentValues();
+        values.put(BatteryHistEntry.KEY_UID, BatteryUtils.UID_OTHER_USERS);
+        values.put(BatteryHistEntry.KEY_USER_ID, BatteryUtils.UID_OTHER_USERS);
+        values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, CONSUMER_TYPE_UID_BATTERY);
+        // We will show the percentage for the "other users" item only, the aggregated
+        // running time information is useless for users to identify individual apps.
+        final BatteryDiffEntry batteryDiffEntry = new BatteryDiffEntry(
+                context,
+                /*foregroundUsageTimeInMs=*/ 0,
+                /*backgroundUsageTimeInMs=*/ 0,
+                consumePower,
+                new BatteryHistEntry(values));
+        batteryDiffEntry.setTotalConsumePower(100 * consumePower / consumePercentage);
+        return batteryDiffEntry;
+    }
 }
diff --git a/src/com/android/settings/network/telephony/NetworkProviderWifiCallingGroup.java b/src/com/android/settings/network/telephony/NetworkProviderWifiCallingGroup.java
index 14bdd41..688084f 100644
--- a/src/com/android/settings/network/telephony/NetworkProviderWifiCallingGroup.java
+++ b/src/com/android/settings/network/telephony/NetworkProviderWifiCallingGroup.java
@@ -74,6 +74,7 @@
     private Map<Integer, PhoneAccountHandle> mSimCallManagerList = new HashMap<>();
     private Map<Integer, Preference> mWifiCallingForSubPreferences;
     private List<SubscriptionInfo> mSubInfoListForWfc;
+    private SubscriptionsChangeListener mChangeListener;
 
     public NetworkProviderWifiCallingGroup(Context context, Lifecycle lifecycle,
             String preferenceGroupKey) {
@@ -87,26 +88,25 @@
             mTelephonyCallback = new PhoneCallStateTelephonyCallback();
         }
         lifecycle.addObserver(this);
+        mChangeListener = new SubscriptionsChangeListener(context, this);
     }
 
     private void setSubscriptionInfoList(Context context) {
         mSubInfoListForWfc = new ArrayList<>(
                 SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager));
-        if (mSubInfoListForWfc != null) {
-            mSubInfoListForWfc.removeIf(info -> {
-                final int subId = info.getSubscriptionId();
-                setTelephonyManagerForSubscriptionId(context, subId);
-                setPhoneAccountHandleForSubscriptionId(context, subId);
-                boolean isExisted = mSubInfoListForWfc.contains(info);
-                boolean shouldShowWfcForSub = shouldShowWifiCallingForSub(subId);
-                if (!shouldShowWfcForSub && isExisted) {
-                    return true;
-                }
-                return false;
-            });
-        } else {
-            Log.d(TAG, "No active subscriptions");
-        }
+        mSubInfoListForWfc.removeIf(info -> {
+            final int subId = info.getSubscriptionId();
+            setTelephonyManagerForSubscriptionId(context, subId);
+            setPhoneAccountHandleForSubscriptionId(context, subId);
+            boolean isExisted = mSubInfoListForWfc.contains(info);
+            boolean shouldShowWfcForSub = shouldShowWifiCallingForSub(subId);
+            if (!shouldShowWfcForSub && isExisted) {
+                return true;
+            }
+            return false;
+        });
+        Log.d(TAG, "setSubscriptionInfoList: mSubInfoListForWfc size:"
+                + mSubInfoListForWfc.size());
     }
 
     private void setTelephonyManagerForSubscriptionId(Context context, int subId) {
@@ -137,12 +137,18 @@
 
     @OnLifecycleEvent(Event.ON_RESUME)
     public void onResume() {
+        if (mChangeListener != null) {
+            mChangeListener.start();
+        }
         updateListener();
         update();
     }
 
     @OnLifecycleEvent(Event.ON_PAUSE)
     public void onPause() {
+        if (mChangeListener != null) {
+            mChangeListener.stop();
+        }
         if ((mTelephonyCallback != null)) {
             mTelephonyCallback.unregister();
         }
@@ -176,6 +182,7 @@
 
     private void update() {
         if (mPreferenceGroup == null) {
+            Log.d(TAG, "mPreferenceGroup == null");
             return;
         }
 
@@ -255,7 +262,11 @@
 
     @Override
     public void onSubscriptionsChanged() {
+        Log.d(TAG, "onSubscriptionsChanged:");
         setSubscriptionInfoList(mContext);
+        if (mPreferenceGroup != null) {
+            mPreferenceGroup.setVisible(isAvailable());
+        }
         updateListener();
         update();
     }
@@ -322,6 +333,7 @@
                         CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL);
             }
         }
+        Log.d(TAG, "isWifiCallingAvailableForCarrier:" + isWifiCallingAvailableForCarrier);
         return isWifiCallingAvailableForCarrier;
     }
 
diff --git a/src/com/android/settings/privacy/PrivacyControlsFragment.java b/src/com/android/settings/privacy/PrivacyControlsFragment.java
index 7b33364..1d9a4712 100644
--- a/src/com/android/settings/privacy/PrivacyControlsFragment.java
+++ b/src/com/android/settings/privacy/PrivacyControlsFragment.java
@@ -33,15 +33,12 @@
     private static final String TAG = "PrivacyDashboardFrag";
     private static final String CAMERA_KEY = "privacy_camera_toggle";
     private static final String MIC_KEY = "privacy_mic_toggle";
-    private static final String LOCATION_KEY = "privacy_location_toggle";
 
     @Override
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         controllers.add(new CameraToggleController(context, CAMERA_KEY));
         controllers.add(new MicToggleController(context, MIC_KEY));
-        controllers.add(new LocationToggleController(context, LOCATION_KEY,
-                getSettingsLifecycle()));
         controllers.add(new ShowClipAccessNotificationPreferenceController(context));
         return controllers;
     }
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
index d8852db..1096f40 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
@@ -173,4 +173,24 @@
 
         assertThat(result).isEqualTo(R.string.fingerprint_intro_error_max);
     }
+
+    @Test
+    public void intro_CheckCanEnrollDuringPortal() {
+        setupFingerprintEnrollIntroWith(
+                new Intent().putExtra(WizardManagerHelper.EXTRA_IS_PORTAL_SETUP, true));
+        setFingerprintManagerToHave(2 /* numEnrollments */);
+        int result = mFingerprintEnrollIntroduction.checkMaxEnrolled();
+
+        assertThat(result).isEqualTo(0);
+    }
+
+    @Test
+    public void intro_CheckMaxEnrolledDuringPortal() {
+        setupFingerprintEnrollIntroWith(
+                new Intent().putExtra(WizardManagerHelper.EXTRA_IS_PORTAL_SETUP, true));
+        setFingerprintManagerToHave(6 /* numEnrollments */);
+        int result = mFingerprintEnrollIntroduction.checkMaxEnrolled();
+
+        assertThat(result).isEqualTo(R.string.fingerprint_intro_error_max);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
index 14bbeea..283df7b 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
@@ -70,6 +70,7 @@
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 @RunWith(RobolectricTestRunner.class)
@@ -343,9 +344,17 @@
 
     private void verifyBackupData(String expectedResult) throws Exception {
         final byte[] expectedBytes = expectedResult.getBytes();
+        final ArgumentCaptor<byte[]> captor = ArgumentCaptor.forClass(byte[].class);
+        final Set<String> expectedResultSet =
+                Set.of(expectedResult.split(BatteryBackupHelper.DELIMITER));
+
         verify(mBackupDataOutput).writeEntityHeader(
                 BatteryBackupHelper.KEY_OPTIMIZATION_LIST, expectedBytes.length);
-        verify(mBackupDataOutput).writeEntityData(expectedBytes, expectedBytes.length);
+        verify(mBackupDataOutput).writeEntityData(captor.capture(), eq(expectedBytes.length));
+        final String actualResult = new String(captor.getValue());
+        final Set<String> actualResultSet =
+                Set.of(actualResult.split(BatteryBackupHelper.DELIMITER));
+        assertThat(actualResultSet).isEqualTo(expectedResultSet);
     }
 
     private void createTestingData(
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
index bb19b5a..683f0fd 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
@@ -138,7 +138,7 @@
         // Generates fake testing data.
         final ContentValues values = getContentValuesWithType(
                 ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
-        values.put("drainType",
+        values.put(BatteryHistEntry.KEY_DRAIN_TYPE,
                 Integer.valueOf(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY));
         final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
 
@@ -164,7 +164,7 @@
         // Generates fake testing data.
         final ContentValues values = getContentValuesWithType(
                 ConvertUtils.CONSUMER_TYPE_USER_BATTERY);
-        values.put("userId", Integer.valueOf(1001));
+        values.put(BatteryHistEntry.KEY_USER_ID, Integer.valueOf(1001));
         final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
 
         final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
@@ -189,8 +189,8 @@
         final String fakePackageName = "com.fake.google.com";
         final ContentValues values = getContentValuesWithType(
                 ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
-        values.put("uid", /*invalid uid*/ 10001);
-        values.put("packageName", fakePackageName);
+        values.put(BatteryHistEntry.KEY_UID, /*invalid uid*/ 10001);
+        values.put(BatteryHistEntry.KEY_PACKAGE_NAME, fakePackageName);
         doReturn(mMockAppInfo).when(mMockPackageManager)
                 .getApplicationInfo(fakePackageName, 0);
         doReturn(expectedAppLabel).when(mMockPackageManager)
@@ -233,7 +233,7 @@
         final String expectedAppLabel = "fake app label";
         final ContentValues values = getContentValuesWithType(
                 ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
-        values.put("appLabel", expectedAppLabel);
+        values.put(BatteryHistEntry.KEY_APP_LABEL, expectedAppLabel);
         final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
 
         final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
@@ -391,8 +391,8 @@
         final String fakePackageName = "com.fake.google.com";
         final ContentValues values = getContentValuesWithType(
                 ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
-        values.put("uid", /*invalid uid*/ 10001);
-        values.put("packageName", fakePackageName);
+        values.put(BatteryHistEntry.KEY_UID, /*invalid uid*/ 10001);
+        values.put(BatteryHistEntry.KEY_PACKAGE_NAME, fakePackageName);
         final BatteryDiffEntry entry =
                 createBatteryDiffEntry(10, new BatteryHistEntry(values));
 
@@ -424,7 +424,7 @@
         final String expectedPackageName = "com.fake.google.com";
         final ContentValues values = getContentValuesWithType(
                 ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
-        values.put("packageName", expectedPackageName);
+        values.put(BatteryHistEntry.KEY_PACKAGE_NAME, expectedPackageName);
         final BatteryDiffEntry entry =
                 createBatteryDiffEntry(10, new BatteryHistEntry(values));
 
@@ -437,7 +437,7 @@
         final ContentValues values = getContentValuesWithType(
                 ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
         values.put(
-                "packageName",
+                BatteryHistEntry.KEY_PACKAGE_NAME,
                 expectedPackageName + ":privileged_process0");
         final BatteryDiffEntry entry =
                 createBatteryDiffEntry(10, new BatteryHistEntry(values));
@@ -445,11 +445,24 @@
         assertThat(entry.getPackageName()).isEqualTo(expectedPackageName);
     }
 
+    @Test
+    public void getAppLabel_withOtherUsersUid_returnExpectedLabel() {
+        final ContentValues values = getContentValuesWithType(
+                ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
+        values.put(BatteryHistEntry.KEY_UID, BatteryUtils.UID_OTHER_USERS);
+
+        final BatteryDiffEntry batteryDiffEntry = createBatteryDiffEntry(
+                /*consumePower=*/ 0, new BatteryHistEntry(values));
+
+        assertThat(batteryDiffEntry.getAppLabel())
+                .isEqualTo(mContext.getString(R.string.battery_usage_other_users));
+    }
+
     private BatteryDiffEntry createBatteryDiffEntry(
             int consumerType, long uid, boolean isHidden) {
         final ContentValues values = getContentValuesWithType(consumerType);
-        values.put("isHidden", isHidden);
-        values.put("uid", uid);
+        values.put(BatteryHistEntry.KEY_IS_HIDDEN, isHidden);
+        values.put(BatteryHistEntry.KEY_UID, uid);
         return new BatteryDiffEntry(
                 mContext,
                 /*foregroundUsageTimeInMs=*/ 0,
@@ -472,15 +485,15 @@
 
     private static ContentValues getContentValuesWithType(int consumerType) {
         final ContentValues values = new ContentValues();
-        values.put("consumerType", Integer.valueOf(consumerType));
+        values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, Integer.valueOf(consumerType));
         return values;
     }
 
     private BatteryDiffEntry createBatteryDiffEntry(Drawable drawable) throws Exception {
         final ContentValues values = getContentValuesWithType(
                 ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
-        values.put("uid", 1001);
-        values.put("packageName", "com.a.b.c");
+        values.put(BatteryHistEntry.KEY_UID, 1001);
+        values.put(BatteryHistEntry.KEY_PACKAGE_NAME, "com.a.b.c");
         final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
         doReturn(drawable).when(mMockPackageManager).getDefaultActivityIcon();
         doReturn(null).when(mMockPackageManager).getApplicationInfo("com.a.b.c", 0);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
index 0b8a98a..c1f9815 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
@@ -27,6 +27,7 @@
 import android.os.LocaleList;
 import android.os.UserHandle;
 
+import com.android.settings.fuelgauge.BatteryUtils;
 import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
 import com.android.settings.testutils.FakeFeatureFactory;
 
@@ -39,6 +40,7 @@
 import org.robolectric.RuntimeEnvironment;
 
 import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -371,6 +373,71 @@
         assertThat(ConvertUtils.getLocale(mContext)).isEqualTo(Locale.getDefault());
     }
 
+    @Test
+    public void resolveMultiUsersData_replaceOtherUsersItemWithExpectedEntry() {
+        final int currentUserId = mContext.getUserId();
+        final Map<Integer, List<BatteryDiffEntry>> entryMap = new HashMap<>();
+        // Without other users time slot.
+        entryMap.put(0, Arrays.asList(
+                createBatteryDiffEntry(
+                        currentUserId,
+                        ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
+                        /*consumePercentage=*/ 50)));
+        // With other users time slot.
+        final List<BatteryDiffEntry> withOtherUsersList = new ArrayList<>();
+        entryMap.put(1, withOtherUsersList);
+        withOtherUsersList.add(
+                createBatteryDiffEntry(
+                        currentUserId + 1,
+                        ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY,
+                        /*consumePercentage=*/ 20));
+        withOtherUsersList.add(
+                createBatteryDiffEntry(
+                        currentUserId + 2,
+                        ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
+                        /*consumePercentage=*/ 30));
+        withOtherUsersList.add(
+                createBatteryDiffEntry(
+                        currentUserId + 3,
+                        ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
+                        /*consumePercentage=*/ 40));
+
+        ConvertUtils.resolveMultiUsersData(mContext, entryMap);
+
+        assertThat(entryMap.get(0).get(0).getPercentOfTotal()).isEqualTo(50);
+        // Asserts with other users items.
+        final List<BatteryDiffEntry> entryList = entryMap.get(1);
+        assertThat(entryList).hasSize(2);
+        assertBatteryDiffEntry(
+                entryList.get(0),
+                currentUserId + 1,
+                /*uid=*/ 0,
+                ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY,
+                /*consumePercentage=*/ 20);
+        assertBatteryDiffEntry(
+                entryList.get(1),
+                BatteryUtils.UID_OTHER_USERS,
+                BatteryUtils.UID_OTHER_USERS,
+                ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
+                /*consumePercentage=*/ 70);
+    }
+
+    private BatteryDiffEntry createBatteryDiffEntry(
+            long userId, int counsumerType, double consumePercentage) {
+        final ContentValues values = new ContentValues();
+        values.put(BatteryHistEntry.KEY_USER_ID, userId);
+        values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, counsumerType);
+        final BatteryDiffEntry batteryDiffEntry =
+                new BatteryDiffEntry(
+                        mContext,
+                        /*foregroundUsageTimeInMs=*/ 0,
+                        /*backgroundUsageTimeInMs=*/ 0,
+                        /*consumePower=*/ consumePercentage,
+                        new BatteryHistEntry(values));
+        batteryDiffEntry.setTotalConsumePower(100f);
+        return batteryDiffEntry;
+    }
+
     private static BatteryHistEntry createBatteryHistEntry(
             String packageName, String appLabel, double consumePower,
             long uid, long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) {
@@ -390,6 +457,15 @@
     }
 
     private static void assertBatteryDiffEntry(
+            BatteryDiffEntry entry, long userId, long uid, int counsumerType,
+            double consumePercentage) {
+        assertThat(entry.mBatteryHistEntry.mUid).isEqualTo(uid);
+        assertThat(entry.mBatteryHistEntry.mUserId).isEqualTo(userId);
+        assertThat(entry.mBatteryHistEntry.mConsumerType).isEqualTo(counsumerType);
+        assertThat(entry.getPercentOfTotal()).isEqualTo(consumePercentage);
+    }
+
+    private static void assertBatteryDiffEntry(
             BatteryDiffEntry entry, int percentOfTotal,
             long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) {
         assertThat((int) entry.getPercentOfTotal()).isEqualTo(percentOfTotal);