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

Commit 490d0201 authored by Hansong Zhang's avatar Hansong Zhang
Browse files

Fix the null check in LocalBluetoothProfileManager

Check mHidDeviceProfile != null before invoking
mHidDeviceProfile.getConnectionStatus()

Bug: 77856868
Test: manual; run LocalBluetoothProfileManagerTest
Change-Id: If3cc7d55265e6734176044e97b32a44e7b1a1a62
parent 5000367d
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.bluetooth.BluetoothUuid;
import android.content.Context;
import android.content.Intent;
import android.os.ParcelUuid;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
import com.android.internal.R;
import java.util.ArrayList;
@@ -41,6 +42,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;


/**
 * LocalBluetoothProfileManager provides access to the LocalBluetoothProfile
 * objects for the available Bluetooth profiles.
@@ -130,7 +132,7 @@ public class LocalBluetoothProfileManager {
        addProfile(mHidProfile, HidProfile.NAME,
                BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);

        mPanProfile = new PanProfile(context);
        mPanProfile = new PanProfile(context, mLocalAdapter);
        addPanProfile(mPanProfile, PanProfile.NAME,
                BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);

@@ -486,6 +488,16 @@ public class LocalBluetoothProfileManager {
        return mHearingAidProfile;
    }

    @VisibleForTesting
    HidProfile getHidProfile() {
        return mHidProfile;
    }

    @VisibleForTesting
    HidDeviceProfile getHidDeviceProfile() {
        return mHidDeviceProfile;
    }

    /**
     * Fill in a list of LocalBluetoothProfile objects that are supported by
     * the local device and the remote device.
@@ -553,7 +565,7 @@ public class LocalBluetoothProfileManager {
            removedProfiles.remove(mHidProfile);
        }

        if (mHidProfile != null && mHidDeviceProfile.getConnectionStatus(device)
        if (mHidDeviceProfile != null && mHidDeviceProfile.getConnectionStatus(device)
                != BluetoothProfile.STATE_DISCONNECTED) {
            profiles.add(mHidDeviceProfile);
            removedProfiles.remove(mHidDeviceProfile);
+5 −4
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ public class PanProfile implements LocalBluetoothProfile {

    private BluetoothPan mService;
    private boolean mIsProfileReady;
    private final LocalBluetoothAdapter mLocalAdapter;

    // Tethering direction for each device
    private final HashMap<BluetoothDevice, Integer> mDeviceRoleMap =
@@ -68,9 +69,9 @@ public class PanProfile implements LocalBluetoothProfile {
        return mIsProfileReady;
    }

    PanProfile(Context context) {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        adapter.getProfileProxy(context, new PanServiceListener(),
    PanProfile(Context context, LocalBluetoothAdapter adapter) {
        mLocalAdapter = adapter;
        mLocalAdapter.getProfileProxy(context, new PanServiceListener(),
            BluetoothProfile.PAN);
    }

+107 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.settingslib.bluetooth;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.when;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothUuid;
import android.content.Context;
import android.os.ParcelUuid;

import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;

@RunWith(RobolectricTestRunner.class)
@Config(resourceDir = "../../res")
public class LocalBluetoothProfileManagerTest {
    @Mock private CachedBluetoothDeviceManager mDeviceManager;
    @Mock private BluetoothEventManager mEventManager;
    @Mock private LocalBluetoothAdapter mAdapter;
    @Mock private BluetoothDevice mDevice;
    private Context mContext;
    private LocalBluetoothProfileManager mProfileManager;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContext = RuntimeEnvironment.application;
        when(mAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
    }

    /**
     * Verify HID and HID Device profiles are not null without running updateUuids()
     */
    @Test
    public void constructor_initiateHidAndHidDeviceProfile() {
        mProfileManager =
                new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);

        assertThat(mProfileManager.getHidProfile()).isNotNull();
        assertThat(mProfileManager.getHidDeviceProfile()).isNotNull();
    }

    /**
     * Verify updateLocalProfiles() for a local A2DP source adds A2dpProfile
     */
    @Test
    public void updateLocalProfiles_addA2dpToLocalProfiles() {
        mProfileManager =
                new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
        when(mAdapter.getUuids()).thenReturn(new ParcelUuid[] {BluetoothUuid.AudioSource});
        assertThat(mProfileManager.getA2dpProfile()).isNull();
        assertThat(mProfileManager.getHeadsetProfile()).isNull();

        ParcelUuid[] uuids = mAdapter.getUuids();
        mProfileManager.updateLocalProfiles(uuids);

        assertThat(mProfileManager.getA2dpProfile()).isNotNull();
        assertThat(mProfileManager.getHeadsetProfile()).isNull();
    }

    /**
     * Verify updateProfiles() for a remote HID device updates profiles and removedProfiles
     */
    @Test
    public void updateProfiles_addHidProfileForRemoteDevice() {
        mProfileManager =
                new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
        ParcelUuid[] uuids = new ParcelUuid[]{BluetoothUuid.Hid};
        ParcelUuid[] localUuids = new ParcelUuid[]{};
        List<LocalBluetoothProfile> profiles = new ArrayList<>();
        List<LocalBluetoothProfile> removedProfiles = new ArrayList<>();

        mProfileManager.updateProfiles(uuids, localUuids, profiles, removedProfiles, false,
                mDevice);

        assertThat(mProfileManager.getHidProfile()).isNotNull();
        assertThat(profiles.contains(mProfileManager.getHidProfile())).isTrue();
        assertThat(removedProfiles.contains(mProfileManager.getHidProfile())).isFalse();
    }
}