Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f11ccf3 authored by Ugo Yu's avatar Ugo Yu
Browse files

Align with Bluetooth metadata API changes

* Align with the changes of Bluetooth metadata APIs.
* Move metadata utils from Settings to SettingsLib.

Bug: 124448651
Test: make RunSettingsRoboTests
Change-Id: Ic9ad91536ef3ff6807a08bbffa3dd796ef1ad523
parent dc4f7ce2
Loading
Loading
Loading
Loading
+26 −25
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.fuelgauge.BatteryMeterView;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnDestroy;
@@ -69,13 +70,12 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
    @VisibleForTesting
    Handler mHandler = new Handler(Looper.getMainLooper());
    @VisibleForTesting
    final BluetoothAdapter.MetadataListener mMetadataListener =
            new BluetoothAdapter.MetadataListener() {
    final BluetoothAdapter.OnMetadataChangedListener mMetadataListener =
            new BluetoothAdapter.OnMetadataChangedListener() {
                @Override
                public void onMetadataChanged(BluetoothDevice device, int key, String value) {
                    super.onMetadataChanged(device, key, value);
                public void onMetadataChanged(BluetoothDevice device, int key, byte[] value) {
                    Log.i(TAG, String.format("Metadata updated in Device %s: %d = %s.", device, key,
                            value));
                            value == null ? null : new String(value)));
                    refresh();
                }
            };
@@ -88,9 +88,9 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont

    @Override
    public int getAvailabilityStatus() {
        final boolean unthetheredHeadset = Utils.getBooleanMetaData(mCachedDevice.getDevice(),
                BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET);
        return unthetheredHeadset ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
        final boolean untetheredHeadset = BluetoothUtils.getBooleanMetaData(
                mCachedDevice.getDevice(), BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET);
        return untetheredHeadset ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
    }

    @Override
@@ -108,8 +108,8 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
            return;
        }
        mCachedDevice.registerCallback(this::onDeviceAttributesChanged);
        mBluetoothAdapter.registerMetadataListener(mCachedDevice.getDevice(), mMetadataListener,
                mHandler);
        mBluetoothAdapter.addOnMetadataChangedListener(mCachedDevice.getDevice(),
                mContext.getMainExecutor(), mMetadataListener);
    }

    @Override
@@ -118,7 +118,8 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
            return;
        }
        mCachedDevice.unregisterCallback(this::onDeviceAttributesChanged);
        mBluetoothAdapter.unregisterMetadataListener(mCachedDevice.getDevice());
        mBluetoothAdapter.removeOnMetadataChangedListener(mCachedDevice.getDevice(),
                mMetadataListener);
    }

    @Override
@@ -154,21 +155,21 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
            }

            updateSubLayout(mLayoutPreference.findViewById(R.id.layout_left),
                    BluetoothDevice.METADATA_UNTHETHERED_LEFT_ICON,
                    BluetoothDevice.METADATA_UNTHETHERED_LEFT_BATTERY,
                    BluetoothDevice.METADATA_UNTHETHERED_LEFT_CHARGING,
                    BluetoothDevice.METADATA_UNTETHERED_LEFT_ICON,
                    BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY,
                    BluetoothDevice.METADATA_UNTETHERED_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,
                    BluetoothDevice.METADATA_UNTETHERED_CASE_ICON,
                    BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY,
                    BluetoothDevice.METADATA_UNTETHERED_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,
                    BluetoothDevice.METADATA_UNTETHERED_RIGHT_ICON,
                    BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY,
                    BluetoothDevice.METADATA_UNTETHERED_RIGHT_CHARGING,
                    R.string.bluetooth_right_name);
        }
    }
@@ -194,15 +195,15 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
            return;
        }
        final BluetoothDevice bluetoothDevice = mCachedDevice.getDevice();
        final String iconUri = Utils.getStringMetaData(bluetoothDevice, iconMetaKey);
        final String iconUri = BluetoothUtils.getStringMetaData(bluetoothDevice, iconMetaKey);
        if (iconUri != null) {
            final ImageView imageView = linearLayout.findViewById(R.id.header_icon);
            updateIcon(imageView, iconUri);
        }

        final int batteryLevel = Utils.getIntMetaData(bluetoothDevice, batteryMetaKey);
        final boolean charging = Utils.getBooleanMetaData(bluetoothDevice, chargeMetaKey);
        if (batteryLevel != Utils.META_INT_ERROR) {
        final int batteryLevel = BluetoothUtils.getIntMetaData(bluetoothDevice, batteryMetaKey);
        final boolean charging = BluetoothUtils.getBooleanMetaData(bluetoothDevice, chargeMetaKey);
        if (batteryLevel != BluetoothUtils.META_INT_ERROR) {
            linearLayout.setVisibility(View.VISIBLE);
            final ImageView imageView = linearLayout.findViewById(R.id.bt_battery_icon);
            imageView.setImageDrawable(createBtBatteryIcon(mContext, batteryLevel, charging));
@@ -233,7 +234,7 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont

        // Only show bluetooth icon
        final BluetoothDevice bluetoothDevice = mCachedDevice.getDevice();
        final String iconUri = Utils.getStringMetaData(bluetoothDevice,
        final String iconUri = BluetoothUtils.getStringMetaData(bluetoothDevice,
                BluetoothDevice.METADATA_MAIN_ICON);
        if (iconUri != null) {
            final ImageView imageView = linearLayout.findViewById(R.id.header_icon);
+2 −2
Original line number Diff line number Diff line
@@ -53,8 +53,8 @@ public class BluetoothDetailsHeaderController extends BluetoothDetailsController

    @Override
    public boolean isAvailable() {
        return !Utils.getBooleanMetaData(mCachedDevice.getDevice(),
                BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET);
        return !BluetoothUtils.getBooleanMetaData(mCachedDevice.getDevice(),
                BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET);
    }

    @Override
+2 −2
Original line number Diff line number Diff line
@@ -33,8 +33,8 @@ public class BluetoothFeatureProviderImpl implements BluetoothFeatureProvider {

    @Override
    public Uri getBluetoothDeviceSettingsUri(BluetoothDevice bluetoothDevice) {
        final String uriString = bluetoothDevice.getMetadata(
        final byte[] uriByte = bluetoothDevice.getMetadata(
                BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI);
        return uriString != null ? Uri.parse(uriString) : null;
        return uriByte == null ? null : Uri.parse(new String(uriByte));
    }
}
+0 −28
Original line number Diff line number Diff line
@@ -47,8 +47,6 @@ public final class Utils {
    static final boolean V = BluetoothUtils.V; // verbose logging
    static final boolean D =  BluetoothUtils.D;  // regular logging

    public static final int META_INT_ERROR = -1;

    private Utils() {
    }

@@ -154,30 +152,4 @@ public final class Utils {
        return Settings.Global.getInt(context.getContentResolver(),
                Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0) == 1;
    }

    public static boolean getBooleanMetaData(BluetoothDevice bluetoothDevice, int key) {
        if (bluetoothDevice == null) {
            return false;
        }

        return Boolean.parseBoolean(bluetoothDevice.getMetadata(key));
    }

    public static String getStringMetaData(BluetoothDevice bluetoothDevice, int key) {
        if (bluetoothDevice == null) {
            return null;
        }
        return bluetoothDevice.getMetadata(key);
    }

    public static int getIntMetaData(BluetoothDevice bluetoothDevice, int key) {
        if (bluetoothDevice == null) {
            return META_INT_ERROR;
        }
        try {
            return Integer.parseInt(bluetoothDevice.getMetadata(key));
        } catch (NumberFormatException e) {
            return META_INT_ERROR;
        }
    }
}
+30 −28
Original line number Diff line number Diff line
@@ -104,14 +104,14 @@ public class AdvancedBluetoothDetailsHeaderControllerTest{
    @Test
    public void refresh_connected_updateCorrectInfo() {
        when(mBluetoothDevice.getMetadata(
                BluetoothDevice.METADATA_UNTHETHERED_LEFT_BATTERY)).thenReturn(
                String.valueOf(BATTERY_LEVEL_LEFT));
                BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY)).thenReturn(
                String.valueOf(BATTERY_LEVEL_LEFT).getBytes());
        when(mBluetoothDevice.getMetadata(
                BluetoothDevice.METADATA_UNTHETHERED_RIGHT_BATTERY)).thenReturn(
                String.valueOf(BATTERY_LEVEL_RIGHT));
                BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY)).thenReturn(
                String.valueOf(BATTERY_LEVEL_RIGHT).getBytes());
        when(mBluetoothDevice.getMetadata(
                BluetoothDevice.METADATA_UNTHETHERED_CASE_BATTERY)).thenReturn(
                String.valueOf(BATTERY_LEVEL_MAIN));
                BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY)).thenReturn(
                String.valueOf(BATTERY_LEVEL_MAIN).getBytes());
        when(mCachedDevice.isConnected()).thenReturn(true);
        mController.refresh();

@@ -141,18 +141,18 @@ public class AdvancedBluetoothDetailsHeaderControllerTest{
    }

    @Test
    public void getAvailabilityStatus_unthetheredHeadset_returnAvailable() {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET))
                .thenReturn("true");
    public void getAvailabilityStatus_untetheredHeadset_returnAvailable() {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
                .thenReturn("true".getBytes());

        assertThat(mController.getAvailabilityStatus()).isEqualTo(
                BasePreferenceController.AVAILABLE);
    }

    @Test
    public void getAvailabilityStatus_notUnthetheredHeadset_returnUnavailable() {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET))
                .thenReturn("false");
    public void getAvailabilityStatus_notUntetheredHeadset_returnUnavailable() {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
                .thenReturn("false".getBytes());

        assertThat(mController.getAvailabilityStatus()).isEqualTo(
                BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
@@ -169,50 +169,52 @@ public class AdvancedBluetoothDetailsHeaderControllerTest{

    @Test
    public void onStart_isAvailable_registerCallback() {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET))
                .thenReturn("true");
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
                .thenReturn("true".getBytes());

        mController.onStart();

        verify(mBluetoothAdapter).registerMetadataListener(mBluetoothDevice,
                mController.mMetadataListener, mController.mHandler);
        verify(mBluetoothAdapter).addOnMetadataChangedListener(mBluetoothDevice,
                mContext.getMainExecutor() ,mController.mMetadataListener);
    }

    @Test
    public void onStop_isAvailable_unregisterCallback() {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET))
                .thenReturn("true");
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
                .thenReturn("true".getBytes());

        mController.onStop();

        verify(mBluetoothAdapter).unregisterMetadataListener(mBluetoothDevice);
        verify(mBluetoothAdapter).removeOnMetadataChangedListener(mBluetoothDevice,
                mController.mMetadataListener);
    }

    @Test
    public void onStart_notAvailable_registerCallback() {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET))
                .thenReturn("false");
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
                .thenReturn("false".getBytes());

        mController.onStart();

        verify(mBluetoothAdapter, never()).registerMetadataListener(mBluetoothDevice,
                mController.mMetadataListener, mController.mHandler);
        verify(mBluetoothAdapter, never()).addOnMetadataChangedListener(mBluetoothDevice,
                mContext.getMainExecutor() ,mController.mMetadataListener);
    }

    @Test
    public void onStop_notAvailable_unregisterCallback() {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET))
                .thenReturn("false");
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
                .thenReturn("false".getBytes());

        mController.onStop();

        verify(mBluetoothAdapter, never()).unregisterMetadataListener(mBluetoothDevice);
        verify(mBluetoothAdapter, never()).removeOnMetadataChangedListener(mBluetoothDevice,
                mController.mMetadataListener);
    }

    @Test
    public void onDestroy_isAvailable_recycleBitmap() {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET))
                .thenReturn("true");
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
                .thenReturn("true".getBytes());
        mController.mIconCache.put(ICON_URI, mBitmap);

        mController.onDestroy();
Loading