Update related UI if battery is not present

This change is to update the related UI in the battery page if the
battery is not present. This includes the following updates:
1. Update the summary of battery tile in the Settings homepage
2. Replace the battery level with "Unknown"
3. Replace the summary with help message in the battery page
4. Remove the battery meter icon

Bug: 171368508
Test: verify on an issue device
Change-Id: I892e0d137143160a0bce0c11ce9265120ebb8fd4
Merged-In: I892e0d137143160a0bce0c11ce9265120ebb8fd4
diff --git a/res/layout/battery_header.xml b/res/layout/battery_header.xml
index dca0972..574d7d4 100644
--- a/res/layout/battery_header.xml
+++ b/res/layout/battery_header.xml
@@ -25,6 +25,7 @@
     style="@style/EntityHeader">
 
     <LinearLayout
+        android:id="@+id/battery_info_layout"
         android:layout_width="170dp"
         android:layout_height="wrap_content"
         android:layout_marginStart="72dp"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2e52996..d141823 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5752,6 +5752,11 @@
     <!-- Title to display the battery percentage. [CHAR LIMIT=24] -->
     <string name="battery_header_title_alternate"><xliff:g id="number" example="88">^1</xliff:g><small> <font size="20"><xliff:g id="unit" example="%">%</xliff:g></font></small></string>
 
+    <!-- Summary for top level battery tile if battery is not present. [CHAR LIMIT=NONE] -->
+    <string name="battery_missing_message">Problem reading your battery meter</string>
+    <!-- Summary to battery page if battery is not present. [CHAR LIMIT=NONE] -->
+    <string name="battery_missing_help_message">Problem reading your battery meter. Tap to <annotation id="url">learn more</annotation></string>
+
     <!-- Title for force stop dialog [CHAR LIMIT=30] -->
     <string name="dialog_stop_title">Stop app?</string>
     <!-- Message body for force stop dialog [CHAR LIMIT=NONE] -->
@@ -7272,6 +7277,8 @@
     <string name="help_uri_sim_combination_warning" translatable="false"></string>
     <!-- url for the NFC and payment settings page -->
     <string name="help_uri_nfc_and_payment_settings" translatable="false"></string>
+    <!-- url for battery page if battery is not present -->
+    <string name="help_url_battery_missing" translatable="false"></string>
 
     <!-- User account title [CHAR LIMIT=30] -->
     <string name="user_account_title">Account for content</string>
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 11a5825..bcb68ff 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -273,6 +273,15 @@
         return batteryChangedIntent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
     }
 
+    /**
+     * Return true if battery is present.
+     */
+    public static boolean isBatteryPresent(Context context) {
+        Intent batteryBroadcast = context.registerReceiver(null /* receiver */,
+                new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+        return isBatteryPresent(batteryBroadcast);
+    }
+
     public static String getBatteryPercentage(Intent batteryChangedIntent) {
         return formatPercentage(getBatteryLevel(batteryChangedIntent));
     }
diff --git a/src/com/android/settings/display/BatteryPercentagePreferenceController.java b/src/com/android/settings/display/BatteryPercentagePreferenceController.java
index e1bbbfc..945ce47 100644
--- a/src/com/android/settings/display/BatteryPercentagePreferenceController.java
+++ b/src/com/android/settings/display/BatteryPercentagePreferenceController.java
@@ -21,9 +21,11 @@
 import android.provider.Settings;
 
 import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
 import androidx.preference.SwitchPreference;
 
 import com.android.internal.R;
+import com.android.settings.Utils;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.PreferenceControllerMixin;
 
@@ -34,12 +36,27 @@
 public class BatteryPercentagePreferenceController extends BasePreferenceController implements
         PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
 
+    private Preference mPreference;
+
     public BatteryPercentagePreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
     }
 
     @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
+        if (!Utils.isBatteryPresent(mContext)) {
+            // Disable battery percentage
+            onPreferenceChange(mPreference, false /* newValue */);
+        }
+    }
+
+    @Override
     public int getAvailabilityStatus() {
+        if (!Utils.isBatteryPresent(mContext)) {
+            return CONDITIONALLY_UNAVAILABLE;
+        }
         return mContext.getResources().getBoolean(
                 R.bool.config_battery_percentage_setting_available) ? AVAILABLE
                 : UNSUPPORTED_ON_DEVICE;
diff --git a/src/com/android/settings/fuelgauge/BatteryBroadcastReceiver.java b/src/com/android/settings/fuelgauge/BatteryBroadcastReceiver.java
index 99510a2..2041543 100644
--- a/src/com/android/settings/fuelgauge/BatteryBroadcastReceiver.java
+++ b/src/com/android/settings/fuelgauge/BatteryBroadcastReceiver.java
@@ -21,6 +21,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.PowerManager;
+import android.util.Log;
 
 import androidx.annotation.IntDef;
 import androidx.annotation.VisibleForTesting;
@@ -41,6 +42,7 @@
  */
 public class BatteryBroadcastReceiver extends BroadcastReceiver {
 
+    private static final String TAG = "BatteryBroadcastRcvr";
     /**
      * Callback when the following has been changed:
      *
@@ -56,12 +58,14 @@
     @IntDef({BatteryUpdateType.MANUAL,
             BatteryUpdateType.BATTERY_LEVEL,
             BatteryUpdateType.BATTERY_SAVER,
-            BatteryUpdateType.BATTERY_STATUS})
+            BatteryUpdateType.BATTERY_STATUS,
+            BatteryUpdateType.BATTERY_NOT_PRESENT})
     public @interface BatteryUpdateType {
         int MANUAL = 0;
         int BATTERY_LEVEL = 1;
         int BATTERY_SAVER = 2;
         int BATTERY_STATUS = 3;
+        int BATTERY_NOT_PRESENT = 4;
     }
 
     @VisibleForTesting
@@ -101,9 +105,11 @@
         if (intent != null && mBatteryListener != null) {
             if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
                 final String batteryLevel = Utils.getBatteryPercentage(intent);
-                final String batteryStatus = Utils.getBatteryStatus(
-                        mContext, intent);
-                if (forceUpdate) {
+                final String batteryStatus = Utils.getBatteryStatus(mContext, intent);
+                if (!Utils.isBatteryPresent(intent)) {
+                    Log.w(TAG, "Problem reading the battery meter.");
+                    mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_NOT_PRESENT);
+                } else if (forceUpdate) {
                     mBatteryListener.onBatteryChanged(BatteryUpdateType.MANUAL);
                 } else if(!batteryLevel.equals(mBatteryLevel)) {
                     mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_LEVEL);
diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
index 468d8c5..7b910a1 100644
--- a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
@@ -25,6 +25,10 @@
 import android.os.BatteryManager;
 import android.os.PowerManager;
 import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import androidx.annotation.VisibleForTesting;
@@ -35,7 +39,9 @@
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.utils.AnnotationSpan;
 import com.android.settings.widget.EntityHeaderController;
+import com.android.settingslib.HelpUtils;
 import com.android.settingslib.Utils;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -49,6 +55,7 @@
         implements PreferenceControllerMixin, LifecycleObserver, OnStart {
     @VisibleForTesting
     static final String KEY_BATTERY_HEADER = "battery_header";
+    private static final String ANNOTATION_URL = "url";
 
     @VisibleForTesting
     BatteryStatusFeatureProvider mBatteryStatusFeatureProvider;
@@ -94,7 +101,11 @@
         mBatteryPercentText = mBatteryLayoutPref.findViewById(R.id.battery_percent);
         mSummary1 = mBatteryLayoutPref.findViewById(R.id.summary1);
 
-        quickUpdateHeaderPreference();
+        if (com.android.settings.Utils.isBatteryPresent(mContext)) {
+            quickUpdateHeaderPreference();
+        } else {
+            showHelpMessage();
+        }
     }
 
     @Override
@@ -146,6 +157,32 @@
         mBatteryPercentText.setText(formatBatteryPercentageText(batteryLevel));
     }
 
+    @VisibleForTesting
+    void showHelpMessage() {
+        final LinearLayout batteryInfoLayout =
+                mBatteryLayoutPref.findViewById(R.id.battery_info_layout);
+        // Remove battery meter icon
+        mBatteryMeterView.setVisibility(View.GONE);
+        // Update the width of battery info layout
+        final ViewGroup.LayoutParams params = batteryInfoLayout.getLayoutParams();
+        params.width = LinearLayout.LayoutParams.WRAP_CONTENT;
+        batteryInfoLayout.setLayoutParams(params);
+        mBatteryPercentText.setText(mContext.getText(R.string.unknown));
+        // Add linkable text for learn more
+        final Intent helpIntent = HelpUtils.getHelpIntent(mContext,
+                mContext.getString(R.string.help_url_battery_missing),
+                mContext.getClass().getName());
+        final AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan
+                .LinkInfo(mContext, ANNOTATION_URL, helpIntent);
+        if (linkInfo.isActionable()) {
+            mSummary1.setMovementMethod(LinkMovementMethod.getInstance());
+            mSummary1.setText(AnnotationSpan
+                    .linkify(mContext.getText(R.string.battery_missing_help_message), linkInfo));
+        } else {
+            mSummary1.setText(mContext.getText(R.string.battery_missing_message));
+        }
+    }
+
     private CharSequence formatBatteryPercentageText(int batteryLevel) {
         return TextUtils.expandTemplate(mContext.getText(R.string.battery_header_title_alternate),
                 NumberFormat.getIntegerInstance().format(batteryLevel));
diff --git a/src/com/android/settings/fuelgauge/PowerUsageBase.java b/src/com/android/settings/fuelgauge/PowerUsageBase.java
index 98b62d9..3a5ed6c 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageBase.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageBase.java
@@ -44,6 +44,7 @@
     protected BatteryStatsHelper mStatsHelper;
     protected UserManager mUm;
     private BatteryBroadcastReceiver mBatteryBroadcastReceiver;
+    protected boolean mIsBatteryPresent = true;
 
     @Override
     public void onAttach(Activity activity) {
@@ -60,6 +61,9 @@
 
         mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(getContext());
         mBatteryBroadcastReceiver.setBatteryChangedListener(type -> {
+            if (type == BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_NOT_PRESENT) {
+                mIsBatteryPresent = false;
+            }
             restartBatteryStatsLoader(type);
         });
     }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 3a5f0ba..57949db 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -56,8 +56,8 @@
 import java.util.List;
 
 /**
- * Displays a list of apps and subsystems that consume power, ordered by how much power was
- * consumed since the last time it was unplugged.
+ * Displays a list of apps and subsystems that consume power, ordered by how much power was consumed
+ * since the last time it was unplugged.
  */
 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
 public class PowerUsageSummary extends PowerUsageBase implements OnLongClickListener,
@@ -220,7 +220,9 @@
                 KEY_TIME_SINCE_LAST_FULL_CHARGE);
         mBatteryUtils = BatteryUtils.getInstance(getContext());
 
-        restartBatteryInfoLoader();
+        if (Utils.isBatteryPresent(getContext())) {
+            restartBatteryInfoLoader();
+        }
         mBatteryTipPreferenceController.restoreInstanceState(icicle);
         updateBatteryTipFlag(icicle);
     }
@@ -287,6 +289,10 @@
         if (context == null) {
             return;
         }
+        // Skip refreshing UI if battery is not present.
+        if (!mIsBatteryPresent) {
+            return;
+        }
 
         // Skip BatteryTipLoader if device is rotated or only battery level change
         if (mNeedUpdateBatteryTip
@@ -295,7 +301,6 @@
         } else {
             mNeedUpdateBatteryTip = true;
         }
-
         // reload BatteryInfo and updateUI
         restartBatteryInfoLoader();
         updateLastFullChargePreference();
@@ -354,6 +359,10 @@
         if (getContext() == null) {
             return;
         }
+        // Skip restartBatteryInfoLoader if battery is not present.
+        if (!mIsBatteryPresent) {
+            return;
+        }
         getLoaderManager().restartLoader(BATTERY_INFO_LOADER, Bundle.EMPTY,
                 mBatteryInfoLoaderCallbacks);
         if (mPowerFeatureProvider.isEstimateDebugEnabled()) {
@@ -378,7 +387,10 @@
     @Override
     protected void restartBatteryStatsLoader(@BatteryUpdateType int refreshType) {
         super.restartBatteryStatsLoader(refreshType);
-        mBatteryHeaderPreferenceController.quickUpdateHeaderPreference();
+        // Update battery header if battery is present.
+        if (mIsBatteryPresent) {
+            mBatteryHeaderPreferenceController.quickUpdateHeaderPreference();
+        }
     }
 
     @Override
@@ -392,7 +404,6 @@
         restartBatteryTipLoader();
     }
 
-
     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider(R.xml.power_usage_summary);
 }
diff --git a/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java b/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java
index 88fd1ce..e428d49 100644
--- a/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
@@ -30,6 +31,8 @@
 public class TopLevelBatteryPreferenceController extends BasePreferenceController implements
         LifecycleObserver, OnStart, OnStop {
 
+    @VisibleForTesting
+    boolean mIsBatteryPresent = true;
     private final BatteryBroadcastReceiver mBatteryBroadcastReceiver;
     private Preference mPreference;
     private BatteryInfo mBatteryInfo;
@@ -38,6 +41,9 @@
         super(context, preferenceKey);
         mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(mContext);
         mBatteryBroadcastReceiver.setBatteryChangedListener(type -> {
+            if (type == BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_NOT_PRESENT) {
+                mIsBatteryPresent = false;
+            }
             BatteryInfo.getBatteryInfo(mContext, info -> {
                 mBatteryInfo = info;
                 updateState(mPreference);
@@ -69,6 +75,10 @@
 
     @Override
     public CharSequence getSummary() {
+        // Display help message if battery is not present.
+        if (!mIsBatteryPresent) {
+            return mContext.getText(R.string.battery_missing_message);
+        }
         return getDashboardLabel(mContext, mBatteryInfo);
     }
 
diff --git a/tests/robotests/src/com/android/settings/display/BatteryPercentagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/BatteryPercentagePreferenceControllerTest.java
index bbc8faf..c84127b 100644
--- a/tests/robotests/src/com/android/settings/display/BatteryPercentagePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/BatteryPercentagePreferenceControllerTest.java
@@ -18,18 +18,25 @@
 
 import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
 
+import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
 import android.provider.Settings;
 
+import com.android.settings.testutils.shadow.ShadowUtils;
+
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowUtils.class)
 public class BatteryPercentagePreferenceControllerTest {
 
     private static final String PREF_KEY = "battery_percentage";
@@ -43,6 +50,11 @@
         mController = new BatteryPercentagePreferenceController(mContext, PREF_KEY);
     }
 
+    @After
+    public void tearDown() {
+        ShadowUtils.reset();
+    }
+
     private int getPercentageSetting() {
         return Settings.System.getInt(mContext.getContentResolver(), SHOW_BATTERY_PERCENT, 0);
     }
@@ -60,4 +72,11 @@
         final int isOn = getPercentageSetting();
         assertThat(isOn).isEqualTo(0);
     }
+
+    @Test
+    public void getAvailabilityStatus_batteryNotPresent_shouldReturnConditionallyUnavailable() {
+        ShadowUtils.setIsBatteryPresent(false);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBroadcastReceiverTest.java
index 4d5f1a0..742daf2 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBroadcastReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBroadcastReceiverTest.java
@@ -95,6 +95,19 @@
             BatteryFixSliceTest.ShadowBatteryStatsHelperLoader.class,
             BatteryFixSliceTest.ShadowBatteryTipLoader.class
     })
+    public void onReceive_batteryNotPresent_shouldShowHelpMessage() {
+        mChargingIntent.putExtra(BatteryManager.EXTRA_PRESENT, false);
+
+        mBatteryBroadcastReceiver.onReceive(mContext, mChargingIntent);
+
+        verify(mBatteryListener).onBatteryChanged(BatteryUpdateType.BATTERY_NOT_PRESENT);
+    }
+
+    @Test
+    @Config(shadows = {
+            BatteryFixSliceTest.ShadowBatteryStatsHelperLoader.class,
+            BatteryFixSliceTest.ShadowBatteryTipLoader.class
+    })
     public void testOnReceive_powerSaveModeChanged_listenerInvoked() {
         mBatteryBroadcastReceiver.onReceive(mContext,
                 new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
index 63e8a80..a6cf653 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
@@ -44,6 +44,7 @@
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
+import com.android.settings.testutils.shadow.ShadowUtils;
 import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.widget.LayoutPreference;
@@ -61,7 +62,7 @@
 import org.robolectric.shadows.ShadowPowerManager;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(shadows = ShadowEntityHeaderController.class)
+@Config(shadows = {ShadowEntityHeaderController.class, ShadowUtils.class})
 public class BatteryHeaderPreferenceControllerTest {
 
     private static final String PREF_KEY = "battery_header";
@@ -116,7 +117,7 @@
 
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
 
-        mController = new BatteryHeaderPreferenceController(mContext, PREF_KEY);
+        mController = spy(new BatteryHeaderPreferenceController(mContext, PREF_KEY));
         mLifecycle.addObserver(mController);
         mController.setActivity(mActivity);
         mController.setFragment(mPreferenceFragment);
@@ -129,6 +130,7 @@
     @After
     public void tearDown() {
         ShadowEntityHeaderController.reset();
+        ShadowUtils.reset();
     }
 
     @Test
@@ -214,4 +216,13 @@
         assertThat(mController.getAvailabilityStatus()).isEqualTo(
                 BasePreferenceController.AVAILABLE_UNSEARCHABLE);
     }
+
+    @Test
+    public void displayPreference_batteryNotPresent_shouldShowHelpMessage() {
+        ShadowUtils.setIsBatteryPresent(false);
+
+        mController.displayPreference(mPreferenceScreen);
+
+        verify(mController).showHelpMessage();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 7839e1a..49f7502 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -45,7 +45,6 @@
 import android.view.View;
 import android.widget.TextView;
 
-import androidx.annotation.VisibleForTesting;
 import androidx.loader.app.LoaderManager;
 import androidx.preference.PreferenceScreen;
 
@@ -56,6 +55,7 @@
 import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.XmlTestUtils;
+import com.android.settings.testutils.shadow.ShadowUtils;
 import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
 import com.android.settingslib.widget.LayoutPreference;
 
@@ -72,6 +72,7 @@
 import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
 import java.util.ArrayList;
@@ -224,6 +225,7 @@
     }
 
     @Test
+    @Config(shadows = ShadowUtils.class)
     public void nonIndexableKeys_MatchPreferenceKeys() {
         final Context context = RuntimeEnvironment.application;
         final List<String> niks =
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceControllerTest.java
index 3775802..10893c9 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceControllerTest.java
@@ -24,6 +24,8 @@
 
 import android.content.Context;
 
+import com.android.settings.R;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -66,4 +68,12 @@
         info.chargeLabel = "5% - charging";
         assertThat(getDashboardLabel(mContext, info)).isEqualTo("5% - charging");
     }
+
+    @Test
+    public void getSummary_batteryNotPresent_shouldShowWarningMessage() {
+        mController.mIsBatteryPresent = false;
+
+        assertThat(mController.getSummary())
+                .isEqualTo(mContext.getString(R.string.battery_missing_message));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
index eadd33a..5a32f34 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
@@ -46,6 +46,7 @@
     private static boolean sIsSystemAlertWindowEnabled;
     private static boolean sIsVoiceCapable;
     private static ArraySet<String> sResultLinks = new ArraySet<>();
+    private static boolean sIsBatteryPresent;
 
     @Implementation
     protected static int enforceSameOwner(Context context, int userId) {
@@ -67,6 +68,7 @@
         sIsDemoUser = false;
         sIsVoiceCapable = false;
         sResultLinks = new ArraySet<>();
+        sIsBatteryPresent = true;
     }
 
     public static void setIsDemoUser(boolean isDemoUser) {
@@ -155,4 +157,13 @@
     public static void setHandledDomains(ArraySet<String> links) {
         sResultLinks = links;
     }
+
+    @Implementation
+    protected static boolean isBatteryPresent(Context context) {
+        return sIsBatteryPresent;
+    }
+
+    public static void setIsBatteryPresent(boolean isBatteryPresent) {
+        sIsBatteryPresent = isBatteryPresent;
+    }
 }