blob: 5ddf14f177299323ac0d8cb239ffb33de9e83a67 [file] [log] [blame]
/*
* Copyright 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.bluetooth.btservice;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.os.Looper;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.rule.ServiceTestRule;
import androidx.test.runner.AndroidJUnit4;
import com.android.bluetooth.TestUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.concurrent.TimeoutException;
@MediumTest
@RunWith(AndroidJUnit4.class)
public class ProfileServiceTest {
private static final int PROFILE_START_MILLIS = 1250;
private static final int NUM_REPEATS = 5;
@Rule public final ServiceTestRule mServiceTestRule = new ServiceTestRule();
private void setProfileState(Class profile, int state) throws TimeoutException {
Intent startIntent = new Intent(InstrumentationRegistry.getTargetContext(), profile);
startIntent.putExtra(AdapterService.EXTRA_ACTION,
AdapterService.ACTION_SERVICE_STATE_CHANGED);
startIntent.putExtra(BluetoothAdapter.EXTRA_STATE, state);
mServiceTestRule.startService(startIntent);
}
private void setAllProfilesState(int state, int invocationNumber) throws TimeoutException {
for (Class profile : mProfiles) {
setProfileState(profile, state);
}
ArgumentCaptor<ProfileService> argument = ArgumentCaptor.forClass(ProfileService.class);
verify(mMockAdapterService, timeout(PROFILE_START_MILLIS).times(
mProfiles.length * invocationNumber)).onProfileServiceStateChanged(
argument.capture(), eq(state));
List<ProfileService> argumentProfiles = argument.getAllValues();
for (Class profile : mProfiles) {
int matches = 0;
for (ProfileService arg : argumentProfiles) {
if (arg.getClass().getName().equals(profile.getName())) {
matches += 1;
}
}
Assert.assertEquals(invocationNumber, matches);
}
}
private @Mock AdapterService mMockAdapterService;
private Class[] mProfiles;
@Before
public void setUp()
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
if (Looper.myLooper() == null) {
Looper.prepare();
}
Assert.assertNotNull(Looper.myLooper());
MockitoAnnotations.initMocks(this);
mProfiles = Config.getSupportedProfiles();
mMockAdapterService.initNative(false /* is_restricted */, false /* is_single_user_mode */,
false);
TestUtils.setAdapterService(mMockAdapterService);
Assert.assertNotNull(AdapterService.getAdapterService());
}
@After
public void tearDown()
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
mMockAdapterService.cleanupNative();
TestUtils.clearAdapterService(mMockAdapterService);
mMockAdapterService = null;
mProfiles = null;
}
/**
* Test: Start the Bluetooth services that are configured.
* Verify that the same services start.
*/
@Test
public void testEnableDisable() throws TimeoutException {
setAllProfilesState(BluetoothAdapter.STATE_ON, 1);
setAllProfilesState(BluetoothAdapter.STATE_OFF, 1);
}
/**
* Test: Start the Bluetooth services that are configured twice.
* Verify that the services start.
*/
@Test
public void testEnableDisableTwice() throws TimeoutException {
setAllProfilesState(BluetoothAdapter.STATE_ON, 1);
setAllProfilesState(BluetoothAdapter.STATE_OFF, 1);
setAllProfilesState(BluetoothAdapter.STATE_ON, 2);
setAllProfilesState(BluetoothAdapter.STATE_OFF, 2);
}
/**
* Test: Start the Bluetooth services that are configured.
* Verify that each profile starts and stops.
*/
@Test
public void testEnableDisableInterleaved() throws TimeoutException {
for (Class profile : mProfiles) {
setProfileState(profile, BluetoothAdapter.STATE_ON);
setProfileState(profile, BluetoothAdapter.STATE_OFF);
}
ArgumentCaptor<ProfileService> starts = ArgumentCaptor.forClass(ProfileService.class);
ArgumentCaptor<ProfileService> stops = ArgumentCaptor.forClass(ProfileService.class);
int invocationNumber = mProfiles.length;
verify(mMockAdapterService,
timeout(PROFILE_START_MILLIS).times(invocationNumber)).onProfileServiceStateChanged(
starts.capture(), eq(BluetoothAdapter.STATE_ON));
verify(mMockAdapterService,
timeout(PROFILE_START_MILLIS).times(invocationNumber)).onProfileServiceStateChanged(
stops.capture(), eq(BluetoothAdapter.STATE_OFF));
List<ProfileService> startedArguments = starts.getAllValues();
List<ProfileService> stoppedArguments = stops.getAllValues();
Assert.assertEquals(startedArguments.size(), stoppedArguments.size());
for (ProfileService service : startedArguments) {
Assert.assertTrue(stoppedArguments.contains(service));
stoppedArguments.remove(service);
Assert.assertFalse(stoppedArguments.contains(service));
}
}
/**
* Test: Start and stop a single profile repeatedly.
* Verify that the profiles start and stop.
*/
@Test
public void testRepeatedEnableDisableSingly() throws TimeoutException {
int profileNumber = 0;
for (Class profile : mProfiles) {
for (int i = 0; i < NUM_REPEATS; i++) {
setProfileState(profile, BluetoothAdapter.STATE_ON);
ArgumentCaptor<ProfileService> start =
ArgumentCaptor.forClass(ProfileService.class);
verify(mMockAdapterService, timeout(PROFILE_START_MILLIS).times(
NUM_REPEATS * profileNumber + i + 1)).onProfileServiceStateChanged(
start.capture(), eq(BluetoothAdapter.STATE_ON));
setProfileState(profile, BluetoothAdapter.STATE_OFF);
ArgumentCaptor<ProfileService> stop = ArgumentCaptor.forClass(ProfileService.class);
verify(mMockAdapterService, timeout(PROFILE_START_MILLIS).times(
NUM_REPEATS * profileNumber + i + 1)).onProfileServiceStateChanged(
stop.capture(), eq(BluetoothAdapter.STATE_OFF));
Assert.assertEquals(start.getValue(), stop.getValue());
}
profileNumber += 1;
}
}
/**
* Test: Start and stop a single profile repeatedly and verify that the profile services are
* registered and unregistered accordingly.
*/
@Test
public void testProfileServiceRegisterUnregister() throws TimeoutException {
int profileNumber = 0;
for (Class profile : mProfiles) {
for (int i = 0; i < NUM_REPEATS; i++) {
setProfileState(profile, BluetoothAdapter.STATE_ON);
ArgumentCaptor<ProfileService> start =
ArgumentCaptor.forClass(ProfileService.class);
verify(mMockAdapterService, timeout(PROFILE_START_MILLIS).times(
NUM_REPEATS * profileNumber + i + 1)).addProfile(
start.capture());
setProfileState(profile, BluetoothAdapter.STATE_OFF);
ArgumentCaptor<ProfileService> stop = ArgumentCaptor.forClass(ProfileService.class);
verify(mMockAdapterService, timeout(PROFILE_START_MILLIS).times(
NUM_REPEATS * profileNumber + i + 1)).removeProfile(
stop.capture());
Assert.assertEquals(start.getValue(), stop.getValue());
}
profileNumber += 1;
}
}
}