diff --git a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java index 4b8efd4e371..a09018ea39a 100644 --- a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java +++ b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java @@ -21,6 +21,7 @@ import android.content.Context; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; +import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -33,12 +34,16 @@ import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settings.fuelgauge.BatteryMeterView; import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; import com.android.settingslib.widget.LayoutPreference; /** * This class adds a header with device name and status (connected/disconnected, etc.). */ -public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceController { +public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceController implements + LifecycleObserver, OnStart, OnStop, CachedBluetoothDevice.Callback { @VisibleForTesting LayoutPreference mLayoutPreference; @@ -63,6 +68,16 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont refresh(); } + @Override + public void onStart() { + mCachedDevice.registerCallback(this::onDeviceAttributesChanged); + } + + @Override + public void onStop() { + mCachedDevice.unregisterCallback(this::onDeviceAttributesChanged); + } + public void init(CachedBluetoothDevice cachedBluetoothDevice) { mCachedDevice = cachedBluetoothDevice; } @@ -75,25 +90,33 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont final TextView summary = mLayoutPreference.findViewById(R.id.entity_header_summary); summary.setText(mCachedDevice.getConnectionSummary()); + if (!mCachedDevice.isConnected()) { + updateDisconnectLayout(); + return; + } + updateSubLayout(mLayoutPreference.findViewById(R.id.layout_left), BluetoothDevice.METADATA_UNTHETHERED_LEFT_ICON, BluetoothDevice.METADATA_UNTHETHERED_LEFT_BATTERY, + BluetoothDevice.METADATA_UNTHETHERED_LEFT_CHARGING, R.string.bluetooth_left_name); updateSubLayout(mLayoutPreference.findViewById(R.id.layout_middle), BluetoothDevice.METADATA_UNTHETHERED_CASE_ICON, BluetoothDevice.METADATA_UNTHETHERED_CASE_BATTERY, + BluetoothDevice.METADATA_UNTHETHERED_CASE_CHARGING, R.string.bluetooth_middle_name); updateSubLayout(mLayoutPreference.findViewById(R.id.layout_right), BluetoothDevice.METADATA_UNTHETHERED_RIGHT_ICON, BluetoothDevice.METADATA_UNTHETHERED_RIGHT_BATTERY, + BluetoothDevice.METADATA_UNTHETHERED_RIGHT_CHARGING, R.string.bluetooth_right_name); } } @VisibleForTesting - Drawable createBtBatteryIcon(Context context, int level) { + Drawable createBtBatteryIcon(Context context, int level, boolean charging) { final BatteryMeterView.BatteryMeterDrawable drawable = new BatteryMeterView.BatteryMeterDrawable(context, context.getColor(R.color.meter_background_color)); @@ -103,12 +126,13 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont com.android.settings.Utils.getColorAttrDefaultColor(context, android.R.attr.colorControlNormal), PorterDuff.Mode.SRC_IN)); + drawable.setCharging(charging); return drawable; } private void updateSubLayout(LinearLayout linearLayout, int iconMetaKey, int batteryMetaKey, - int titleResId) { + int chargeMetaKey, int titleResId) { if (linearLayout == null) { return; } @@ -121,14 +145,51 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont } final int batteryLevel = Utils.getIntMetaData(bluetoothDevice, batteryMetaKey); + final boolean charging = Utils.getBooleanMetaData(bluetoothDevice, chargeMetaKey); if (batteryLevel != Utils.META_INT_ERROR) { + linearLayout.setVisibility(View.VISIBLE); final ImageView imageView = linearLayout.findViewById(R.id.bt_battery_icon); - imageView.setImageDrawable(createBtBatteryIcon(mContext, batteryLevel)); + imageView.setImageDrawable(createBtBatteryIcon(mContext, batteryLevel, charging)); + imageView.setVisibility(View.VISIBLE); final TextView textView = linearLayout.findViewById(R.id.bt_battery_summary); textView.setText(com.android.settings.Utils.formatPercentage(batteryLevel)); + textView.setVisibility(View.VISIBLE); + } else { + // Hide it if it doesn't have battery information + linearLayout.setVisibility(View.GONE); } final TextView textView = linearLayout.findViewById(R.id.header_title); textView.setText(titleResId); + textView.setVisibility(View.VISIBLE); + } + + private void updateDisconnectLayout() { + mLayoutPreference.findViewById(R.id.layout_left).setVisibility(View.GONE); + mLayoutPreference.findViewById(R.id.layout_right).setVisibility(View.GONE); + + // Hide title, battery icon and battery summary + final LinearLayout linearLayout = mLayoutPreference.findViewById(R.id.layout_middle); + linearLayout.setVisibility(View.VISIBLE); + linearLayout.findViewById(R.id.header_title).setVisibility(View.GONE); + linearLayout.findViewById(R.id.bt_battery_summary).setVisibility(View.GONE); + linearLayout.findViewById(R.id.bt_battery_icon).setVisibility(View.GONE); + + // Only show bluetooth icon + final BluetoothDevice bluetoothDevice = mCachedDevice.getDevice(); + final String iconUri = Utils.getStringMetaData(bluetoothDevice, + BluetoothDevice.METADATA_MAIN_ICON); + if (iconUri != null) { + final ImageView imageView = linearLayout.findViewById(R.id.header_icon); + final IconCompat iconCompat = IconCompat.createWithContentUri(iconUri); + imageView.setImageBitmap(iconCompat.getBitmap()); + } + } + + @Override + public void onDeviceAttributesChanged() { + if (mCachedDevice != null) { + refresh(); + } } } diff --git a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java index a74610e1a3d..e6462731b98 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java @@ -24,6 +24,7 @@ import android.bluetooth.BluetoothDevice; import android.content.Context; import android.graphics.drawable.Drawable; import android.view.LayoutInflater; +import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; @@ -74,16 +75,18 @@ public class AdvancedBluetoothDetailsHeaderControllerTest{ @Test public void createBatteryIcon_hasCorrectInfo() { - final Drawable drawable = mController.createBtBatteryIcon(mContext, BATTERY_LEVEL_MAIN); + final Drawable drawable = mController.createBtBatteryIcon(mContext, BATTERY_LEVEL_MAIN, + true /* charging */); assertThat(drawable).isInstanceOf(BatteryMeterView.BatteryMeterDrawable.class); final BatteryMeterView.BatteryMeterDrawable iconDrawable = (BatteryMeterView.BatteryMeterDrawable) drawable; assertThat(iconDrawable.getBatteryLevel()).isEqualTo(BATTERY_LEVEL_MAIN); + assertThat(iconDrawable.getCharging()).isTrue(); } @Test - public void refresh_updateCorrectInfo() { + public void refresh_connected_updateCorrectInfo() { when(mBluetoothDevice.getMetadata( BluetoothDevice.METADATA_UNTHETHERED_LEFT_BATTERY)).thenReturn( String.valueOf(BATTERY_LEVEL_LEFT)); @@ -93,6 +96,7 @@ public class AdvancedBluetoothDetailsHeaderControllerTest{ when(mBluetoothDevice.getMetadata( BluetoothDevice.METADATA_UNTHETHERED_CASE_BATTERY)).thenReturn( String.valueOf(BATTERY_LEVEL_MAIN)); + when(mCachedDevice.isConnected()).thenReturn(true); mController.refresh(); assertBatteryLevel(mLayoutPreference.findViewById(R.id.layout_left), BATTERY_LEVEL_LEFT); @@ -100,6 +104,26 @@ public class AdvancedBluetoothDetailsHeaderControllerTest{ assertBatteryLevel(mLayoutPreference.findViewById(R.id.layout_middle), BATTERY_LEVEL_MAIN); } + @Test + public void refresh_disconnected_updateCorrectInfo() { + when(mCachedDevice.isConnected()).thenReturn(false); + + mController.refresh(); + + final LinearLayout layout = mLayoutPreference.findViewById(R.id.layout_middle); + + assertThat(mLayoutPreference.findViewById(R.id.layout_left).getVisibility()).isEqualTo( + View.GONE); + assertThat(mLayoutPreference.findViewById(R.id.layout_right).getVisibility()).isEqualTo( + View.GONE); + assertThat(layout.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(layout.findViewById(R.id.header_title).getVisibility()).isEqualTo(View.GONE); + assertThat(layout.findViewById(R.id.bt_battery_summary).getVisibility()).isEqualTo( + View.GONE); + assertThat(layout.findViewById(R.id.bt_battery_icon).getVisibility()).isEqualTo(View.GONE); + assertThat(layout.findViewById(R.id.header_icon).getVisibility()).isEqualTo(View.VISIBLE); + } + @Test public void getAvailabilityStatus_unthetheredHeadset_returnAvailable() { when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET))