Merge "Fix Sound Amplifier does not have 'Open XXX' button" into sc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index b5214e6..5d6fdda 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -141,7 +141,7 @@
 
         <activity android:name=".network.telephony.MobileNetworkActivity"
                   android:label="@string/network_settings_title"
-                  android:theme="@style/Theme.Settings.Home"
+                  android:theme="@style/Theme.SubSettings"
                   android:exported="true"
                   android:launchMode="singleTask">
             <intent-filter android:priority="1">
@@ -418,6 +418,7 @@
                 android:label="@string/apn_settings"
                 android:launchMode="singleTask"
                 android:exported="true"
+                android:theme="@style/Theme.SubSettings"
                 android:configChanges="orientation|keyboardHidden|screenSize">
             <intent-filter android:priority="1">
                 <action android:name="android.settings.APN_SETTINGS" />
@@ -2060,6 +2061,7 @@
         <activity android:name="Settings$ApnEditorActivity"
                 android:configChanges="orientation|keyboardHidden|screenSize"
                 android:exported="true"
+                android:theme="@style/Theme.SubSettings"
                 android:label="@string/apn_edit">
             <intent-filter>
                 <action android:name="android.intent.action.VIEW" />
@@ -3000,6 +3002,7 @@
         <activity
             android:name="Settings$WifiCallingSettingsActivity"
             android:exported="true"
+            android:theme="@style/Theme.SubSettings"
             android:label="@string/wifi_calling_settings_title">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/res/layout/loading_container.xml b/res/layout/loading_container.xml
index eb67044..80cbbf9 100644
--- a/res/layout/loading_container.xml
+++ b/res/layout/loading_container.xml
@@ -18,7 +18,7 @@
     android:id="@+id/loading_container"
     android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
+    android:layout_height="450dp"
     android:visibility="gone"
     android:gravity="center">
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 742ed97..ac239f6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5121,7 +5121,7 @@
     <!-- Title for the accessibility preference category of interaction control services and settings. [CHAR LIMIT=50] -->
     <string name="interaction_control_category_title">Interaction controls</string>
     <!-- Title for the accessibility tap assistance page. [CHAR LIMIT=50] -->
-    <string name="accessibility_tap_assistance_title">Tap assistance</string>
+    <string name="accessibility_tap_assistance_title">Timing controls</string>
     <!-- Title for the accessibility system controls page. [CHAR LIMIT=50] -->
     <string name="accessibility_system_controls_title">System controls</string>
     <!-- Title for the accessibility preference category of services downloaded by the user. [CHAR LIMIT=50] -->
@@ -6088,7 +6088,7 @@
     <string name="restricted_app_time_summary">Restricted <xliff:g id="time" example="5 days ago">%1$s</xliff:g></string>
 
     <!-- Footer message for restrict app details page -->
-    <string name="restricted_app_detail_footer">These apps have been using battery in the background. Restricted apps may not work properly and notifications may be delayed.</string>
+    <string name="restricted_app_detail_footer">These apps are restricted from background battery usage. They may not work as expected, and notifications may be delayed.</string>
 
     <!-- Title for auto restriction toggle -->
     <string name="battery_auto_restriction_title">Use Battery Manager</string>
@@ -6312,7 +6312,7 @@
     <!-- Title for usage time that full charge lasts. [CHAR LIMIT=60] -->
     <string name="battery_full_charge_last">Full charge lasts about</string>
     <!-- Description for text in battery footer. [CHAR LIMIT=NONE] -->
-    <string name="battery_footer_summary">Battery usage data is approximate and can change based on usage</string>
+    <string name="battery_footer_summary">Battery usage data is approximate and can change based on usage.</string>
     <!-- Title for text that shows the amount of time an app has been running while in the foreground. [CHAR LIMIT=80] -->
     <string name="battery_detail_foreground">While in active use</string>
     <!-- Title for text that shows the amount of time an app has been running while in the background. [CHAR LIMIT=80] -->
@@ -6417,11 +6417,11 @@
     <string name="battery_saver_sticky_title_new">Turn off when charged</string>
 
     <!-- Battery Saver: Description for sticky battery saver preference [CHAR_LIMIT=NONE] -->
-    <string name="battery_saver_sticky_description_new" product="default">Battery Saver turns off when your phone charges above <xliff:g id="percent" example="90%">%1$s</xliff:g></string>
+    <string name="battery_saver_sticky_description_new" product="default">Battery Saver turns off when your phone charges above <xliff:g id="number" example="88">^1</xliff:g><xliff:g id="unit" example="%">%</xliff:g></string>
     <!-- Battery Saver: Description for sticky battery saver preference [CHAR_LIMIT=NONE] -->
-    <string name="battery_saver_sticky_description_new" product="tablet">Battery Saver turns off when your tablet charges above <xliff:g id="percent" example="90%">%1$s</xliff:g></string>
+    <string name="battery_saver_sticky_description_new" product="tablet">Battery Saver turns off when your tablet charges above <xliff:g id="number" example="88">^1</xliff:g><xliff:g id="unit" example="%">%</xliff:g></string>
     <!-- Battery Saver: Description for sticky battery saver preference [CHAR_LIMIT=NONE] -->
-    <string name="battery_saver_sticky_description_new" product="device">Battery Saver turns off when your device charges above <xliff:g id="percent" example="90%">%1$s</xliff:g></string>
+    <string name="battery_saver_sticky_description_new" product="device">Battery Saver turns off when your device charges above <xliff:g id="number" example="88">^1</xliff:g><xliff:g id="unit" example="%">%</xliff:g></string>
 
     <!-- Battery saver: Label for seekbar to change battery saver threshold [CHAR_LIMIT=40] -->
     <string name="battery_saver_seekbar_title"><xliff:g id="percent">%1$s</xliff:g></string>
diff --git a/res/xml/connected_devices.xml b/res/xml/connected_devices.xml
index e7e3c2c..75878f9 100644
--- a/res/xml/connected_devices.xml
+++ b/res/xml/connected_devices.xml
@@ -40,7 +40,6 @@
         android:key="add_bt_devices"
         android:title="@string/bluetooth_pairing_pref_title"
         android:icon="@drawable/ic_add_24dp"
-        android:summary="@string/connected_device_add_device_summary"
         android:fragment="com.android.settings.bluetooth.BluetoothPairingDetail"
         settings:allowDividerAbove="true"
         settings:keywords="@string/keywords_add_bt_device"
@@ -48,6 +47,18 @@
         settings:useAdminDisabledSummary="true"
         settings:controller="com.android.settings.connecteddevice.AddDevicePreferenceController"/>
 
+    <com.android.settingslib.RestrictedPreference
+        android:key="add_bt_devices_summary"
+        android:title="@string/bluetooth_pairing_pref_title"
+        android:icon="@drawable/ic_add_24dp"
+        android:summary="@string/connected_device_add_device_summary"
+        android:fragment="com.android.settings.bluetooth.BluetoothPairingDetail"
+        settings:allowDividerAbove="true"
+        settings:keywords="@string/keywords_add_bt_device"
+        settings:userRestriction="no_config_bluetooth"
+        settings:useAdminDisabledSummary="true"
+        settings:controller="com.android.settings.connecteddevice.AddDeviceSummaryPreferenceController"/>
+
     <PreferenceCategory
         android:key="previously_connected_devices"
         android:title="@string/connected_device_previously_connected_title"
diff --git a/src/com/android/settings/biometrics/combination/BiometricFaceStatusPreferenceController.java b/src/com/android/settings/biometrics/combination/BiometricFaceStatusPreferenceController.java
index e4b210e..047a2df 100644
--- a/src/com/android/settings/biometrics/combination/BiometricFaceStatusPreferenceController.java
+++ b/src/com/android/settings/biometrics/combination/BiometricFaceStatusPreferenceController.java
@@ -32,6 +32,6 @@
 
     @Override
     protected boolean isDeviceSupported() {
-        return Utils.hasFaceHardware(mContext);
+        return Utils.isMultipleBiometricsSupported(mContext) && Utils.hasFaceHardware(mContext);
     }
 }
diff --git a/src/com/android/settings/biometrics/combination/BiometricFingerprintStatusPreferenceController.java b/src/com/android/settings/biometrics/combination/BiometricFingerprintStatusPreferenceController.java
index fd742ff..72a19c7 100644
--- a/src/com/android/settings/biometrics/combination/BiometricFingerprintStatusPreferenceController.java
+++ b/src/com/android/settings/biometrics/combination/BiometricFingerprintStatusPreferenceController.java
@@ -33,6 +33,7 @@
 
     @Override
     protected boolean isDeviceSupported() {
-        return Utils.hasFingerprintHardware(mContext);
+        return Utils.isMultipleBiometricsSupported(mContext)
+                && Utils.hasFingerprintHardware(mContext);
     }
 }
diff --git a/src/com/android/settings/biometrics/combination/BiometricSettingsAppPreferenceController.java b/src/com/android/settings/biometrics/combination/BiometricSettingsAppPreferenceController.java
index 9107e1b..861ff27 100644
--- a/src/com/android/settings/biometrics/combination/BiometricSettingsAppPreferenceController.java
+++ b/src/com/android/settings/biometrics/combination/BiometricSettingsAppPreferenceController.java
@@ -69,6 +69,9 @@
 
     @Override
     public int getAvailabilityStatus() {
+        if (!Utils.isMultipleBiometricsSupported(mContext)) {
+            return UNSUPPORTED_ON_DEVICE;
+        }
         if (mFaceManager == null || mFingerprintManager == null) {
             return AVAILABLE_UNSEARCHABLE;
         }
diff --git a/src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceController.java b/src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceController.java
index 263134a..6fe651f 100644
--- a/src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceController.java
+++ b/src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceController.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.provider.Settings;
 
+import com.android.settings.Utils;
 import com.android.settings.core.TogglePreferenceController;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -62,6 +63,9 @@
 
     @Override
     public int getAvailabilityStatus() {
+        if (!Utils.isMultipleBiometricsSupported(mContext)) {
+            return UNSUPPORTED_ON_DEVICE;
+        }
         return getRestrictingAdmin() != null ? DISABLED_FOR_USER : AVAILABLE;
     }
 }
diff --git a/src/com/android/settings/connecteddevice/AddDevicePreferenceController.java b/src/com/android/settings/connecteddevice/AddDevicePreferenceController.java
index 9706c17..6fdc7e5 100644
--- a/src/com/android/settings/connecteddevice/AddDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/AddDevicePreferenceController.java
@@ -33,7 +33,8 @@
 
 /**
  * Controller to maintain the {@link androidx.preference.Preference} for add
- * device. It monitor Bluetooth's status(on/off) and decide if need to show summary or not.
+ * device without summary at beginning. It monitor Bluetooth's status(on/off) and decide if need
+ * to show summary or not.
  */
 public class AddDevicePreferenceController extends BasePreferenceController
         implements LifecycleObserver, OnStart, OnStop {
@@ -46,7 +47,8 @@
         }
     };
     private IntentFilter mIntentFilter;
-    private BluetoothAdapter mBluetoothAdapter;
+
+    protected BluetoothAdapter mBluetoothAdapter;
 
     public AddDevicePreferenceController(Context context, String key) {
         super(context, key);
@@ -57,6 +59,7 @@
     @Override
     public void onStart() {
         mContext.registerReceiver(mReceiver, mIntentFilter);
+        updateState(mPreference);
     }
 
     @Override
@@ -75,17 +78,22 @@
     @Override
     public int getAvailabilityStatus() {
         return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
+                && isBluetoothEnabled()
                 ? AVAILABLE
                 : UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
     public CharSequence getSummary() {
-        return mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()
+        return isBluetoothEnabled()
                 ? ""
                 : mContext.getString(R.string.connected_device_add_device_summary);
     }
 
+    protected boolean isBluetoothEnabled() {
+        return mBluetoothAdapter != null && mBluetoothAdapter.isEnabled();
+    }
+
     void updateState() {
         updateState(mPreference);
     }
diff --git a/src/com/android/settings/connecteddevice/AddDeviceSummaryPreferenceController.java b/src/com/android/settings/connecteddevice/AddDeviceSummaryPreferenceController.java
new file mode 100644
index 0000000..4513473
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/AddDeviceSummaryPreferenceController.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 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.settings.connecteddevice;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+/**
+ * Controller to maintain the {@link androidx.preference.Preference} for add
+ * device with summary at beginning. It monitor Bluetooth's status(on/off) and decide if need
+ * to show summary or not.
+ */
+public class AddDeviceSummaryPreferenceController extends AddDevicePreferenceController {
+
+    public AddDeviceSummaryPreferenceController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
+                && !isBluetoothEnabled()
+                ? AVAILABLE
+                : UNSUPPORTED_ON_DEVICE;
+    }
+}
diff --git a/src/com/android/settings/display/AdaptiveSleepPreferenceController.java b/src/com/android/settings/display/AdaptiveSleepPreferenceController.java
index 7fbb01e..8f61683 100644
--- a/src/com/android/settings/display/AdaptiveSleepPreferenceController.java
+++ b/src/com/android/settings/display/AdaptiveSleepPreferenceController.java
@@ -73,7 +73,6 @@
      * Adds the controlled preference to the provided preference screen.
      */
     public void addToScreen(PreferenceScreen screen) {
-        initializePreference();
         updatePreference();
         screen.addPreference(mPreference);
     }
@@ -82,6 +81,7 @@
      * Updates the appearance of the preference.
      */
     public void updatePreference() {
+        initializePreference();
         final EnforcedAdmin enforcedAdmin = mRestrictionUtils.checkIfRestrictionEnforced(mContext,
                 UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT);
         if (enforcedAdmin != null) {
@@ -93,19 +93,22 @@
 
     @VisibleForTesting
     void initializePreference() {
-        mPreference = new RestrictedSwitchPreference(mContext);
-        mPreference.setTitle(R.string.adaptive_sleep_title);
-        mPreference.setSummary(R.string.adaptive_sleep_description);
-        mPreference.setChecked(isChecked());
-        mPreference.setKey(PREFERENCE_KEY);
-        mPreference.setOnPreferenceChangeListener((preference, value) -> {
-            final boolean isChecked = (Boolean) value;
-            mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_SCREEN_ATTENTION_CHANGED,
-                    isChecked);
-            Settings.Secure.putInt(mContext.getContentResolver(),
-                    Settings.Secure.ADAPTIVE_SLEEP, isChecked ? 1 : DEFAULT_VALUE);
-            return true;
-        });
+        if (mPreference == null) {
+            mPreference = new RestrictedSwitchPreference(mContext);
+            mPreference.setTitle(R.string.adaptive_sleep_title);
+            mPreference.setSummary(R.string.adaptive_sleep_description);
+            mPreference.setChecked(isChecked());
+            mPreference.setKey(PREFERENCE_KEY);
+            mPreference.setOnPreferenceChangeListener((preference, value) -> {
+                final boolean isChecked = (Boolean) value;
+                mMetricsFeatureProvider.action(mContext,
+                        SettingsEnums.ACTION_SCREEN_ATTENTION_CHANGED,
+                        isChecked);
+                Settings.Secure.putInt(mContext.getContentResolver(),
+                        Settings.Secure.ADAPTIVE_SLEEP, isChecked ? 1 : DEFAULT_VALUE);
+                return true;
+            });
+        }
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/fuelgauge/BatteryChartView.java b/src/com/android/settings/fuelgauge/BatteryChartView.java
index 8e83cb9..e2e7f8f 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartView.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartView.java
@@ -111,6 +111,10 @@
 
     /** Sets all levels value to draw the trapezoid shape */
     public void setLevels(int[] levels) {
+        if (levels == null) {
+            mLevels = null;
+            return;
+        }
         // We should provide trapezoid count + 1 data to draw all trapezoids.
         mLevels = levels.length == mTrapezoidCount + 1 ? levels : null;
         setClickable(false);
diff --git a/src/com/android/settings/fuelgauge/BatteryHistEntry.java b/src/com/android/settings/fuelgauge/BatteryHistEntry.java
index 6130fff..d83d814 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistEntry.java
@@ -16,6 +16,7 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.os.BatteryConsumer;
+import android.util.Log;
 
 import java.time.Duration;
 
@@ -310,6 +311,14 @@
             lowerHistEntry == null ? 0 : lowerHistEntry.mBackgroundUsageTimeInMs,
             upperHistEntry.mBackgroundUsageTimeInMs,
             ratio);
+        // Checks whether there is any abnoaml cases!
+        if (upperHistEntry.mConsumePower < consumePower
+                || upperHistEntry.mForegroundUsageTimeInMs < foregroundUsageTimeInMs
+                || upperHistEntry.mBackgroundUsageTimeInMs < backgroundUsageTimeInMs) {
+            Log.w(TAG, String.format(
+                "abnormal interpolation:\nupper:%s\nlower:%s",
+                upperHistEntry, lowerHistEntry));
+        }
         final double batteryLevel =
             lowerHistEntry == null
                 ? upperHistEntry.mBatteryLevel
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java
index 7d4bdac..6754245 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java
@@ -4,6 +4,8 @@
 import android.icu.text.NumberFormat;
 import android.provider.Settings;
 import android.provider.Settings.Global;
+import android.text.TextUtils;
+
 import androidx.preference.Preference;
 import androidx.preference.SwitchPreference;
 import com.android.settings.R;
@@ -37,13 +39,11 @@
     @Override
     protected void refreshSummary(Preference preference) {
         super.refreshSummary(preference);
-        final double stickyShutoffLevel = Settings.Global.getInt(
+        final int stickyShutoffLevel = Settings.Global.getInt(
             mContext.getContentResolver(), Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL, 90);
-        final String percentage = NumberFormat
-            .getPercentInstance()
-            .format(stickyShutoffLevel / 100.0);
-        preference.setSummary(
-            mContext.getString(R.string.battery_saver_sticky_description_new, percentage));
+        preference.setSummary(TextUtils.expandTemplate(
+                mContext.getString(R.string.battery_saver_sticky_description_new),
+                NumberFormat.getIntegerInstance().format(stickyShutoffLevel)));
     }
 
     @Override
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AddDevicePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AddDevicePreferenceControllerTest.java
index e2b1270..c3841c9 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/AddDevicePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/AddDevicePreferenceControllerTest.java
@@ -79,6 +79,7 @@
         String key = mAddDevicePreferenceController.getPreferenceKey();
         mAddDevicePreference = new RestrictedPreference(mContext);
         mAddDevicePreference.setKey(key);
+        when(mBluetoothAdapter.isEnabled()).thenReturn(true);
         when(mScreen.findPreference(key)).thenReturn(mAddDevicePreference);
         mAddDevicePreferenceController.displayPreference(mScreen);
     }
@@ -128,4 +129,13 @@
         assertThat(mAddDevicePreferenceController.getAvailabilityStatus())
                 .isEqualTo(AVAILABLE);
     }
+
+    @Test
+    public void getAvailabilityStatus_bluetoothIsDisabled_unSupported() {
+        mPackageManager.setSystemFeature(PackageManager.FEATURE_BLUETOOTH, true);
+        when(mBluetoothAdapter.isEnabled()).thenReturn(false);
+
+        assertThat(mAddDevicePreferenceController.getAvailabilityStatus())
+                .isEqualTo(UNSUPPORTED_ON_DEVICE);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AddDeviceSummaryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AddDeviceSummaryPreferenceControllerTest.java
new file mode 100644
index 0000000..e134a16
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/AddDeviceSummaryPreferenceControllerTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2021 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.settings.connecteddevice;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.text.TextUtils;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settingslib.RestrictedPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplicationPackageManager;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowApplicationPackageManager.class)
+public class AddDeviceSummaryPreferenceControllerTest {
+
+    @Mock
+    private PreferenceScreen mScreen;
+    @Mock
+    private BluetoothAdapter mBluetoothAdapter;
+
+    private Context mContext;
+    private AddDeviceSummaryPreferenceController mAddDeviceSummaryPreferenceController;
+    private RestrictedPreference mAddDevicePreference;
+    private ShadowApplicationPackageManager mPackageManager;
+
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = RuntimeEnvironment.application;
+        mPackageManager = (ShadowApplicationPackageManager) Shadows.shadowOf(
+                mContext.getPackageManager());
+        mPackageManager.setSystemFeature(PackageManager.FEATURE_BLUETOOTH, true);
+
+        mAddDeviceSummaryPreferenceController = new AddDeviceSummaryPreferenceController(mContext,
+                "add_bt_devices");
+        ReflectionHelpers.setField(mAddDeviceSummaryPreferenceController,
+                "mBluetoothAdapter", mBluetoothAdapter);
+
+        String key = mAddDeviceSummaryPreferenceController.getPreferenceKey();
+        mAddDevicePreference = new RestrictedPreference(mContext);
+        mAddDevicePreference.setKey(key);
+        when(mScreen.findPreference(key)).thenReturn(mAddDevicePreference);
+        when(mBluetoothAdapter.isEnabled()).thenReturn(false);
+        mAddDeviceSummaryPreferenceController.displayPreference(mScreen);
+    }
+
+    @Test
+    public void getSummary_btOnThenOff_summaryShouldBeShown() {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(true);
+
+        mAddDeviceSummaryPreferenceController.updateState();
+
+        assertTrue(TextUtils.isEmpty(mAddDevicePreference.getSummary()));
+
+        Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
+        intent.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
+        BroadcastReceiver receiver = ReflectionHelpers.getField(
+                mAddDeviceSummaryPreferenceController, "mReceiver");
+        when(mBluetoothAdapter.isEnabled()).thenReturn(false);
+
+        receiver.onReceive(mContext, intent);
+
+        assertThat(mAddDevicePreference.getSummary()).isEqualTo(
+                mContext.getString(R.string.connected_device_add_device_summary));
+    }
+
+    @Test
+    public void getSummary_btOffThenOn_summaryShouldNotBeShown() {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(false);
+
+        mAddDeviceSummaryPreferenceController.updateState();
+
+        assertThat(mAddDevicePreference.getSummary()).isEqualTo(
+                mContext.getString(R.string.connected_device_add_device_summary));
+
+        Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
+        intent.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_ON);
+        BroadcastReceiver receiver = ReflectionHelpers.getField(
+                mAddDeviceSummaryPreferenceController, "mReceiver");
+        when(mBluetoothAdapter.isEnabled()).thenReturn(true);
+
+        receiver.onReceive(mContext, intent);
+
+        assertTrue(TextUtils.isEmpty(mAddDevicePreference.getSummary()));
+    }
+
+    @Test
+    public void getAvailabilityStatus_notHaveBluetoothFeature_unSupported() {
+        mPackageManager.setSystemFeature(PackageManager.FEATURE_BLUETOOTH, false);
+
+        assertThat(mAddDeviceSummaryPreferenceController.getAvailabilityStatus())
+                .isEqualTo(UNSUPPORTED_ON_DEVICE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_haveBluetoothFeature_supported() {
+        mPackageManager.setSystemFeature(PackageManager.FEATURE_BLUETOOTH, true);
+
+        assertThat(mAddDeviceSummaryPreferenceController.getAvailabilityStatus())
+                .isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_bluetoothIsEnabled_unSupported() {
+        mPackageManager.setSystemFeature(PackageManager.FEATURE_BLUETOOTH, true);
+        when(mBluetoothAdapter.isEnabled()).thenReturn(true);
+
+        assertThat(mAddDeviceSummaryPreferenceController.getAvailabilityStatus())
+                .isEqualTo(UNSUPPORTED_ON_DEVICE);
+    }
+}