BluetoothSummaryUpdaterTest.java revision ac040e3b1fc3488155e5bb337908c491627900bc
1/*
2 * Copyright (C) 2017 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
17package com.android.settings.bluetooth;
18
19import static com.google.common.truth.Truth.assertThat;
20
21import static org.mockito.Matchers.anyString;
22import static org.mockito.Mockito.doAnswer;
23import static org.mockito.Mockito.doCallRealMethod;
24import static org.mockito.Mockito.doReturn;
25import static org.mockito.Mockito.times;
26import static org.mockito.Mockito.verify;
27import static org.mockito.Mockito.when;
28
29import android.bluetooth.BluetoothAdapter;
30import android.bluetooth.BluetoothDevice;
31import android.content.Context;
32import android.util.Log;
33
34import com.android.settings.R;
35import com.android.settings.TestConfig;
36import com.android.settings.testutils.SettingsRobolectricTestRunner;
37import com.android.settings.widget.SummaryUpdater.OnSummaryChangeListener;
38import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
39import com.android.settingslib.bluetooth.LocalBluetoothManager;
40
41import org.junit.Before;
42import org.junit.Test;
43import org.junit.runner.RunWith;
44import org.mockito.Answers;
45import org.mockito.Mock;
46import org.mockito.MockitoAnnotations;
47import org.robolectric.RuntimeEnvironment;
48import org.robolectric.annotation.Config;
49
50import java.util.HashSet;
51import java.util.Set;
52
53@RunWith(SettingsRobolectricTestRunner.class)
54@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
55public class BluetoothSummaryUpdaterTest {
56    private static final String DEVICE_NAME = "Nightshade";
57    private static final String DEVICE_KEYBOARD_NAME = "Bluetooth Keyboard";
58
59    private Context mContext;
60    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
61    private LocalBluetoothManager mBluetoothManager;
62    @Mock
63    private LocalBluetoothAdapter mBtAdapter;
64    @Mock
65    private BluetoothDevice mConnectedDevice;
66    @Mock
67    private BluetoothDevice mConnectedKeyBoardDevice;
68    @Mock
69    private SummaryListener mListener;
70
71    // Disabled by default
72    private final boolean[] mAdapterEnabled = {false};
73    // Not connected by default
74    private final int[] mAdapterConnectionState = {BluetoothAdapter.STATE_DISCONNECTED};
75    // Not connected by default
76    private final boolean[] mDeviceConnected = {false, false};
77    private final Set<BluetoothDevice> mBondedDevices = new HashSet<>();
78    private BluetoothSummaryUpdater mSummaryUpdater;
79
80    @Before
81    public void setUp() {
82        MockitoAnnotations.initMocks(this);
83        mContext = RuntimeEnvironment.application.getApplicationContext();
84        doCallRealMethod().when(mListener).onSummaryChanged(anyString());
85        // Setup mock adapter
86        when(mBluetoothManager.getBluetoothAdapter()).thenReturn(mBtAdapter);
87        doAnswer(invocation -> mAdapterEnabled[0]).when(mBtAdapter).isEnabled();
88        doAnswer(invocation -> mAdapterConnectionState[0]).when(mBtAdapter).getConnectionState();
89        mSummaryUpdater = new BluetoothSummaryUpdater(mContext, mListener, mBluetoothManager);
90        // Setup first device
91        doReturn(DEVICE_NAME).when(mConnectedDevice).getName();
92        doAnswer(invocation -> mDeviceConnected[0]).when(mConnectedDevice).isConnected();
93        // Setup second device
94        doReturn(DEVICE_KEYBOARD_NAME).when(mConnectedKeyBoardDevice).getName();
95        doAnswer(invocation -> mDeviceConnected[1]).when(mConnectedKeyBoardDevice)
96                .isConnected();
97        doReturn(mBondedDevices).when(mBtAdapter).getBondedDevices();
98    }
99
100    @Test
101    public void register_true_shouldRegisterListener() {
102        mSummaryUpdater.register(true);
103
104        verify(mBluetoothManager.getEventManager()).registerCallback(mSummaryUpdater);
105    }
106
107    @Test
108    public void register_false_shouldUnregisterListener() {
109        mSummaryUpdater.register(false);
110
111        verify(mBluetoothManager.getEventManager()).unregisterCallback(mSummaryUpdater);
112    }
113
114    @Test
115    public void register_true_shouldSendSummaryChange() {
116        mAdapterEnabled[0] = true;
117        mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTED;
118        mBondedDevices.add(mConnectedDevice);
119        mDeviceConnected[0] = true;
120
121        mSummaryUpdater.register(true);
122
123        verify(mListener).onSummaryChanged(
124                mContext.getString(R.string.bluetooth_connected_summary, DEVICE_NAME));
125    }
126
127    @Test
128    public void onBluetoothStateChanged_btDisabled_shouldSendDisabledSummary() {
129        // These states should be ignored
130        mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTED;
131        mBondedDevices.add(mConnectedDevice);
132        mDeviceConnected[0] = true;
133
134        mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
135
136        verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_disabled));
137    }
138
139    @Test
140    public void onBluetoothStateChanged_btEnabled_connected_shouldSendConnectedSummary() {
141        mAdapterEnabled[0] = true;
142        mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTED;
143        mBondedDevices.add(mConnectedDevice);
144        mDeviceConnected[0] = true;
145
146        mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_ON);
147
148        verify(mListener).onSummaryChanged(
149                mContext.getString(R.string.bluetooth_connected_summary, DEVICE_NAME));
150    }
151
152    @Test
153    public void onBluetoothStateChanged_btEnabled_connectedMisMatch_shouldSendNotConnected() {
154        mAdapterEnabled[0] = true;
155        mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTED;
156        mBondedDevices.add(mConnectedDevice);
157        // State mismatch
158        mDeviceConnected[0] = false;
159
160        mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_ON);
161
162        verify(mListener).onSummaryChanged(mContext.getString(R.string.disconnected));
163    }
164
165    @Test
166    public void onBluetoothStateChanged_btEnabled_notConnected_shouldSendDisconnectedMessage() {
167        mAdapterEnabled[0] = true;
168        mAdapterConnectionState[0] = BluetoothAdapter.STATE_DISCONNECTED;
169        mBondedDevices.add(mConnectedDevice);
170        // This should be ignored
171        mDeviceConnected[0] = true;
172
173        mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_TURNING_ON);
174
175        verify(mListener).onSummaryChanged(mContext.getString(R.string.disconnected));
176    }
177
178    @Test
179    public void onBluetoothStateChanged_ConnectedDisabledEnabled_shouldSendDisconnectedSummary() {
180        mAdapterEnabled[0] = true;
181        mAdapterConnectionState[0] = BluetoothAdapter.STATE_DISCONNECTED;
182        mBondedDevices.add(mConnectedDevice);
183        mDeviceConnected[0] = false;
184
185        mSummaryUpdater.register(true);
186        verify(mListener).onSummaryChanged(mContext.getString(R.string.disconnected));
187
188        mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTED;
189        mDeviceConnected[0] = true;
190        mSummaryUpdater.onConnectionStateChanged(null /* device */,
191                BluetoothAdapter.STATE_CONNECTED);
192        verify(mListener).onSummaryChanged(
193                mContext.getString(R.string.bluetooth_connected_summary, DEVICE_NAME));
194
195        mAdapterEnabled[0] = false;
196        mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
197        verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_disabled));
198
199        // Turning ON means not enabled
200        mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_TURNING_ON);
201        // There should still be only one invocation of disabled message
202        verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_disabled));
203
204        mAdapterEnabled[0] = true;
205        mDeviceConnected[0] = false;
206        mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_ON);
207        verify(mListener, times(2)).onSummaryChanged(mContext.getString(R.string.disconnected));
208        verify(mListener, times(4)).onSummaryChanged(anyString());
209    }
210
211    @Test
212    public void onConnectionStateChanged_connected_shouldSendConnectedMessage() {
213        mAdapterEnabled[0] = true;
214        mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTED;
215        mBondedDevices.add(mConnectedDevice);
216        mDeviceConnected[0] = true;
217
218        mSummaryUpdater.onConnectionStateChanged(null /* device */,
219                BluetoothAdapter.STATE_CONNECTED);
220
221        verify(mListener).onSummaryChanged(
222                mContext.getString(R.string.bluetooth_connected_summary, DEVICE_NAME));
223    }
224
225    @Test
226    public void onConnectionStateChanged_inconsistentState_shouldSendDisconnectedMessage() {
227        mAdapterEnabled[0] = true;
228        mAdapterConnectionState[0] = BluetoothAdapter.STATE_DISCONNECTED;
229        mBondedDevices.add(mConnectedDevice);
230        mDeviceConnected[0] = false;
231
232        mSummaryUpdater.onConnectionStateChanged(null /* device */,
233                BluetoothAdapter.STATE_CONNECTED);
234
235        verify(mListener).onSummaryChanged(mContext.getString(R.string.disconnected));
236    }
237
238    @Test
239    public void onConnectionStateChanged_noBondedDevice_shouldSendDisconnectedMessage() {
240        mAdapterEnabled[0] = true;
241        mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTED;
242
243        mSummaryUpdater.onConnectionStateChanged(null /* device */,
244                BluetoothAdapter.STATE_CONNECTED);
245
246        verify(mListener).onSummaryChanged(
247                mContext.getString(R.string.disconnected));
248    }
249
250    @Test
251    public void onConnectionStateChanged_connecting_shouldSendConnectingMessage() {
252        // No need for bonded devices
253        mAdapterEnabled[0] = true;
254        mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTING;
255
256        mSummaryUpdater.onConnectionStateChanged(null /* device */,
257                BluetoothAdapter.STATE_CONNECTING);
258
259        verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_connecting));
260    }
261
262    @Test
263    public void onConnectionStateChanged_disconnecting_shouldSendDisconnectingMessage() {
264        // No need for bonded devices
265        mAdapterEnabled[0] = true;
266        mAdapterConnectionState[0] = BluetoothAdapter.STATE_DISCONNECTING;
267
268        mSummaryUpdater.onConnectionStateChanged(null /* device */,
269                BluetoothAdapter.STATE_DISCONNECTING);
270
271        verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_disconnecting));
272    }
273
274    @Test
275    public void getConnectedDeviceSummary_hasConnectedDevice_returnOneDeviceSummary() {
276        mBondedDevices.add(mConnectedDevice);
277        mDeviceConnected[0] = true;
278        final String expectedSummary = mContext.getString(R.string.bluetooth_connected_summary,
279                DEVICE_NAME);
280
281        assertThat(mSummaryUpdater.getConnectedDeviceSummary()).isEqualTo(expectedSummary);
282    }
283
284    @Test
285    public void getConnectedDeviceSummary_multipleDevices_returnMultipleDevicesSummary() {
286        mBondedDevices.add(mConnectedDevice);
287        mBondedDevices.add(mConnectedKeyBoardDevice);
288        mDeviceConnected[0] = true;
289        mDeviceConnected[1] = true;
290        final String expectedSummary = mContext.getString(
291                R.string.bluetooth_connected_multiple_devices_summary);
292
293        assertThat(mSummaryUpdater.getConnectedDeviceSummary()).isEqualTo(expectedSummary);
294    }
295
296    private class SummaryListener implements OnSummaryChangeListener {
297        String summary;
298
299        @Override
300        public void onSummaryChanged(String summary) {
301            this.summary = summary;
302        }
303    }
304
305}
306