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

Commit 55769475 authored by Tom Hsu's avatar Tom Hsu Committed by Android (Google) Code Review
Browse files

Merge "[Settings] Avoid NPE if BT device is changed by framework." into udc-dev

parents c8c19902 06176314
Loading
Loading
Loading
Loading
+39 −12
Original line number Diff line number Diff line
@@ -57,7 +57,9 @@ import com.android.settingslib.widget.LayoutPreference;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
@@ -92,6 +94,7 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
    @VisibleForTesting
    final Map<String, Bitmap> mIconCache;
    private CachedBluetoothDevice mCachedDevice;
    private Set<BluetoothDevice> mBluetoothDevices;
    @VisibleForTesting
    BluetoothAdapter mBluetoothAdapter;
    @VisibleForTesting
@@ -141,23 +144,13 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
        if (!isAvailable()) {
            return;
        }
        mIsRegisterCallback = true;
        mCachedDevice.registerCallback(this);
        mBluetoothAdapter.addOnMetadataChangedListener(mCachedDevice.getDevice(),
                mContext.getMainExecutor(), mMetadataListener);

        registerBluetoothDevice();
        refresh();
    }

    @Override
    public void onStop() {
        if (!mIsRegisterCallback) {
            return;
        }
        mCachedDevice.unregisterCallback(this);
        mBluetoothAdapter.removeOnMetadataChangedListener(mCachedDevice.getDevice(),
                mMetadataListener);
        mIsRegisterCallback = false;
        unRegisterBluetoothDevice();
    }

    @Override
@@ -175,6 +168,40 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
        mCachedDevice = cachedBluetoothDevice;
    }

    private void registerBluetoothDevice() {
        if (mBluetoothDevices == null) {
            mBluetoothDevices = new HashSet<>();
        }
        mBluetoothDevices.clear();
        if (mCachedDevice.getDevice() != null) {
            mBluetoothDevices.add(mCachedDevice.getDevice());
        }
        mCachedDevice.getMemberDevice().forEach(cbd -> {
            if (cbd != null) {
                mBluetoothDevices.add(cbd.getDevice());
            }
        });
        if (mBluetoothDevices.isEmpty()) {
            Log.d(TAG, "No BT devcie to register.");
            return;
        }
        mCachedDevice.registerCallback(this);
        mBluetoothDevices.forEach(bd ->
                mBluetoothAdapter.addOnMetadataChangedListener(bd,
                        mContext.getMainExecutor(), mMetadataListener));
    }

    private void unRegisterBluetoothDevice() {
        if (mBluetoothDevices == null || mBluetoothDevices.isEmpty()) {
            Log.d(TAG, "No BT devcie to unregister.");
            return;
        }
        mCachedDevice.unregisterCallback(this);
        mBluetoothDevices.forEach(bd -> mBluetoothAdapter.removeOnMetadataChangedListener(bd,
                mMetadataListener));
        mBluetoothDevices.clear();
    }

    @VisibleForTesting
    void refresh() {
        if (mLayoutPreference != null && mCachedDevice != null) {
+40 −9
Original line number Diff line number Diff line
@@ -56,6 +56,9 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;

import java.util.HashSet;
import java.util.Set;

@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowEntityHeaderController.class, ShadowDeviceConfig.class})
public class AdvancedBluetoothDetailsHeaderControllerTest {
@@ -380,40 +383,68 @@ public class AdvancedBluetoothDetailsHeaderControllerTest {
                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();

        verify(mCachedDevice).registerCallback(mController);
        verify(mBluetoothAdapter).addOnMetadataChangedListener(mBluetoothDevice,
                mContext.getMainExecutor(), mController.mMetadataListener);
    }

    @Test
    public void onStop_isRegisterCallback_unregisterCallback() {
        mController.mIsRegisterCallback = true;
    public void onStart_notAvailable_notNeedToRegisterCallback() {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
                .thenReturn("false".getBytes());

        mController.onStop();
        mController.onStart();

        verify(mBluetoothAdapter).removeOnMetadataChangedListener(mBluetoothDevice,
                mController.mMetadataListener);
        verify(mCachedDevice, never()).registerCallback(mController);
        verify(mBluetoothAdapter, never()).addOnMetadataChangedListener(mBluetoothDevice,
                mContext.getMainExecutor(), mController.mMetadataListener);
    }

    @Test
    public void onStart_notAvailable_registerCallback() {
    public void onStart_isAvailableButNoBluetoothDevice_notNeedToRegisterCallback() {
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
                SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
                .thenReturn("false".getBytes());
                .thenReturn("true".getBytes());
        when(mCachedDevice.getDevice()).thenReturn(null);
        Set<CachedBluetoothDevice> cacheBluetoothDevices = new HashSet<>();
        when(mCachedDevice.getMemberDevice()).thenReturn(cacheBluetoothDevices);

        mController.onStart();

        verify(mCachedDevice, never()).registerCallback(mController);
        verify(mBluetoothAdapter, never()).addOnMetadataChangedListener(mBluetoothDevice,
                mContext.getMainExecutor(), mController.mMetadataListener);
    }

    @Test
    public void onStop_notRegisterCallback_unregisterCallback() {
        mController.mIsRegisterCallback = false;
    public void onStop_availableAndHasBluetoothDevice_unregisterCallback() {
        onStart_isAvailable_registerCallback();

        mController.onStop();

        verify(mCachedDevice).unregisterCallback(mController);
        verify(mBluetoothAdapter).removeOnMetadataChangedListener(mBluetoothDevice,
                mController.mMetadataListener);
    }

    @Test
    public void onStop_noBluetoothDevice_noNeedToUnregisterCallback() {
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
                SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
                .thenReturn("true".getBytes());
        when(mCachedDevice.getDevice()).thenReturn(null);

        mController.onStart();
        mController.onStop();

        verify(mCachedDevice, never()).unregisterCallback(mController);
        verify(mBluetoothAdapter, never()).removeOnMetadataChangedListener(mBluetoothDevice,
                mController.mMetadataListener);
    }