Move rename button next to the device name

BUG: 343317785
Test: atest GeneralBluetoothDetailsHeaderControllerTest
Flag: com.android.settings.flags.enable_bluetooth_device_details_polish
Change-Id: I87f030ca48d3edac13759fe51499b7e400dbb795
This commit is contained in:
Haijie Hong
2024-08-11 18:40:14 +08:00
parent f56a1bccba
commit c2ed6d3242
11 changed files with 507 additions and 20 deletions

View File

@@ -17,6 +17,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/entity_header"
style="@style/EntityHeader"
android:layout_width="match_parent"
@@ -25,15 +26,41 @@
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:orientation="vertical">
<TextView
android:id="@+id/entity_header_title"
style="@style/TextAppearance.EntityHeaderTitle"
android:layout_width="wrap_content"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:ellipsize="marquee"
android:textDirection="locale"/>
android:gravity="center">
<TextView
android:id="@+id/entity_header_title"
style="@style/TextAppearance.EntityHeaderTitle"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:ellipsize="marquee"
android:textDirection="locale"
android:layout_marginStart="48dp"
android:layout_marginEnd="48dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constrainedWidth="true" />
<ImageButton
android:id="@+id/rename_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="@dimen/min_tap_target_size"
android:minHeight="@dimen/min_tap_target_size"
android:background="@android:color/transparent"
android:src="@drawable/ic_mode_edit"
android:contentDescription="@string/bluetooth_rename_button"
android:tint="@color/settingslib_materialColorOnSurface"
app:layout_constraintStart_toEndOf="@+id/entity_header_title"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/entity_header_summary"

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2024 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/entity_header"
style="@style/EntityHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:orientation="vertical">
<ImageView
android:id="@+id/bt_header_icon"
android:importantForAccessibility="no"
style="@style/SettingsLibEntityHeaderIcon"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:gravity="center">
<TextView
android:id="@+id/bt_header_device_name"
style="@style/TextAppearance.EntityHeaderTitle"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:gravity="center"
android:ellipsize="marquee"
android:textDirection="locale"
android:layout_marginStart="48dp"
android:layout_marginEnd="48dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constrainedWidth="true" />
<ImageButton
android:id="@+id/rename_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="@dimen/min_tap_target_size"
android:minHeight="@dimen/min_tap_target_size"
android:background="@android:color/transparent"
android:src="@drawable/ic_mode_edit"
android:contentDescription="@string/bluetooth_rename_button"
android:tint="@color/settingslib_materialColorOnSurface"
app:layout_constraintStart_toEndOf="@+id/bt_header_device_name"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/bt_header_connection_summary"
style="@style/TextAppearance.EntityHeaderSummary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:singleLine="false"
android:textAlignment="center"/>
</LinearLayout>

View File

@@ -17,6 +17,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/entity_header"
style="@style/EntityHeader"
android:layout_width="match_parent"
@@ -27,15 +28,42 @@
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:orientation="vertical">
<TextView
android:id="@+id/entity_header_title"
style="@style/TextAppearance.EntityHeaderTitle"
android:layout_width="wrap_content"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:ellipsize="marquee"
android:textDirection="locale"/>
android:gravity="center">
<TextView
android:id="@+id/entity_header_title"
style="@style/TextAppearance.EntityHeaderTitle"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:ellipsize="marquee"
android:textDirection="locale"
android:layout_marginStart="48dp"
android:layout_marginEnd="48dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constrainedWidth="true" />
<ImageButton
android:id="@+id/rename_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="@dimen/min_tap_target_size"
android:minHeight="@dimen/min_tap_target_size"
android:background="@android:color/transparent"
android:src="@drawable/ic_mode_edit"
android:contentDescription="@string/bluetooth_rename_button"
android:tint="@color/settingslib_materialColorOnSurface"
app:layout_constraintStart_toEndOf="@+id/entity_header_title"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/entity_header_summary"

View File

@@ -26,6 +26,13 @@
settings:allowDividerBelow="true"
settings:searchable="false"/>
<com.android.settingslib.widget.LayoutPreference
android:key="general_bluetooth_device_header"
android:layout="@layout/general_bt_entity_header"
android:selectable="false"
settings:allowDividerBelow="true"
settings:searchable="false"/>
<com.android.settingslib.widget.LayoutPreference
android:key="advanced_bluetooth_device_header"
android:layout="@layout/advanced_bt_entity_header"

View File

@@ -37,12 +37,14 @@ import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
@@ -97,6 +99,7 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
private static final int MAIN_DEVICE_ID = 4;
private static final float HALF_ALPHA = 0.5f;
PreferenceFragmentCompat mFragment;
@VisibleForTesting
LayoutPreference mLayoutPreference;
@VisibleForTesting
@@ -170,8 +173,11 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
mIconCache.clear();
}
public void init(CachedBluetoothDevice cachedBluetoothDevice) {
/** Initializes the controller. */
public void init(
CachedBluetoothDevice cachedBluetoothDevice, PreferenceFragmentCompat fragment) {
mCachedDevice = cachedBluetoothDevice;
mFragment = fragment;
}
private void registerBluetoothDevice() {
@@ -325,6 +331,14 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
MAIN_DEVICE_ID);
}
});
if (Flags.enableBluetoothDeviceDetailsPolish()) {
ImageButton renameButton = mLayoutPreference.findViewById(R.id.rename_button);
renameButton.setVisibility(View.VISIBLE);
renameButton.setOnClickListener(view -> {
RemoteDeviceNameDialogFragment.newInstance(mCachedDevice).show(
mFragment.getFragmentManager(), RemoteDeviceNameDialogFragment.TAG);
});
}
}
}

View File

@@ -26,6 +26,7 @@ import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.flags.Flags;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -47,6 +48,9 @@ public class BluetoothDetailsHeaderController extends BluetoothDetailsController
@Override
public boolean isAvailable() {
if (Flags.enableBluetoothDeviceDetailsPolish()) {
return false;
}
boolean hasLeAudio = mCachedDevice.getUiAccessibleProfiles()
.stream()
.anyMatch(profile -> profile.getProfileId() == BluetoothProfile.LE_AUDIO);

View File

@@ -50,6 +50,7 @@ import com.android.settings.R;
import com.android.settings.connecteddevice.stylus.StylusDevicesController;
import com.android.settings.core.SettingsUIDeviceConfig;
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.flags.Flags;
import com.android.settings.inputmethod.KeyboardSettingsPreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.slices.SlicePreferenceController;
@@ -213,8 +214,8 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
finish();
return;
}
use(AdvancedBluetoothDetailsHeaderController.class).init(mCachedDevice);
use(LeAudioBluetoothDetailsHeaderController.class).init(mCachedDevice, mManager);
use(AdvancedBluetoothDetailsHeaderController.class).init(mCachedDevice, this);
use(LeAudioBluetoothDetailsHeaderController.class).init(mCachedDevice, mManager, this);
use(KeyboardSettingsPreferenceController.class).init(mCachedDevice);
final BluetoothFeatureProvider featureProvider =
@@ -338,7 +339,7 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (!mUserManager.isGuestUser()) {
if (!Flags.enableBluetoothDeviceDetailsPolish() && !mUserManager.isGuestUser()) {
MenuItem item = menu.add(0, EDIT_DEVICE_NAME_ITEM_ID, 0,
R.string.bluetooth_rename_button);
item.setIcon(com.android.internal.R.drawable.ic_mode_edit);
@@ -365,6 +366,9 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
Lifecycle lifecycle = getSettingsLifecycle();
controllers.add(new BluetoothDetailsHeaderController(context, this, mCachedDevice,
lifecycle));
controllers.add(
new GeneralBluetoothDetailsHeaderController(
context, this, mCachedDevice, lifecycle));
controllers.add(new BluetoothDetailsButtonsController(context, this, mCachedDevice,
lifecycle));
controllers.add(new BluetoothDetailsCompanionAppsController(context, this,

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.bluetooth;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.Pair;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.flags.Flags;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.widget.LayoutPreference;
/** This class adds a header with device name and status (connected/disconnected, etc.). */
public class GeneralBluetoothDetailsHeaderController extends BluetoothDetailsController {
private static final String KEY_GENERAL_DEVICE_HEADER = "general_bluetooth_device_header";
@Nullable
private LayoutPreference mLayoutPreference;
public GeneralBluetoothDetailsHeaderController(
Context context,
PreferenceFragmentCompat fragment,
CachedBluetoothDevice device,
Lifecycle lifecycle) {
super(context, fragment, device, lifecycle);
}
@Override
public boolean isAvailable() {
if (!Flags.enableBluetoothDeviceDetailsPolish()) {
return false;
}
boolean hasLeAudio =
mCachedDevice.getUiAccessibleProfiles().stream()
.anyMatch(profile -> profile.getProfileId() == BluetoothProfile.LE_AUDIO);
return !BluetoothUtils.isAdvancedDetailsHeader(mCachedDevice.getDevice()) && !hasLeAudio;
}
@Override
protected void init(PreferenceScreen screen) {
mLayoutPreference = screen.findPreference(KEY_GENERAL_DEVICE_HEADER);
}
@Override
protected void refresh() {
if (!isAvailable() || mLayoutPreference == null) {
return;
}
ImageView imageView = mLayoutPreference.findViewById(R.id.bt_header_icon);
if (imageView != null) {
final Pair<Drawable, String> pair =
BluetoothUtils.getBtRainbowDrawableWithDescription(mContext, mCachedDevice);
imageView.setImageDrawable(pair.first);
imageView.setContentDescription(pair.second);
}
TextView title = mLayoutPreference.findViewById(R.id.bt_header_device_name);
if (title != null) {
title.setText(mCachedDevice.getName());
}
TextView summary = mLayoutPreference.findViewById(R.id.bt_header_connection_summary);
if (summary != null) {
summary.setText(mCachedDevice.getConnectionSummary());
}
ImageButton renameButton = mLayoutPreference.findViewById(R.id.rename_button);
renameButton.setVisibility(View.VISIBLE);
renameButton.setOnClickListener(
view -> {
RemoteDeviceNameDialogFragment.newInstance(mCachedDevice)
.show(
mFragment.getFragmentManager(),
RemoteDeviceNameDialogFragment.TAG);
});
}
@Override
@NonNull
public String getPreferenceKey() {
return KEY_GENERAL_DEVICE_HEADER;
}
}

View File

@@ -27,14 +27,17 @@ import android.os.Looper;
import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.flags.Flags;
import com.android.settings.fuelgauge.BatteryMeterView;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -86,6 +89,7 @@ public class LeAudioBluetoothDetailsHeaderController extends BasePreferenceContr
@VisibleForTesting
static final int INVALID_RESOURCE_ID = -1;
PreferenceFragmentCompat mFragment;
@VisibleForTesting
LayoutPreference mLayoutPreference;
LocalBluetoothManager mManager;
@@ -151,11 +155,12 @@ public class LeAudioBluetoothDetailsHeaderController extends BasePreferenceContr
}
public void init(CachedBluetoothDevice cachedBluetoothDevice,
LocalBluetoothManager bluetoothManager) {
LocalBluetoothManager bluetoothManager, PreferenceFragmentCompat fragment) {
mCachedDevice = cachedBluetoothDevice;
mManager = bluetoothManager;
mProfileManager = bluetoothManager.getProfileManager();
mCachedDeviceGroup = Utils.findAllCachedBluetoothDevicesByGroupId(mManager, mCachedDevice);
mFragment = fragment;
}
@VisibleForTesting
@@ -163,6 +168,14 @@ public class LeAudioBluetoothDetailsHeaderController extends BasePreferenceContr
if (mLayoutPreference == null || mCachedDevice == null) {
return;
}
if (Flags.enableBluetoothDeviceDetailsPolish()) {
ImageButton renameButton = mLayoutPreference.findViewById(R.id.rename_button);
renameButton.setVisibility(View.VISIBLE);
renameButton.setOnClickListener(view -> {
RemoteDeviceNameDialogFragment.newInstance(mCachedDevice).show(
mFragment.getFragmentManager(), RemoteDeviceNameDialogFragment.TAG);
});
}
final ImageView imageView = mLayoutPreference.findViewById(R.id.entity_header_icon);
if (imageView != null) {
final Pair<Drawable, String> pair =

View File

@@ -28,15 +28,19 @@ import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.DeviceConfig;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.preference.PreferenceFragmentCompat;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.core.BasePreferenceController;
@@ -93,6 +97,8 @@ public class AdvancedBluetoothDetailsHeaderControllerTest {
private CachedBluetoothDevice mCachedDevice;
@Mock
private BluetoothAdapter mBluetoothAdapter;
@Mock
private PreferenceFragmentCompat mFragment;
private AdvancedBluetoothDetailsHeaderController mController;
private LayoutPreference mLayoutPreference;
@@ -103,7 +109,7 @@ public class AdvancedBluetoothDetailsHeaderControllerTest {
mContext = Robolectric.buildActivity(SettingsActivity.class).get();
mController = new AdvancedBluetoothDetailsHeaderController(mContext, "pref_Key");
when(mCachedDevice.getDevice()).thenReturn(mBluetoothDevice);
mController.init(mCachedDevice);
mController.init(mCachedDevice, mFragment);
mLayoutPreference = new LayoutPreference(mContext,
LayoutInflater.from(mContext).inflate(R.layout.advanced_bt_entity_header, null));
mController.mLayoutPreference = mLayoutPreference;
@@ -540,6 +546,22 @@ public class AdvancedBluetoothDetailsHeaderControllerTest {
rightBatteryPrediction);
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void enablePolishFlag_renameButtonShown() {
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("true".getBytes());
Set<CachedBluetoothDevice> cacheBluetoothDevices = new HashSet<>();
when(mCachedDevice.getMemberDevice()).thenReturn(cacheBluetoothDevices);
mController.onStart();
ImageButton button = mLayoutPreference.findViewById(R.id.rename_button);
assertThat(button.getVisibility()).isEqualTo(View.VISIBLE);
}
private void assertBatteryPredictionVisible(LinearLayout linearLayout, int visible) {
final TextView textView = linearLayout.findViewById(R.id.bt_battery_prediction);
assertThat(textView.getVisibility()).isEqualTo(visible);

View File

@@ -0,0 +1,180 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.bluetooth;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.core.SettingsUIDeviceConfig;
import com.android.settings.flags.Flags;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settingslib.bluetooth.LeAudioProfile;
import com.android.settingslib.widget.LayoutPreference;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowDeviceConfig.class})
public class GeneralBluetoothDetailsHeaderControllerTest
extends BluetoothDetailsControllerTestBase {
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private GeneralBluetoothDetailsHeaderController mController;
private LayoutPreference mPreference;
@Mock private BluetoothDevice mBluetoothDevice;
@Mock private LeAudioProfile mLeAudioProfile;
@Override
public void setUp() {
super.setUp();
FakeFeatureFactory.setupForTest();
android.provider.DeviceConfig.setProperty(
android.provider.DeviceConfig.NAMESPACE_SETTINGS_UI,
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED,
"true",
true);
mController =
new GeneralBluetoothDetailsHeaderController(
mContext, mFragment, mCachedDevice, mLifecycle);
mPreference = new LayoutPreference(mContext, R.layout.general_bt_entity_header);
mPreference.setKey(mController.getPreferenceKey());
mScreen.addPreference(mPreference);
setupDevice(mDeviceConfig);
when(mCachedDevice.getDevice()).thenReturn(mBluetoothDevice);
when(mLeAudioProfile.getProfileId()).thenReturn(BluetoothProfile.LE_AUDIO);
}
@After
public void tearDown() {
ShadowEntityHeaderController.reset();
}
/**
* Test to verify the current test context object works so that we are not checking null against
* null
*/
@Test
public void testContextMock() {
assertThat(mContext.getString(com.android.settingslib.R.string.bluetooth_connected))
.isNotNull();
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void header() {
when(mCachedDevice.getName()).thenReturn("device name");
when(mCachedDevice.getConnectionSummary()).thenReturn("Active");
showScreen(mController);
TextView deviceName = mPreference.findViewById(R.id.bt_header_device_name);
TextView summary = mPreference.findViewById(R.id.bt_header_connection_summary);
assertThat(deviceName.getText().toString()).isEqualTo("device name");
assertThat(summary.getText().toString()).isEqualTo("Active");
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void connectionStatusChangesWhileScreenOpen() {
TextView summary = mPreference.findViewById(R.id.bt_header_connection_summary);
when(mCachedDevice.getConnectionSummary())
.thenReturn(
mContext.getString(com.android.settingslib.R.string.bluetooth_connected));
showScreen(mController);
String summaryText1 = summary.getText().toString();
when(mCachedDevice.getConnectionSummary()).thenReturn(null);
mController.onDeviceAttributesChanged();
String summaryText2 = summary.getText().toString();
when(mCachedDevice.getConnectionSummary())
.thenReturn(
mContext.getString(com.android.settingslib.R.string.bluetooth_connecting));
mController.onDeviceAttributesChanged();
String summaryText3 = summary.getText().toString();
assertThat(summaryText1)
.isEqualTo(
mContext.getString(com.android.settingslib.R.string.bluetooth_connected));
assertThat(summaryText2).isEqualTo("");
assertThat(summaryText3)
.isEqualTo(
mContext.getString(com.android.settingslib.R.string.bluetooth_connecting));
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void isAvailable_untetheredHeadset_returnFalse() {
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("true".getBytes());
assertThat(mController.isAvailable()).isFalse();
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void isAvailable_notUntetheredHeadset_returnTrue() {
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("false".getBytes());
assertThat(mController.isAvailable()).isTrue();
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void isAvailable_leAudioDevice_returnFalse() {
when(mCachedDevice.getUiAccessibleProfiles())
.thenReturn(List.of(mLeAudioProfile));
assertThat(mController.isAvailable()).isFalse();
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void isAvailable_flagEnabled_returnTrue() {
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("false".getBytes());
assertThat(mController.isAvailable()).isTrue();
}
@Test
@DisableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void iaAvailable_flagDisabled_returnFalse() {
assertThat(mController.isAvailable()).isFalse();
}
}