• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bluetooth.btservice;
18 
19 import static org.mockito.ArgumentMatchers.eq;
20 import static org.mockito.Mockito.*;
21 
22 import android.bluetooth.BluetoothAdapter;
23 import android.content.Intent;
24 import android.os.Looper;
25 import android.support.test.InstrumentationRegistry;
26 import android.support.test.filters.MediumTest;
27 import android.support.test.rule.ServiceTestRule;
28 import android.support.test.runner.AndroidJUnit4;
29 
30 import com.android.bluetooth.TestUtils;
31 
32 import org.junit.After;
33 import org.junit.Assert;
34 import org.junit.Before;
35 import org.junit.Rule;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.mockito.ArgumentCaptor;
39 import org.mockito.Mock;
40 import org.mockito.MockitoAnnotations;
41 
42 import java.lang.reflect.InvocationTargetException;
43 import java.util.List;
44 import java.util.concurrent.TimeoutException;
45 
46 @MediumTest
47 @RunWith(AndroidJUnit4.class)
48 public class ProfileServiceTest {
49     private static final int PROFILE_START_MILLIS = 1250;
50     private static final int NUM_REPEATS = 5;
51 
52     @Rule public final ServiceTestRule mServiceTestRule = new ServiceTestRule();
53 
setProfileState(Class profile, int state)54     private void setProfileState(Class profile, int state) throws TimeoutException {
55         Intent startIntent = new Intent(InstrumentationRegistry.getTargetContext(), profile);
56         startIntent.putExtra(AdapterService.EXTRA_ACTION,
57                 AdapterService.ACTION_SERVICE_STATE_CHANGED);
58         startIntent.putExtra(BluetoothAdapter.EXTRA_STATE, state);
59         mServiceTestRule.startService(startIntent);
60     }
61 
setAllProfilesState(int state, int invocationNumber)62     private void setAllProfilesState(int state, int invocationNumber) throws TimeoutException {
63         for (Class profile : mProfiles) {
64             setProfileState(profile, state);
65         }
66         ArgumentCaptor<ProfileService> argument = ArgumentCaptor.forClass(ProfileService.class);
67         verify(mMockAdapterService, timeout(PROFILE_START_MILLIS).times(
68                 mProfiles.length * invocationNumber)).onProfileServiceStateChanged(
69                 argument.capture(), eq(state));
70         List<ProfileService> argumentProfiles = argument.getAllValues();
71         for (Class profile : mProfiles) {
72             int matches = 0;
73             for (ProfileService arg : argumentProfiles) {
74                 if (arg.getClass().getName().equals(profile.getName())) {
75                     matches += 1;
76                 }
77             }
78             Assert.assertEquals(invocationNumber, matches);
79         }
80     }
81 
82     private @Mock AdapterService mMockAdapterService;
83 
84     private Class[] mProfiles;
85 
86     @Before
setUp()87     public void setUp()
88             throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
89         if (Looper.myLooper() == null) {
90             Looper.prepare();
91         }
92         Assert.assertNotNull(Looper.myLooper());
93 
94         MockitoAnnotations.initMocks(this);
95 
96         mProfiles = Config.getSupportedProfiles();
97 
98         mMockAdapterService.initNative();
99 
100         TestUtils.setAdapterService(mMockAdapterService);
101 
102         Assert.assertNotNull(AdapterService.getAdapterService());
103     }
104 
105     @After
tearDown()106     public void tearDown()
107             throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
108         mMockAdapterService.cleanupNative();
109         TestUtils.clearAdapterService(mMockAdapterService);
110         mMockAdapterService = null;
111         mProfiles = null;
112     }
113 
114     /**
115      * Test: Start the Bluetooth services that are configured.
116      * Verify that the same services start.
117      */
118     @Test
testEnableDisable()119     public void testEnableDisable() throws TimeoutException {
120         setAllProfilesState(BluetoothAdapter.STATE_ON, 1);
121         setAllProfilesState(BluetoothAdapter.STATE_OFF, 1);
122     }
123 
124     /**
125      * Test: Start the Bluetooth services that are configured twice.
126      * Verify that the services start.
127      */
128     @Test
testEnableDisableTwice()129     public void testEnableDisableTwice() throws TimeoutException {
130         setAllProfilesState(BluetoothAdapter.STATE_ON, 1);
131         setAllProfilesState(BluetoothAdapter.STATE_OFF, 1);
132         setAllProfilesState(BluetoothAdapter.STATE_ON, 2);
133         setAllProfilesState(BluetoothAdapter.STATE_OFF, 2);
134     }
135 
136     /**
137      * Test: Start the Bluetooth services that are configured.
138      * Verify that each profile starts and stops.
139      */
140     @Test
testEnableDisableInterleaved()141     public void testEnableDisableInterleaved() throws TimeoutException {
142         for (Class profile : mProfiles) {
143             setProfileState(profile, BluetoothAdapter.STATE_ON);
144             setProfileState(profile, BluetoothAdapter.STATE_OFF);
145         }
146         ArgumentCaptor<ProfileService> starts = ArgumentCaptor.forClass(ProfileService.class);
147         ArgumentCaptor<ProfileService> stops = ArgumentCaptor.forClass(ProfileService.class);
148         int invocationNumber = mProfiles.length;
149         verify(mMockAdapterService,
150                 timeout(PROFILE_START_MILLIS).times(invocationNumber)).onProfileServiceStateChanged(
151                 starts.capture(), eq(BluetoothAdapter.STATE_ON));
152         verify(mMockAdapterService,
153                 timeout(PROFILE_START_MILLIS).times(invocationNumber)).onProfileServiceStateChanged(
154                 stops.capture(), eq(BluetoothAdapter.STATE_OFF));
155 
156         List<ProfileService> startedArguments = starts.getAllValues();
157         List<ProfileService> stoppedArguments = stops.getAllValues();
158         Assert.assertEquals(startedArguments.size(), stoppedArguments.size());
159         for (ProfileService service : startedArguments) {
160             Assert.assertTrue(stoppedArguments.contains(service));
161             stoppedArguments.remove(service);
162             Assert.assertFalse(stoppedArguments.contains(service));
163         }
164     }
165 
166     /**
167      * Test: Start and stop a single profile repeatedly.
168      * Verify that the profiles start and stop.
169      */
170     @Test
testRepeatedEnableDisableSingly()171     public void testRepeatedEnableDisableSingly() throws TimeoutException {
172         int profileNumber = 0;
173         for (Class profile : mProfiles) {
174             for (int i = 0; i < NUM_REPEATS; i++) {
175                 setProfileState(profile, BluetoothAdapter.STATE_ON);
176                 ArgumentCaptor<ProfileService> start =
177                         ArgumentCaptor.forClass(ProfileService.class);
178                 verify(mMockAdapterService, timeout(PROFILE_START_MILLIS).times(
179                         NUM_REPEATS * profileNumber + i + 1)).onProfileServiceStateChanged(
180                         start.capture(), eq(BluetoothAdapter.STATE_ON));
181                 setProfileState(profile, BluetoothAdapter.STATE_OFF);
182                 ArgumentCaptor<ProfileService> stop = ArgumentCaptor.forClass(ProfileService.class);
183                 verify(mMockAdapterService, timeout(PROFILE_START_MILLIS).times(
184                         NUM_REPEATS * profileNumber + i + 1)).onProfileServiceStateChanged(
185                         stop.capture(), eq(BluetoothAdapter.STATE_OFF));
186                 Assert.assertEquals(start.getValue(), stop.getValue());
187             }
188             profileNumber += 1;
189         }
190     }
191 
192     /**
193      * Test: Start and stop a single profile repeatedly and verify that the profile services are
194      * registered and unregistered accordingly.
195      */
196     @Test
testProfileServiceRegisterUnregister()197     public void testProfileServiceRegisterUnregister() throws TimeoutException {
198         int profileNumber = 0;
199         for (Class profile : mProfiles) {
200             for (int i = 0; i < NUM_REPEATS; i++) {
201                 setProfileState(profile, BluetoothAdapter.STATE_ON);
202                 ArgumentCaptor<ProfileService> start =
203                         ArgumentCaptor.forClass(ProfileService.class);
204                 verify(mMockAdapterService, timeout(PROFILE_START_MILLIS).times(
205                         NUM_REPEATS * profileNumber + i + 1)).addProfile(
206                         start.capture());
207                 setProfileState(profile, BluetoothAdapter.STATE_OFF);
208                 ArgumentCaptor<ProfileService> stop = ArgumentCaptor.forClass(ProfileService.class);
209                 verify(mMockAdapterService, timeout(PROFILE_START_MILLIS).times(
210                         NUM_REPEATS * profileNumber + i + 1)).removeProfile(
211                         stop.capture());
212                 Assert.assertEquals(start.getValue(), stop.getValue());
213             }
214             profileNumber += 1;
215         }
216     }
217 }
218