From 76611379814d786a7319c7231ba90e0b4365f0c2 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Wed, 9 Aug 2017 09:57:27 -0700 Subject: [PATCH] Add battery indicator to bluetooth icon This cl change util method in bluetooth package to return drawable instead of resId. If the bt device has battery level, then method return customized layerDrawable, otherwise return a simple drawable created from resId. Bug: 63393322 Test: RunSettingsRoboTests Change-Id: Ib21822eafda0e8570212ce5cb070478e4f4876a2 Merged-In: Ib21822eafda0e8570212ce5cb070478e4f4876a2 --- res/layout-sw320dp/settings_entity_header.xml | 2 +- .../BluetoothDetailsHeaderController.java | 8 ++-- .../bluetooth/BluetoothDevicePreference.java | 5 +- src/com/android/settings/bluetooth/Utils.java | 56 +++++++++++++++------- .../BluetoothDetailsHeaderControllerTest.java | 4 +- .../bluetooth/BluetoothDevicePreferenceTest.java | 7 ++- .../com/android/settings/bluetooth/UtilsTest.java | 31 ++++++++++-- 7 files changed, 84 insertions(+), 29 deletions(-) diff --git a/res/layout-sw320dp/settings_entity_header.xml b/res/layout-sw320dp/settings_entity_header.xml index 5cedd8dd33..951961c53e 100644 --- a/res/layout-sw320dp/settings_entity_header.xml +++ b/res/layout-sw320dp/settings_entity_header.xml @@ -38,7 +38,7 @@ android:id="@+id/entity_header_icon" android:layout_width="48dp" android:layout_height="48dp" - android:scaleType="fitXY" + android:scaleType="fitCenter" android:layout_gravity="center_horizontal" android:antialias="true" /> diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java index 5ec7c85251..147021402e 100644 --- a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java +++ b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java @@ -16,8 +16,8 @@ package com.android.settings.bluetooth; - import android.content.Context; +import android.graphics.drawable.Drawable; import android.support.v14.preference.PreferenceFragment; import android.support.v7.preference.PreferenceScreen; import android.util.Pair; @@ -51,11 +51,11 @@ public class BluetoothDetailsHeaderController extends BluetoothDetailsController } protected void setHeaderProperties() { - Pair pair = Utils.getBtClassDrawableWithDescription - (mContext.getResources(), mCachedDevice); + final Pair pair = Utils.getBtClassDrawableWithDescription + (mContext, mCachedDevice); String summaryText = mCachedDevice.getConnectionSummary(); mHeaderController.setLabel(mCachedDevice.getName()); - mHeaderController.setIcon(mContext.getDrawable(pair.first)); + mHeaderController.setIcon(pair.first); mHeaderController.setIconContentDescription(pair.second); mHeaderController.setSummary(summaryText); } diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java index a216400d8d..7b81018d26 100644 --- a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java +++ b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java @@ -21,6 +21,7 @@ import android.bluetooth.BluetoothDevice; import android.content.Context; import android.content.DialogInterface; import android.content.res.Resources; +import android.graphics.drawable.Drawable; import android.os.UserManager; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceViewHolder; @@ -120,9 +121,9 @@ public final class BluetoothDevicePreference extends GearPreference implements // Null check is done at the framework setSummary(mCachedDevice.getConnectionSummary()); - Pair pair = Utils.getBtClassDrawableWithDescription(mResources, + final Pair pair = Utils.getBtClassDrawableWithDescription(getContext(), mCachedDevice); - if (pair.first != 0) { + if (pair.first != null) { setIcon(pair.first); contentDescription = pair.second; } diff --git a/src/com/android/settings/bluetooth/Utils.java b/src/com/android/settings/bluetooth/Utils.java index 26edd84d2e..e80237ebc6 100755 --- a/src/com/android/settings/bluetooth/Utils.java +++ b/src/com/android/settings/bluetooth/Utils.java @@ -23,6 +23,9 @@ import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.DialogInterface; import android.content.res.Resources; +import android.graphics.drawable.Drawable; +import android.support.annotation.DrawableRes; +import android.support.annotation.IdRes; import android.support.annotation.VisibleForTesting; import android.util.Pair; import android.widget.Toast; @@ -36,6 +39,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothManager.BluetoothManagerCallback; import com.android.settingslib.bluetooth.LocalBluetoothProfile; import com.android.settingslib.bluetooth.Utils.ErrorListener; +import com.android.settingslib.graph.BluetoothDeviceLayerDrawable; import java.util.List; @@ -150,27 +154,31 @@ public final class Utils { } }; - static Pair getBtClassDrawableWithDescription(Resources r, + static Pair getBtClassDrawableWithDescription(Context context, CachedBluetoothDevice cachedDevice) { BluetoothClass btClass = cachedDevice.getBtClass(); + final int level = cachedDevice.getBatteryLevel(); if (btClass != null) { switch (btClass.getMajorDeviceClass()) { case BluetoothClass.Device.Major.COMPUTER: - return new Pair(R.drawable.ic_bt_laptop, - r.getString(R.string.bluetooth_talkback_computer)); + return new Pair<>(getBluetoothDrawable(context, R.drawable.ic_bt_laptop, level), + context.getString(R.string.bluetooth_talkback_computer)); case BluetoothClass.Device.Major.PHONE: - return new Pair(R.drawable.ic_bt_cellphone, - r.getString(R.string.bluetooth_talkback_phone)); + return new Pair<>( + getBluetoothDrawable(context, R.drawable.ic_bt_cellphone, level), + context.getString(R.string.bluetooth_talkback_phone)); case BluetoothClass.Device.Major.PERIPHERAL: - return new Pair(HidProfile.getHidClassDrawable(btClass), - r.getString( - R.string.bluetooth_talkback_input_peripheral)); + return new Pair<>( + getBluetoothDrawable(context, HidProfile.getHidClassDrawable(btClass), + level), + context.getString(R.string.bluetooth_talkback_input_peripheral)); case BluetoothClass.Device.Major.IMAGING: - return new Pair(R.drawable.ic_settings_print, - r.getString(R.string.bluetooth_talkback_imaging)); + return new Pair<>( + getBluetoothDrawable(context, R.drawable.ic_settings_print, level), + context.getString(R.string.bluetooth_talkback_imaging)); default: // unrecognized device class; continue @@ -181,20 +189,34 @@ public final class Utils { for (LocalBluetoothProfile profile : profiles) { int resId = profile.getDrawableResource(btClass); if (resId != 0) { - return new Pair(resId, null); + return new Pair<>(getBluetoothDrawable(context, resId, level), null); } } if (btClass != null) { if (btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) { - return new Pair(R.drawable.ic_bt_headset_hfp, - r.getString(R.string.bluetooth_talkback_headset)); + return new Pair<>( + getBluetoothDrawable(context, R.drawable.ic_bt_headset_hfp, level), + context.getString(R.string.bluetooth_talkback_headset)); } if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) { - return new Pair(R.drawable.ic_bt_headphones_a2dp, - r.getString(R.string.bluetooth_talkback_headphone)); + return new Pair<>( + getBluetoothDrawable(context, R.drawable.ic_bt_headphones_a2dp, level), + context.getString(R.string.bluetooth_talkback_headphone)); } } - return new Pair(R.drawable.ic_settings_bluetooth, - r.getString(R.string.bluetooth_talkback_bluetooth)); + return new Pair<>(getBluetoothDrawable(context, R.drawable.ic_settings_bluetooth, level), + context.getString(R.string.bluetooth_talkback_bluetooth)); + } + + @VisibleForTesting + static Drawable getBluetoothDrawable(Context context, @DrawableRes int resId, + int batteryLevel) { + if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) { + return BluetoothDeviceLayerDrawable.createLayerDrawable(context, resId, batteryLevel); + } else if (resId != 0) { + return context.getDrawable(resId); + } else { + return null; + } } } diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java index 27c1a83c28..98a3580a36 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java @@ -32,6 +32,7 @@ import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.SettingsShadowBluetoothDevice; +import com.android.settings.testutils.shadow.SettingsShadowResources; import com.android.settings.testutils.shadow.ShadowEntityHeaderController; import com.android.settings.widget.EntityHeaderController; @@ -45,7 +46,8 @@ import org.robolectric.annotation.Config; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, - shadows={SettingsShadowBluetoothDevice.class, ShadowEntityHeaderController.class}) + shadows={SettingsShadowBluetoothDevice.class, ShadowEntityHeaderController.class, + SettingsShadowResources.class}) public class BluetoothDetailsHeaderControllerTest extends BluetoothDetailsControllerTestBase { private BluetoothDetailsHeaderController mController; private LayoutPreference mPreference; diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java index d60571c0f0..b16e5bc047 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java @@ -26,6 +26,7 @@ import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import com.android.settings.core.instrumentation.MetricsFeatureProvider; import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settings.testutils.shadow.SettingsShadowResources; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import org.junit.Before; @@ -44,7 +45,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, + shadows = SettingsShadowResources.class) public class BluetoothDevicePreferenceTest { private Context mContext; @@ -140,8 +142,11 @@ public class BluetoothDevicePreferenceTest { @Test public void imagingDeviceIcon_isICSettingsPrint() { + when(mCachedBluetoothDevice.getBatteryLevel()).thenReturn( + BluetoothDevice.BATTERY_LEVEL_UNKNOWN); when(mCachedBluetoothDevice.getBtClass()).thenReturn( new BluetoothClass(BluetoothClass.Device.Major.IMAGING)); + mPreference.onDeviceAttributesChanged(); assertThat(mPreference.getIcon()).isEqualTo( mContext.getDrawable(R.drawable.ic_settings_print)); diff --git a/tests/robotests/src/com/android/settings/bluetooth/UtilsTest.java b/tests/robotests/src/com/android/settings/bluetooth/UtilsTest.java index 4667dacef5..76549212a0 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/UtilsTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/UtilsTest.java @@ -15,14 +15,21 @@ */ package com.android.settings.bluetooth; +import static com.google.common.truth.Truth.assertThat; + +import android.bluetooth.BluetoothDevice; import android.content.Context; +import android.graphics.drawable.Drawable; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.settings.R; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import com.android.settings.core.instrumentation.MetricsFeatureProvider; import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settings.testutils.shadow.SettingsShadowResources; import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.graph.BluetoothDeviceLayerDrawable; import org.junit.Before; import org.junit.Test; @@ -30,6 +37,7 @@ import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import static org.mockito.Matchers.anyInt; @@ -40,7 +48,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, + shadows = SettingsShadowResources.class) public class UtilsTest { @Mock(answer = Answers.RETURNS_DEEP_STUBS) @@ -60,11 +69,27 @@ public class UtilsTest { } @Test - public void showConnectingError_shouldLogBluetoothConnectError() { + public void testShowConnectingError_shouldLogBluetoothConnectError() { when(mContext.getString(anyInt(), anyString())).thenReturn("testMessage"); Utils.showConnectingError(mContext, "testName", mock(LocalBluetoothManager.class)); verify(mMetricsFeatureProvider).visible(eq(mContext), anyInt(), - eq(MetricsEvent.ACTION_SETTINGS_BLUETOOTH_CONNECT_ERROR)); + eq(MetricsEvent.ACTION_SETTINGS_BLUETOOTH_CONNECT_ERROR)); + } + + @Test + public void testGetBluetoothDrawable_noBatteryLevel_returnSimpleDrawable() { + final Drawable drawable = Utils.getBluetoothDrawable(RuntimeEnvironment.application, + R.drawable.ic_bt_laptop, BluetoothDevice.BATTERY_LEVEL_UNKNOWN); + + assertThat(drawable).isNotInstanceOf(BluetoothDeviceLayerDrawable.class); + } + + @Test + public void testGetBluetoothDrawable_hasBatteryLevel_returnLayerDrawable() { + final Drawable drawable = Utils.getBluetoothDrawable(RuntimeEnvironment.application, + R.drawable.ic_bt_laptop, 10 /* batteryLevel */); + + assertThat(drawable).isInstanceOf(BluetoothDeviceLayerDrawable.class); } } -- 2.11.0