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
This commit is contained in:
@@ -38,7 +38,7 @@
|
|||||||
android:id="@+id/entity_header_icon"
|
android:id="@+id/entity_header_icon"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:scaleType="fitXY"
|
android:scaleType="fitCenter"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:antialias="true" />
|
android:antialias="true" />
|
||||||
|
|
||||||
|
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
package com.android.settings.bluetooth;
|
package com.android.settings.bluetooth;
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.support.v14.preference.PreferenceFragment;
|
import android.support.v14.preference.PreferenceFragment;
|
||||||
import android.support.v7.preference.PreferenceScreen;
|
import android.support.v7.preference.PreferenceScreen;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
@@ -51,11 +51,11 @@ public class BluetoothDetailsHeaderController extends BluetoothDetailsController
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void setHeaderProperties() {
|
protected void setHeaderProperties() {
|
||||||
Pair<Integer, String> pair = Utils.getBtClassDrawableWithDescription
|
final Pair<Drawable, String> pair = Utils.getBtClassDrawableWithDescription
|
||||||
(mContext.getResources(), mCachedDevice);
|
(mContext, mCachedDevice);
|
||||||
String summaryText = mCachedDevice.getConnectionSummary();
|
String summaryText = mCachedDevice.getConnectionSummary();
|
||||||
mHeaderController.setLabel(mCachedDevice.getName());
|
mHeaderController.setLabel(mCachedDevice.getName());
|
||||||
mHeaderController.setIcon(mContext.getDrawable(pair.first));
|
mHeaderController.setIcon(pair.first);
|
||||||
mHeaderController.setIconContentDescription(pair.second);
|
mHeaderController.setIconContentDescription(pair.second);
|
||||||
mHeaderController.setSummary(summaryText);
|
mHeaderController.setSummary(summaryText);
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@ import android.bluetooth.BluetoothDevice;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.support.v7.preference.Preference;
|
import android.support.v7.preference.Preference;
|
||||||
import android.support.v7.preference.PreferenceViewHolder;
|
import android.support.v7.preference.PreferenceViewHolder;
|
||||||
@@ -120,9 +121,9 @@ public final class BluetoothDevicePreference extends GearPreference implements
|
|||||||
// Null check is done at the framework
|
// Null check is done at the framework
|
||||||
setSummary(mCachedDevice.getConnectionSummary());
|
setSummary(mCachedDevice.getConnectionSummary());
|
||||||
|
|
||||||
Pair<Integer, String> pair = Utils.getBtClassDrawableWithDescription(mResources,
|
final Pair<Drawable, String> pair = Utils.getBtClassDrawableWithDescription(getContext(),
|
||||||
mCachedDevice);
|
mCachedDevice);
|
||||||
if (pair.first != 0) {
|
if (pair.first != null) {
|
||||||
setIcon(pair.first);
|
setIcon(pair.first);
|
||||||
contentDescription = pair.second;
|
contentDescription = pair.second;
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,9 @@ import android.bluetooth.BluetoothProfile;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.res.Resources;
|
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.support.annotation.VisibleForTesting;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.widget.Toast;
|
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.LocalBluetoothManager.BluetoothManagerCallback;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
|
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
|
||||||
import com.android.settingslib.bluetooth.Utils.ErrorListener;
|
import com.android.settingslib.bluetooth.Utils.ErrorListener;
|
||||||
|
import com.android.settingslib.graph.BluetoothDeviceLayerDrawable;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -150,27 +154,31 @@ public final class Utils {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static Pair<Integer, String> getBtClassDrawableWithDescription(Resources r,
|
static Pair<Drawable, String> getBtClassDrawableWithDescription(Context context,
|
||||||
CachedBluetoothDevice cachedDevice) {
|
CachedBluetoothDevice cachedDevice) {
|
||||||
BluetoothClass btClass = cachedDevice.getBtClass();
|
BluetoothClass btClass = cachedDevice.getBtClass();
|
||||||
|
final int level = cachedDevice.getBatteryLevel();
|
||||||
if (btClass != null) {
|
if (btClass != null) {
|
||||||
switch (btClass.getMajorDeviceClass()) {
|
switch (btClass.getMajorDeviceClass()) {
|
||||||
case BluetoothClass.Device.Major.COMPUTER:
|
case BluetoothClass.Device.Major.COMPUTER:
|
||||||
return new Pair<Integer, String>(R.drawable.ic_bt_laptop,
|
return new Pair<>(getBluetoothDrawable(context, R.drawable.ic_bt_laptop, level),
|
||||||
r.getString(R.string.bluetooth_talkback_computer));
|
context.getString(R.string.bluetooth_talkback_computer));
|
||||||
|
|
||||||
case BluetoothClass.Device.Major.PHONE:
|
case BluetoothClass.Device.Major.PHONE:
|
||||||
return new Pair<Integer, String>(R.drawable.ic_bt_cellphone,
|
return new Pair<>(
|
||||||
r.getString(R.string.bluetooth_talkback_phone));
|
getBluetoothDrawable(context, R.drawable.ic_bt_cellphone, level),
|
||||||
|
context.getString(R.string.bluetooth_talkback_phone));
|
||||||
|
|
||||||
case BluetoothClass.Device.Major.PERIPHERAL:
|
case BluetoothClass.Device.Major.PERIPHERAL:
|
||||||
return new Pair<Integer, String>(HidProfile.getHidClassDrawable(btClass),
|
return new Pair<>(
|
||||||
r.getString(
|
getBluetoothDrawable(context, HidProfile.getHidClassDrawable(btClass),
|
||||||
R.string.bluetooth_talkback_input_peripheral));
|
level),
|
||||||
|
context.getString(R.string.bluetooth_talkback_input_peripheral));
|
||||||
|
|
||||||
case BluetoothClass.Device.Major.IMAGING:
|
case BluetoothClass.Device.Major.IMAGING:
|
||||||
return new Pair<Integer, String>(R.drawable.ic_settings_print,
|
return new Pair<>(
|
||||||
r.getString(R.string.bluetooth_talkback_imaging));
|
getBluetoothDrawable(context, R.drawable.ic_settings_print, level),
|
||||||
|
context.getString(R.string.bluetooth_talkback_imaging));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// unrecognized device class; continue
|
// unrecognized device class; continue
|
||||||
@@ -181,20 +189,34 @@ public final class Utils {
|
|||||||
for (LocalBluetoothProfile profile : profiles) {
|
for (LocalBluetoothProfile profile : profiles) {
|
||||||
int resId = profile.getDrawableResource(btClass);
|
int resId = profile.getDrawableResource(btClass);
|
||||||
if (resId != 0) {
|
if (resId != 0) {
|
||||||
return new Pair<Integer, String>(resId, null);
|
return new Pair<>(getBluetoothDrawable(context, resId, level), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (btClass != null) {
|
if (btClass != null) {
|
||||||
if (btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
|
if (btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
|
||||||
return new Pair<Integer, String>(R.drawable.ic_bt_headset_hfp,
|
return new Pair<>(
|
||||||
r.getString(R.string.bluetooth_talkback_headset));
|
getBluetoothDrawable(context, R.drawable.ic_bt_headset_hfp, level),
|
||||||
|
context.getString(R.string.bluetooth_talkback_headset));
|
||||||
}
|
}
|
||||||
if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) {
|
if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) {
|
||||||
return new Pair<Integer, String>(R.drawable.ic_bt_headphones_a2dp,
|
return new Pair<>(
|
||||||
r.getString(R.string.bluetooth_talkback_headphone));
|
getBluetoothDrawable(context, R.drawable.ic_bt_headphones_a2dp, level),
|
||||||
|
context.getString(R.string.bluetooth_talkback_headphone));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new Pair<Integer, String>(R.drawable.ic_settings_bluetooth,
|
return new Pair<>(getBluetoothDrawable(context, R.drawable.ic_settings_bluetooth, level),
|
||||||
r.getString(R.string.bluetooth_talkback_bluetooth));
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -32,6 +32,7 @@ import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
|||||||
import com.android.settings.TestConfig;
|
import com.android.settings.TestConfig;
|
||||||
import com.android.settings.testutils.FakeFeatureFactory;
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
import com.android.settings.testutils.shadow.SettingsShadowBluetoothDevice;
|
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.testutils.shadow.ShadowEntityHeaderController;
|
||||||
import com.android.settings.widget.EntityHeaderController;
|
import com.android.settings.widget.EntityHeaderController;
|
||||||
|
|
||||||
@@ -45,7 +46,8 @@ import org.robolectric.annotation.Config;
|
|||||||
|
|
||||||
@RunWith(SettingsRobolectricTestRunner.class)
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
|
@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 {
|
public class BluetoothDetailsHeaderControllerTest extends BluetoothDetailsControllerTestBase {
|
||||||
private BluetoothDetailsHeaderController mController;
|
private BluetoothDetailsHeaderController mController;
|
||||||
private LayoutPreference mPreference;
|
private LayoutPreference mPreference;
|
||||||
|
@@ -26,6 +26,7 @@ import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
|||||||
import com.android.settings.TestConfig;
|
import com.android.settings.TestConfig;
|
||||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||||
import com.android.settings.testutils.FakeFeatureFactory;
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
|
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -44,7 +45,8 @@ import static org.mockito.Mockito.verify;
|
|||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@RunWith(SettingsRobolectricTestRunner.class)
|
@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 {
|
public class BluetoothDevicePreferenceTest {
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
@@ -140,8 +142,11 @@ public class BluetoothDevicePreferenceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void imagingDeviceIcon_isICSettingsPrint() {
|
public void imagingDeviceIcon_isICSettingsPrint() {
|
||||||
|
when(mCachedBluetoothDevice.getBatteryLevel()).thenReturn(
|
||||||
|
BluetoothDevice.BATTERY_LEVEL_UNKNOWN);
|
||||||
when(mCachedBluetoothDevice.getBtClass()).thenReturn(
|
when(mCachedBluetoothDevice.getBtClass()).thenReturn(
|
||||||
new BluetoothClass(BluetoothClass.Device.Major.IMAGING));
|
new BluetoothClass(BluetoothClass.Device.Major.IMAGING));
|
||||||
|
|
||||||
mPreference.onDeviceAttributesChanged();
|
mPreference.onDeviceAttributesChanged();
|
||||||
assertThat(mPreference.getIcon()).isEqualTo(
|
assertThat(mPreference.getIcon()).isEqualTo(
|
||||||
mContext.getDrawable(R.drawable.ic_settings_print));
|
mContext.getDrawable(R.drawable.ic_settings_print));
|
||||||
|
@@ -15,14 +15,21 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.settings.bluetooth;
|
package com.android.settings.bluetooth;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
|
import com.android.settings.R;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
import com.android.settings.TestConfig;
|
import com.android.settings.TestConfig;
|
||||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||||
import com.android.settings.testutils.FakeFeatureFactory;
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
|
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
|
import com.android.settingslib.graph.BluetoothDeviceLayerDrawable;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -30,6 +37,7 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.Answers;
|
import org.mockito.Answers;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
import static org.mockito.Matchers.anyInt;
|
import static org.mockito.Matchers.anyInt;
|
||||||
@@ -40,7 +48,8 @@ import static org.mockito.Mockito.verify;
|
|||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@RunWith(SettingsRobolectricTestRunner.class)
|
@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 {
|
public class UtilsTest {
|
||||||
|
|
||||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||||
@@ -60,11 +69,27 @@ public class UtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void showConnectingError_shouldLogBluetoothConnectError() {
|
public void testShowConnectingError_shouldLogBluetoothConnectError() {
|
||||||
when(mContext.getString(anyInt(), anyString())).thenReturn("testMessage");
|
when(mContext.getString(anyInt(), anyString())).thenReturn("testMessage");
|
||||||
Utils.showConnectingError(mContext, "testName", mock(LocalBluetoothManager.class));
|
Utils.showConnectingError(mContext, "testName", mock(LocalBluetoothManager.class));
|
||||||
|
|
||||||
verify(mMetricsFeatureProvider).visible(eq(mContext), anyInt(),
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user