Loading res/xml/bluetooth_device_details_fragment.xml +5 −0 Original line number Diff line number Diff line Loading @@ -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" Loading src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java +52 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 { Loading @@ -61,6 +69,7 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment @VisibleForTesting interface TestDataFactory { CachedBluetoothDevice getDevice(String deviceAddress); LocalBluetoothManager getManager(Context context); } Loading Loading @@ -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 Loading src/com/android/settings/bluetooth/BluetoothFeatureProvider.java +9 −0 Original line number Diff line number Diff line Loading @@ -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); } src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java +7 −0 Original line number Diff line number Diff line Loading @@ -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} */ Loading @@ -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); } } tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java +14 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); } } Loading
res/xml/bluetooth_device_details_fragment.xml +5 −0 Original line number Diff line number Diff line Loading @@ -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" Loading
src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java +52 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 { Loading @@ -61,6 +69,7 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment @VisibleForTesting interface TestDataFactory { CachedBluetoothDevice getDevice(String deviceAddress); LocalBluetoothManager getManager(Context context); } Loading Loading @@ -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 Loading
src/com/android/settings/bluetooth/BluetoothFeatureProvider.java +9 −0 Original line number Diff line number Diff line Loading @@ -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); }
src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java +7 −0 Original line number Diff line number Diff line Loading @@ -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} */ Loading @@ -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); } }
tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java +14 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); } }