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

Commit 8595cf77 authored by Alan Huang's avatar Alan Huang
Browse files

Add Hearable control slice in bluetooth device detail settings

Bug: 229048602
Test: make -j64 RunSettingsRoboTests
Change-Id: I850aaee9bf7518c9f9de065fbbd1eb4919fc62ee
parent 56c7f91c
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -46,6 +46,11 @@
        android:key="action_buttons"
        settings:allowDividerBelow="true"/>

    <com.android.settings.slices.SlicePreference
        android:key="bt_extra_control"
        settings:controller="com.android.settings.slices.SlicePreferenceController"
        settings:allowDividerAbove="true"/>

    <com.android.settings.slices.SlicePreference
        android:key="bt_device_slice"
        settings:controller="com.android.settings.slices.BlockingSlicePrefController"
+52 −0
Original line number Diff line number Diff line
@@ -22,12 +22,18 @@ import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.provider.DeviceConfig;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;

import androidx.annotation.VisibleForTesting;

@@ -36,12 +42,14 @@ import com.android.settings.core.SettingsUIDeviceConfig;
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.slices.BlockingSlicePrefController;
import com.android.settings.slices.SlicePreferenceController;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;

import java.util.ArrayList;
import java.util.IllegalFormatException;
import java.util.List;

public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment {
@@ -61,6 +69,7 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
    @VisibleForTesting
    interface TestDataFactory {
        CachedBluetoothDevice getDevice(String deviceAddress);

        LocalBluetoothManager getManager(Context context);
    }

@@ -127,6 +136,49 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
        use(BlockingSlicePrefController.class).setSliceUri(sliceEnabled
                ? featureProvider.getBluetoothDeviceSettingsUri(mCachedDevice.getDevice())
                : null);
        updateExtraControlUri(/* viewWidth */ 0);
    }

    private void updateExtraControlUri(int viewWidth) {
        BluetoothFeatureProvider featureProvider = FeatureFactory.getFactory(
                getContext()).getBluetoothFeatureProvider(getContext());
        boolean sliceEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
                SettingsUIDeviceConfig.BT_SLICE_SETTINGS_ENABLED, true);
        Uri controlUri = null;
        String uri = featureProvider.getBluetoothDeviceControlUri(mCachedDevice.getDevice());
        if (!TextUtils.isEmpty(uri)) {
            try {
                controlUri = Uri.parse(String.format(uri, viewWidth));
            } catch (IllegalFormatException | NullPointerException exception) {
                Log.d(TAG, "unable to parse uri");
                controlUri = null;
            }
        }
        use(SlicePreferenceController.class).setSliceUri(sliceEnabled ? controlUri : null);
    }

    private final ViewTreeObserver.OnGlobalLayoutListener mOnGlobalLayoutListener =
            new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    View view = getView();
                    if (view == null) {
                        return;
                    }
                    updateExtraControlUri(view.getWidth());
                    view.getViewTreeObserver().removeOnGlobalLayoutListener(
                            mOnGlobalLayoutListener);
                }
            };

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = super.onCreateView(inflater, container, savedInstanceState);
        if (view != null) {
            view.getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);
        }
        return view;
    }

    @Override
+9 −0
Original line number Diff line number Diff line
@@ -26,8 +26,17 @@ public interface BluetoothFeatureProvider {

    /**
     * Get the {@link Uri} that represents extra settings for a specific bluetooth device
     *
     * @param bluetoothDevice bluetooth device
     * @return {@link Uri} for extra settings
     */
    Uri getBluetoothDeviceSettingsUri(BluetoothDevice bluetoothDevice);

    /**
     * Get the {@link Uri} that represents extra control for a specific bluetooth device
     *
     * @param bluetoothDevice bluetooth device
     * @return {@link String} uri string for extra control
     */
    String getBluetoothDeviceControlUri(BluetoothDevice bluetoothDevice);
}
+7 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.net.Uri;

import com.android.settingslib.bluetooth.BluetoothUtils;

/**
 * Impl of {@link BluetoothFeatureProvider}
 */
@@ -37,4 +39,9 @@ public class BluetoothFeatureProviderImpl implements BluetoothFeatureProvider {
                BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI);
        return uriByte == null ? null : Uri.parse(new String(uriByte));
    }

    @Override
    public String getBluetoothDeviceControlUri(BluetoothDevice bluetoothDevice) {
        return BluetoothUtils.getControlUriMetaData(bluetoothDevice);
    }
}
+14 −0
Original line number Diff line number Diff line
@@ -33,6 +33,11 @@ import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class BluetoothFeatureProviderImplTest {
    private static final String SETTINGS_URI = "content://test.provider/settings_uri";
    private static final String CONTROL_METADATA =
            "<HEARABLE_CONTROL_SLICE_WITH_WIDTH>" + SETTINGS_URI
                    + "</HEARABLE_CONTROL_SLICE_WITH_WIDTH>";
    private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;

    private BluetoothFeatureProvider mBluetoothFeatureProvider;

    @Mock
@@ -54,4 +59,13 @@ public class BluetoothFeatureProviderImplTest {
        final Uri uri = mBluetoothFeatureProvider.getBluetoothDeviceSettingsUri(mBluetoothDevice);
        assertThat(uri.toString()).isEqualTo(SETTINGS_URI);
    }

    @Test
    public void getBluetoothDeviceControlUri_returnsCorrectUri() {
        when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS)).thenReturn(
                CONTROL_METADATA.getBytes());
        assertThat(
                mBluetoothFeatureProvider.getBluetoothDeviceControlUri(mBluetoothDevice)).isEqualTo(
                SETTINGS_URI);
    }
}