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

Commit f970d63b authored by SongFerng Wang's avatar SongFerng Wang Committed by Android (Google) Code Review
Browse files

Merge "Add the way for hiding the "contact sharing" on the pairing dialog" into tm-qpr-dev

parents ee21072a 51cabc55
Loading
Loading
Loading
Loading
+53 −3
Original line number Diff line number Diff line
@@ -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;
    }
}
+3 −4
Original line number Diff line number Diff line
@@ -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;
    }

}
+174 −4
Original line number Diff line number Diff line
@@ -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<LocalBluetoothProfile> 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);
    }
}
+4 −6
Original line number Diff line number Diff line
@@ -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();