From 51cabc55532d125ed7ec1fce88adb3bce997b921 Mon Sep 17 00:00:00 2001 From: SongFerngWang Date: Fri, 23 Sep 2022 21:21:25 +0800 Subject: [PATCH] Add the way for hiding the "contact sharing" on the pairing dialog There is the way to hide the "contact sharing" at the "device details" page, but it did not be implemented on the pairing dialog. Add this way on pairing dialog. Bug: 246668278 Test: make RunSettingsRoboTests ROBOTEST_FILTER=BluetoothPairingControllerTest make RunSettingsRoboTests ROBOTEST_FILTER=BluetoothPairingDialogTest Change-Id: I472acb80e70fe5d2a59cb9eed95fcbccfa417fa5 --- .../bluetooth/BluetoothPairingController.java | 56 +++++- .../BluetoothPairingDialogFragment.java | 7 +- .../BluetoothPairingControllerTest.java | 178 +++++++++++++++++- .../bluetooth/BluetoothPairingDialogTest.java | 10 +- 4 files changed, 234 insertions(+), 17 deletions(-) diff --git a/src/com/android/settings/bluetooth/BluetoothPairingController.java b/src/com/android/settings/bluetooth/BluetoothPairingController.java index c70a56ab866..a9e89e914cb 100644 --- a/src/com/android/settings/bluetooth/BluetoothPairingController.java +++ b/src/com/android/settings/bluetooth/BluetoothPairingController.java @@ -17,8 +17,10 @@ package com.android.settings.bluetooth; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; +import android.provider.DeviceConfig; import android.text.Editable; import android.util.Log; import android.widget.CompoundButton; @@ -28,6 +30,7 @@ import androidx.annotation.VisibleForTesting; import com.android.settings.R; import com.android.settings.bluetooth.BluetoothPairingDialogFragment.BluetoothPairingDialogListener; +import com.android.settings.core.SettingsUIDeviceConfig; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfile; @@ -54,7 +57,7 @@ public class BluetoothPairingController implements OnCheckedChangeListener, private static final int BLUETOOTH_PASSKEY_MAX_LENGTH = 6; // Bluetooth dependencies for the connection we are trying to establish - private LocalBluetoothManager mBluetoothManager; + LocalBluetoothManager mBluetoothManager; private BluetoothDevice mDevice; @VisibleForTesting int mType; @@ -66,6 +69,8 @@ public class BluetoothPairingController implements OnCheckedChangeListener, private LocalBluetoothProfile mPbapClientProfile; private boolean mPbapAllowed; private boolean mIsCoordinatedSetMember; + private boolean mIsLeAudio; + private boolean mIsLeContactSharingEnabled; /** * Creates an instance of a BluetoothPairingController. @@ -92,10 +97,26 @@ public class BluetoothPairingController implements OnCheckedChangeListener, mDeviceName = mBluetoothManager.getCachedDeviceManager().getName(mDevice); mPbapClientProfile = mBluetoothManager.getProfileManager().getPbapClientProfile(); mPasskeyFormatted = formatKey(mPasskey); + final CachedBluetoothDevice cachedDevice = mBluetoothManager.getCachedDeviceManager().findDevice(mDevice); - mIsCoordinatedSetMember = cachedDevice != null - ? cachedDevice.isCoordinatedSetMemberDevice() : false; + + mIsCoordinatedSetMember = false; + mIsLeAudio = false; + mIsLeContactSharingEnabled = true; + if (cachedDevice != null) { + mIsCoordinatedSetMember = cachedDevice.isCoordinatedSetMemberDevice(); + + for (LocalBluetoothProfile profile : cachedDevice.getProfiles()) { + if (profile.getProfileId() == BluetoothProfile.LE_AUDIO) { + mIsLeAudio = true; + } + } + + mIsLeContactSharingEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI, + SettingsUIDeviceConfig.BT_LE_AUDIO_CONTACT_SHARING_ENABLED, true); + Log.d(TAG, "BT_LE_AUDIO_CONTACT_SHARING_ENABLED is " + mIsLeContactSharingEnabled); + } } @Override @@ -180,6 +201,30 @@ public class BluetoothPairingController implements OnCheckedChangeListener, return mPbapClientProfile != null && mPbapClientProfile.isProfileReady(); } + @VisibleForTesting + boolean isLeAudio() { + return mIsLeAudio; + } + + @VisibleForTesting + boolean isLeContactSharingEnabled() { + return mIsLeContactSharingEnabled; + } + + /** + * A method whether the device allows to show the le audio's contact sharing. + * + * @return A boolean whether the device allows to show the contact sharing. + */ + public boolean isContactSharingVisible() { + boolean isContactSharingVisible = !isProfileReady(); + // If device do not support the ContactSharing of LE audio device, hiding ContactSharing UI + if (isLeAudio() && !isLeContactSharingEnabled()) { + isContactSharingVisible = false; + } + return isContactSharingVisible; + } + /** * A method for querying if the bluetooth device has access to contacts on the device. * @@ -447,4 +492,9 @@ public class BluetoothPairingController implements OnCheckedChangeListener, public boolean deviceEquals(BluetoothDevice device) { return mDevice == device; } + + @VisibleForTesting + void mockPbapClientProfile(LocalBluetoothProfile mockPbapClientProfile) { + mPbapClientProfile = mockPbapClientProfile; + } } diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java index 8dd00b389ed..bae2471dd9b 100644 --- a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java +++ b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java @@ -254,8 +254,8 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i mPairingController.getDeviceName())); EditText pairingView = (EditText) view.findViewById(R.id.text); - contactSharing.setVisibility(mPairingController.isProfileReady() - ? View.GONE : View.VISIBLE); + contactSharing.setVisibility( + mPairingController.isContactSharingVisible() ? View.VISIBLE : View.GONE); mPairingController.setContactSharingState(); contactSharing.setOnCheckedChangeListener(mPairingController); contactSharing.setChecked(mPairingController.getContactSharingState()); @@ -346,7 +346,7 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i mPairingController.getDeviceName())); contactSharing.setVisibility( - mPairingController.isProfileReady() ? View.GONE : View.VISIBLE); + mPairingController.isContactSharingVisible() ? View.VISIBLE : View.GONE); mPairingController.setContactSharingState(); contactSharing.setChecked(mPairingController.getContactSharingState()); contactSharing.setOnCheckedChangeListener(mPairingController); @@ -363,5 +363,4 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i ? View.VISIBLE : View.GONE); return view; } - } diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingControllerTest.java index 88e15ebc13e..a7dc17da0e0 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingControllerTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingControllerTest.java @@ -17,16 +17,28 @@ package com.android.settings.bluetooth; import static android.bluetooth.BluetoothDevice.PAIRING_VARIANT_CONSENT; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.os.Parcel; +import com.android.settings.core.SettingsUIDeviceConfig; import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; +import com.android.settings.testutils.shadow.ShadowBluetoothUtils; +import com.android.settings.testutils.shadow.ShadowDeviceConfig; +import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; +import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.bluetooth.LocalBluetoothProfile; +import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import org.junit.Before; import org.junit.Test; @@ -36,16 +48,36 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; + +import java.util.ArrayList; +import java.util.List; @RunWith(RobolectricTestRunner.class) -@Config(shadows = {ShadowBluetoothAdapter.class}) +@Config(shadows = {ShadowBluetoothAdapter.class, ShadowBluetoothUtils.class, + ShadowDeviceConfig.class}) public class BluetoothPairingControllerTest { private final BluetoothClass mBluetoothClass = createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE); + + @Mock + private CachedBluetoothDeviceManager mCachedDeviceManager; + @Mock + private LocalBluetoothManager mLocalBluetoothManager; + @Mock + private LocalBluetoothProfileManager mLocalBluetoothProfileManager; @Mock private BluetoothDevice mBluetoothDevice; + @Mock + private CachedBluetoothDevice mCachedDevice; + @Mock + private LocalBluetoothProfile mLocalBluetoothProfile; + @Mock + private LocalBluetoothProfile mPbapLocalBluetoothProfile; + private Context mContext; private BluetoothPairingController mBluetoothPairingController; + private ShadowBluetoothAdapter mShadowBluetoothAdapter; private BluetoothClass createBtClass(int deviceClass) { Parcel p = Parcel.obtain(); @@ -57,14 +89,32 @@ public class BluetoothPairingControllerTest { return bluetoothClass; } + private BluetoothPairingController createBluetoothPairingController() { + final Intent intent = new Intent(); + intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice); + return new BluetoothPairingController(intent, mContext); + } + @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; - final Intent intent = new Intent(); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice); - mBluetoothPairingController = new BluetoothPairingController(intent, mContext); + mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); + mShadowBluetoothAdapter.setEnabled(true); + ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager; + mLocalBluetoothManager = Utils.getLocalBtManager(mContext); + when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager); + when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); + when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedDevice); + List localBluetoothProfiles = new ArrayList<>(); + mockIsLeAudio(false); + localBluetoothProfiles.add(mLocalBluetoothProfile); + when(mCachedDevice.getProfiles()).thenReturn(localBluetoothProfiles); + when(mCachedDevice.getDevice()).thenReturn(mBluetoothDevice); + + mBluetoothPairingController = createBluetoothPairingController(); + mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); } @Test @@ -108,4 +158,124 @@ public class BluetoothPairingControllerTest { verify(mBluetoothDevice).setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED); } + + @Test + public void isLeAudio_noLeProfile_returnsFalse() { + mockIsLeAudio(false); + + mBluetoothPairingController = createBluetoothPairingController(); + + assertThat(mBluetoothPairingController.isLeAudio()).isFalse(); + } + + @Test + public void isLeAudio_isLeProfile_returnsTrue() { + mockIsLeAudio(true); + + mBluetoothPairingController = createBluetoothPairingController(); + + assertThat(mBluetoothPairingController.isLeAudio()).isTrue(); + } + + @Test + public void isLeContactSharingEnabled_configIsFalse_returnsFalse() { + mockIsLeContactSharingEnabled(false); + + mBluetoothPairingController = createBluetoothPairingController(); + + assertThat(mBluetoothPairingController.isLeContactSharingEnabled()).isFalse(); + } + + @Test + public void isLeContactSharingEnabled_configIsTrue_returnsTrue() { + mockIsLeContactSharingEnabled(true); + + mBluetoothPairingController = createBluetoothPairingController(); + + assertThat(mBluetoothPairingController.isLeContactSharingEnabled()).isTrue(); + } + + @Test + public void isContactSharingVisible_profileIsNotReady_returnsTrue() { + // isProfileReady=false, isLeAudio=false, isLeContactSharingEnabled=true + mockIsProfileReady(false); + mockIsLeAudio(false); + mockIsLeContactSharingEnabled(true); + + mBluetoothPairingController = createBluetoothPairingController(); + mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); + + assertThat(mBluetoothPairingController.isContactSharingVisible()).isTrue(); + } + + @Test + public void isContactSharingVisible_profileIsReady_returnsFalse() { + // isProfileReady=true, isLeAudio=false, isLeContactSharingEnabled=true + mockIsProfileReady(true); + mockIsLeAudio(false); + mockIsLeContactSharingEnabled(true); + + mBluetoothPairingController = createBluetoothPairingController(); + mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); + + assertThat(mBluetoothPairingController.isContactSharingVisible()).isFalse(); + } + + @Test + public void isContactSharingVisible_DeviceIsLeAudioAndProfileIsReady_returnsFalse() { + // isProfileReady=true, isLeAudio=true, isLeContactSharingEnabled=true + mockIsProfileReady(true); + mockIsLeAudio(true); + mockIsLeContactSharingEnabled(true); + + mBluetoothPairingController = createBluetoothPairingController(); + mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); + + assertThat(mBluetoothPairingController.isContactSharingVisible()).isFalse(); + } + + @Test + public void isContactSharingVisible_DeviceIsLeAudioAndProfileIsNotReady_returnsTrue() { + // isProfileReady=false, isLeAudio=true, isLeContactSharingEnabled=true + mockIsProfileReady(false); + mockIsLeAudio(true); + mockIsLeContactSharingEnabled(true); + + mBluetoothPairingController = createBluetoothPairingController(); + mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); + + assertThat(mBluetoothPairingController.isContactSharingVisible()).isTrue(); + } + + @Test + public void isContactSharingVisible_DeviceIsLeAndContactSharingIsNotEnabled_returnsFalse() { + // isProfileReady=false, isLeAudio=true, isLeContactSharingEnabled=false + mockIsProfileReady(false); + mockIsLeAudio(true); + mockIsLeContactSharingEnabled(false); + + mBluetoothPairingController = createBluetoothPairingController(); + mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); + + assertThat(mBluetoothPairingController.isContactSharingVisible()).isFalse(); + } + + private void mockIsProfileReady(boolean mockValue) { + when(mPbapLocalBluetoothProfile.isProfileReady()).thenReturn(mockValue); + } + + private void mockIsLeAudio(boolean mockValue) { + int profileId = BluetoothProfile.HEADSET; + if (mockValue) { + profileId = BluetoothProfile.LE_AUDIO; + } + when(mLocalBluetoothProfile.getProfileId()).thenReturn(profileId); + } + + private void mockIsLeContactSharingEnabled(boolean mockValue) { + android.provider.DeviceConfig.setProperty( + android.provider.DeviceConfig.NAMESPACE_SETTINGS_UI, + SettingsUIDeviceConfig.BT_LE_AUDIO_CONTACT_SHARING_ENABLED, + /* value= */ mockValue ? "true" : "false", true); + } } diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java index a53e693976e..874ddf0d158 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java @@ -274,13 +274,12 @@ public class BluetoothPairingDialogTest { } @Test - public void dialogShowsContactSharingCheckboxWhenBluetoothProfileNotReady() { + public void contactSharingCheckbox_conditionIsReady_showsUi() { // set the dialog variant to confirmation/consent when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG); - // set a fake device name and pretend the profile has not been set up for it when(controller.getDeviceName()).thenReturn(FAKE_DEVICE_NAME); - when(controller.isProfileReady()).thenReturn(false); + when(controller.isContactSharingVisible()).thenReturn(true); // build the fragment BluetoothPairingDialogFragment frag = makeFragment(); @@ -292,13 +291,12 @@ public class BluetoothPairingDialogTest { } @Test - public void dialogHidesContactSharingCheckboxWhenBluetoothProfileIsReady() { + public void contactSharingCheckbox_conditionIsNotReady_doesNotShowUi() { // set the dialog variant to confirmation/consent when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG); - // set a fake device name and pretend the profile has been set up for it when(controller.getDeviceName()).thenReturn(FAKE_DEVICE_NAME); - when(controller.isProfileReady()).thenReturn(true); + when(controller.isContactSharingVisible()).thenReturn(false); // build the fragment BluetoothPairingDialogFragment frag = makeFragment();