Merge "Add battery indicator to bluetooth icon" into oc-mr1-dev

am: 77bd8c3a73

Change-Id: I36f5729dd042c88c9f8d6a2d4abf720a05748246
This commit is contained in:
jackqdyulei
2017-08-25 18:37:53 +00:00
committed by android-build-merger
7 changed files with 84 additions and 29 deletions

View File

@@ -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" />

View File

@@ -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);
} }

View File

@@ -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;
} }

View File

@@ -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;
}
} }
} }

View File

@@ -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;

View File

@@ -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));

View File

@@ -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);
} }
} }