Add Hearable control slice in bluetooth device detail settings
Bug: 229048602 Test: make -j64 RunSettingsRoboTests Change-Id: I850aaee9bf7518c9f9de065fbbd1eb4919fc62ee
This commit is contained in:
@@ -46,6 +46,11 @@
|
|||||||
android:key="action_buttons"
|
android:key="action_buttons"
|
||||||
settings:allowDividerBelow="true"/>
|
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
|
<com.android.settings.slices.SlicePreference
|
||||||
android:key="bt_device_slice"
|
android:key="bt_device_slice"
|
||||||
settings:controller="com.android.settings.slices.BlockingSlicePrefController"
|
settings:controller="com.android.settings.slices.BlockingSlicePrefController"
|
||||||
|
@@ -22,12 +22,18 @@ import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
|||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.DeviceConfig;
|
import android.provider.DeviceConfig;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.ViewTreeObserver;
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
@@ -36,12 +42,14 @@ import com.android.settings.core.SettingsUIDeviceConfig;
|
|||||||
import com.android.settings.dashboard.RestrictedDashboardFragment;
|
import com.android.settings.dashboard.RestrictedDashboardFragment;
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
import com.android.settings.slices.BlockingSlicePrefController;
|
import com.android.settings.slices.BlockingSlicePrefController;
|
||||||
|
import com.android.settings.slices.SlicePreferenceController;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
import com.android.settingslib.core.AbstractPreferenceController;
|
import com.android.settingslib.core.AbstractPreferenceController;
|
||||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.IllegalFormatException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment {
|
public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment {
|
||||||
@@ -61,6 +69,7 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
interface TestDataFactory {
|
interface TestDataFactory {
|
||||||
CachedBluetoothDevice getDevice(String deviceAddress);
|
CachedBluetoothDevice getDevice(String deviceAddress);
|
||||||
|
|
||||||
LocalBluetoothManager getManager(Context context);
|
LocalBluetoothManager getManager(Context context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,6 +136,49 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
|||||||
use(BlockingSlicePrefController.class).setSliceUri(sliceEnabled
|
use(BlockingSlicePrefController.class).setSliceUri(sliceEnabled
|
||||||
? featureProvider.getBluetoothDeviceSettingsUri(mCachedDevice.getDevice())
|
? featureProvider.getBluetoothDeviceSettingsUri(mCachedDevice.getDevice())
|
||||||
: null);
|
: 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
|
@Override
|
||||||
|
@@ -26,8 +26,17 @@ public interface BluetoothFeatureProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the {@link Uri} that represents extra settings for a specific bluetooth device
|
* Get the {@link Uri} that represents extra settings for a specific bluetooth device
|
||||||
|
*
|
||||||
* @param bluetoothDevice bluetooth device
|
* @param bluetoothDevice bluetooth device
|
||||||
* @return {@link Uri} for extra settings
|
* @return {@link Uri} for extra settings
|
||||||
*/
|
*/
|
||||||
Uri getBluetoothDeviceSettingsUri(BluetoothDevice bluetoothDevice);
|
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);
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,8 @@ import android.bluetooth.BluetoothDevice;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Impl of {@link BluetoothFeatureProvider}
|
* Impl of {@link BluetoothFeatureProvider}
|
||||||
*/
|
*/
|
||||||
@@ -37,4 +39,9 @@ public class BluetoothFeatureProviderImpl implements BluetoothFeatureProvider {
|
|||||||
BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI);
|
BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI);
|
||||||
return uriByte == null ? null : Uri.parse(new String(uriByte));
|
return uriByte == null ? null : Uri.parse(new String(uriByte));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getBluetoothDeviceControlUri(BluetoothDevice bluetoothDevice) {
|
||||||
|
return BluetoothUtils.getControlUriMetaData(bluetoothDevice);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -33,6 +33,11 @@ import org.robolectric.RuntimeEnvironment;
|
|||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
public class BluetoothFeatureProviderImplTest {
|
public class BluetoothFeatureProviderImplTest {
|
||||||
private static final String SETTINGS_URI = "content://test.provider/settings_uri";
|
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;
|
private BluetoothFeatureProvider mBluetoothFeatureProvider;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
@@ -54,4 +59,13 @@ public class BluetoothFeatureProviderImplTest {
|
|||||||
final Uri uri = mBluetoothFeatureProvider.getBluetoothDeviceSettingsUri(mBluetoothDevice);
|
final Uri uri = mBluetoothFeatureProvider.getBluetoothDeviceSettingsUri(mBluetoothDevice);
|
||||||
assertThat(uri.toString()).isEqualTo(SETTINGS_URI);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user