1 /*
2  * Copyright 2019 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.storage;
18 
19 import static org.junit.Assert.assertThat;
20 import static org.mockito.ArgumentMatchers.any;
21 import static org.mockito.ArgumentMatchers.anyInt;
22 import static org.mockito.ArgumentMatchers.anyString;
23 import static org.mockito.Mockito.doNothing;
24 import static org.mockito.Mockito.doReturn;
25 import static org.mockito.Mockito.times;
26 import static org.mockito.Mockito.verify;
27 import static org.mockito.Mockito.when;
28 
29 import android.bluetooth.BluetoothA2dp;
30 import android.bluetooth.BluetoothAdapter;
31 import android.bluetooth.BluetoothDevice;
32 import android.bluetooth.BluetoothProfile;
33 import android.content.ContentValues;
34 import android.database.Cursor;
35 import android.database.sqlite.SQLiteDatabase;
36 
37 import androidx.room.Room;
38 import androidx.room.testing.MigrationTestHelper;
39 import androidx.sqlite.db.SupportSQLiteDatabase;
40 import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory;
41 import androidx.test.InstrumentationRegistry;
42 import androidx.test.filters.MediumTest;
43 import androidx.test.runner.AndroidJUnit4;
44 
45 import com.android.bluetooth.TestUtils;
46 import com.android.bluetooth.btservice.AdapterService;
47 
48 import org.hamcrest.CoreMatchers;
49 import org.junit.After;
50 import org.junit.Assert;
51 import org.junit.Before;
52 import org.junit.Rule;
53 import org.junit.Test;
54 import org.junit.runner.RunWith;
55 import org.mockito.Mock;
56 import org.mockito.MockitoAnnotations;
57 
58 import java.io.IOException;
59 import java.util.List;
60 
61 @MediumTest
62 @RunWith(AndroidJUnit4.class)
63 public final class DatabaseManagerTest {
64 
65     @Mock private AdapterService mAdapterService;
66 
67     private MetadataDatabase mDatabase;
68     private DatabaseManager mDatabaseManager;
69     private BluetoothDevice mTestDevice;
70     private BluetoothDevice mTestDevice2;
71     private BluetoothDevice mTestDevice3;
72 
73     private static final String LOCAL_STORAGE = "LocalStorage";
74     private static final String TEST_BT_ADDR = "11:22:33:44:55:66";
75     private static final String TEST_BT_ADDR2 = "66:55:44:33:22:11";
76     private static final String TEST_BT_ADDR3 = "12:34:56:65:43:21";
77     private static final String OTHER_BT_ADDR1 = "11:11:11:11:11:11";
78     private static final String OTHER_BT_ADDR2 = "22:22:22:22:22:22";
79     private static final String DB_NAME = "test_db";
80     private static final int A2DP_SUPPORT_OP_CODEC_TEST = 0;
81     private static final int A2DP_ENALBED_OP_CODEC_TEST = 1;
82     private static final int MAX_META_ID = 16;
83     private static final byte[] TEST_BYTE_ARRAY = "TEST_VALUE".getBytes();
84 
85     @Rule
86     public MigrationTestHelper testHelper = new MigrationTestHelper(
87             InstrumentationRegistry.getInstrumentation(),
88             MetadataDatabase.class.getCanonicalName(),
89             new FrameworkSQLiteOpenHelperFactory());
90     @Before
setUp()91     public void setUp() throws Exception {
92         MockitoAnnotations.initMocks(this);
93         TestUtils.setAdapterService(mAdapterService);
94 
95         mTestDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(TEST_BT_ADDR);
96         mTestDevice2 = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(TEST_BT_ADDR2);
97         mTestDevice3 = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(TEST_BT_ADDR3);
98 
99         // Create a memory database for DatabaseManager instead of use a real database.
100         mDatabase = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getTargetContext(),
101                 MetadataDatabase.class).build();
102 
103         when(mAdapterService.getPackageManager()).thenReturn(
104                 InstrumentationRegistry.getTargetContext().getPackageManager());
105         mDatabaseManager = new DatabaseManager(mAdapterService);
106 
107         BluetoothDevice[] bondedDevices = {mTestDevice};
108         doReturn(bondedDevices).when(mAdapterService).getBondedDevices();
109         doNothing().when(mAdapterService).metadataChanged(
110                 anyString(), anyInt(), any(byte[].class));
111 
112         restartDatabaseManagerHelper();
113     }
114 
115     @After
tearDown()116     public void tearDown() throws Exception {
117         TestUtils.clearAdapterService(mAdapterService);
118         mDatabase.deleteAll();
119         mDatabaseManager.cleanup();
120     }
121 
122     @Test
testMetadataDefault()123     public void testMetadataDefault() {
124         Metadata data = new Metadata(TEST_BT_ADDR);
125         mDatabase.insert(data);
126         restartDatabaseManagerHelper();
127 
128         for (int id = 0; id < BluetoothProfile.MAX_PROFILE_ID; id++) {
129             Assert.assertEquals(BluetoothProfile.CONNECTION_POLICY_UNKNOWN,
130                     mDatabaseManager.getProfileConnectionPolicy(mTestDevice, id));
131         }
132 
133         Assert.assertEquals(BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN,
134                 mDatabaseManager.getA2dpSupportsOptionalCodecs(mTestDevice));
135 
136         Assert.assertEquals(BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN,
137                     mDatabaseManager.getA2dpOptionalCodecsEnabled(mTestDevice));
138 
139         for (int id = 0; id < MAX_META_ID; id++) {
140             Assert.assertNull(mDatabaseManager.getCustomMeta(mTestDevice, id));
141         }
142 
143         mDatabaseManager.factoryReset();
144         mDatabaseManager.mMetadataCache.clear();
145         // Wait for clear database
146         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
147     }
148 
149     @Test
testSetGetProfileConnectionPolicy()150     public void testSetGetProfileConnectionPolicy() {
151         int badConnectionPolicy = -100;
152 
153         // Cases of device not in database
154         testSetGetProfileConnectionPolicyCase(false, BluetoothProfile.CONNECTION_POLICY_UNKNOWN,
155                 BluetoothProfile.CONNECTION_POLICY_UNKNOWN, true);
156         testSetGetProfileConnectionPolicyCase(false, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN,
157                 BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, true);
158         testSetGetProfileConnectionPolicyCase(false, BluetoothProfile.CONNECTION_POLICY_ALLOWED,
159                 BluetoothProfile.CONNECTION_POLICY_ALLOWED, true);
160         testSetGetProfileConnectionPolicyCase(false, badConnectionPolicy,
161                 BluetoothProfile.CONNECTION_POLICY_UNKNOWN, false);
162 
163         // Cases of device already in database
164         testSetGetProfileConnectionPolicyCase(true, BluetoothProfile.CONNECTION_POLICY_UNKNOWN,
165                 BluetoothProfile.CONNECTION_POLICY_UNKNOWN, true);
166         testSetGetProfileConnectionPolicyCase(true, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN,
167                 BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, true);
168         testSetGetProfileConnectionPolicyCase(true, BluetoothProfile.CONNECTION_POLICY_ALLOWED,
169                 BluetoothProfile.CONNECTION_POLICY_ALLOWED, true);
170         testSetGetProfileConnectionPolicyCase(true, badConnectionPolicy,
171                 BluetoothProfile.CONNECTION_POLICY_UNKNOWN, false);
172     }
173 
174     @Test
testSetGetA2dpSupportsOptionalCodecs()175     public void testSetGetA2dpSupportsOptionalCodecs() {
176         int badValue = -100;
177 
178         // Cases of device not in database
179         testSetGetA2dpOptionalCodecsCase(A2DP_SUPPORT_OP_CODEC_TEST, false,
180                 BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN,
181                 BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN);
182         testSetGetA2dpOptionalCodecsCase(A2DP_SUPPORT_OP_CODEC_TEST, false,
183                 BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED,
184                 BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN);
185         testSetGetA2dpOptionalCodecsCase(A2DP_SUPPORT_OP_CODEC_TEST, false,
186                 BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED,
187                 BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN);
188         testSetGetA2dpOptionalCodecsCase(A2DP_SUPPORT_OP_CODEC_TEST, false,
189                 badValue, BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN);
190 
191         // Cases of device already in database
192         testSetGetA2dpOptionalCodecsCase(A2DP_SUPPORT_OP_CODEC_TEST, true,
193                 BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN,
194                 BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN);
195         testSetGetA2dpOptionalCodecsCase(A2DP_SUPPORT_OP_CODEC_TEST, true,
196                 BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED,
197                 BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
198         testSetGetA2dpOptionalCodecsCase(A2DP_SUPPORT_OP_CODEC_TEST, true,
199                 BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED,
200                 BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
201         testSetGetA2dpOptionalCodecsCase(A2DP_SUPPORT_OP_CODEC_TEST, true,
202                 badValue, BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN);
203     }
204 
205     @Test
testSetGetA2dpOptionalCodecsEnabled()206     public void testSetGetA2dpOptionalCodecsEnabled() {
207         int badValue = -100;
208 
209         // Cases of device not in database
210         testSetGetA2dpOptionalCodecsCase(A2DP_ENALBED_OP_CODEC_TEST, false,
211                 BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN,
212                 BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN);
213         testSetGetA2dpOptionalCodecsCase(A2DP_ENALBED_OP_CODEC_TEST, false,
214                 BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED,
215                 BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN);
216         testSetGetA2dpOptionalCodecsCase(A2DP_ENALBED_OP_CODEC_TEST, false,
217                 BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED,
218                 BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN);
219         testSetGetA2dpOptionalCodecsCase(A2DP_ENALBED_OP_CODEC_TEST, false,
220                 badValue, BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN);
221 
222         // Cases of device already in database
223         testSetGetA2dpOptionalCodecsCase(A2DP_ENALBED_OP_CODEC_TEST, true,
224                 BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN,
225                 BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN);
226         testSetGetA2dpOptionalCodecsCase(A2DP_ENALBED_OP_CODEC_TEST, true,
227                 BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED,
228                 BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED);
229         testSetGetA2dpOptionalCodecsCase(A2DP_ENALBED_OP_CODEC_TEST, true,
230                 BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED,
231                 BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED);
232         testSetGetA2dpOptionalCodecsCase(A2DP_ENALBED_OP_CODEC_TEST, true,
233                 badValue, BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN);
234     }
235 
236     @Test
testRemoveUnusedMetadata_WithSingleBondedDevice()237     public void testRemoveUnusedMetadata_WithSingleBondedDevice() {
238         // Insert two devices to database and cache, only mTestDevice is
239         // in the bonded list
240         Metadata otherData = new Metadata(OTHER_BT_ADDR1);
241         // Add metadata for otherDevice
242         otherData.setCustomizedMeta(0, TEST_BYTE_ARRAY);
243         mDatabaseManager.mMetadataCache.put(OTHER_BT_ADDR1, otherData);
244         mDatabase.insert(otherData);
245 
246         Metadata data = new Metadata(TEST_BT_ADDR);
247         mDatabaseManager.mMetadataCache.put(TEST_BT_ADDR, data);
248         mDatabase.insert(data);
249 
250         mDatabaseManager.removeUnusedMetadata();
251         // Wait for database update
252         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
253 
254         // Check removed device report metadata changed to null
255         verify(mAdapterService).metadataChanged(OTHER_BT_ADDR1, 0, null);
256 
257         List<Metadata> list = mDatabase.load();
258 
259         // Check number of metadata in the database
260         Assert.assertEquals(1, list.size());
261 
262         // Check whether the device is in database
263         Metadata checkData = list.get(0);
264         Assert.assertEquals(TEST_BT_ADDR, checkData.getAddress());
265 
266         mDatabaseManager.factoryReset();
267         mDatabaseManager.mMetadataCache.clear();
268         // Wait for clear database
269         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
270     }
271 
272     @Test
testRemoveUnusedMetadata_WithMultiBondedDevices()273     public void testRemoveUnusedMetadata_WithMultiBondedDevices() {
274         // Insert three devices to database and cache, otherDevice1 and otherDevice2
275         // are in the bonded list
276 
277         // Add metadata for TEST_BT_ADDR
278         Metadata testData = new Metadata(TEST_BT_ADDR);
279         testData.setCustomizedMeta(0, TEST_BYTE_ARRAY);
280         mDatabaseManager.mMetadataCache.put(TEST_BT_ADDR, testData);
281         mDatabase.insert(testData);
282 
283         // Add metadata for OTHER_BT_ADDR1
284         Metadata otherData1 = new Metadata(OTHER_BT_ADDR1);
285         otherData1.setCustomizedMeta(0, TEST_BYTE_ARRAY);
286         mDatabaseManager.mMetadataCache.put(OTHER_BT_ADDR1, otherData1);
287         mDatabase.insert(otherData1);
288 
289         // Add metadata for OTHER_BT_ADDR2
290         Metadata otherData2 = new Metadata(OTHER_BT_ADDR2);
291         otherData2.setCustomizedMeta(0, TEST_BYTE_ARRAY);
292         mDatabaseManager.mMetadataCache.put(OTHER_BT_ADDR2, otherData2);
293         mDatabase.insert(otherData2);
294 
295         // Add OTHER_BT_ADDR1 OTHER_BT_ADDR2 to bonded devices
296         BluetoothDevice otherDevice1 = BluetoothAdapter.getDefaultAdapter()
297                 .getRemoteDevice(OTHER_BT_ADDR1);
298         BluetoothDevice otherDevice2 = BluetoothAdapter.getDefaultAdapter()
299                 .getRemoteDevice(OTHER_BT_ADDR2);
300         BluetoothDevice[] bondedDevices = {otherDevice1, otherDevice2};
301         doReturn(bondedDevices).when(mAdapterService).getBondedDevices();
302 
303         mDatabaseManager.removeUnusedMetadata();
304         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
305 
306         // Check TEST_BT_ADDR report metadata changed to null
307         verify(mAdapterService).metadataChanged(TEST_BT_ADDR, 0, null);
308 
309         // Check number of metadata in the database
310         List<Metadata> list = mDatabase.load();
311         // OTHER_BT_ADDR1 and OTHER_BT_ADDR2 should still in database
312         Assert.assertEquals(2, list.size());
313 
314         // Check whether the devices are in the database
315         Metadata checkData1 = list.get(0);
316         Assert.assertEquals(OTHER_BT_ADDR2, checkData1.getAddress());
317         Metadata checkData2 = list.get(1);
318         Assert.assertEquals(OTHER_BT_ADDR1, checkData2.getAddress());
319 
320         mDatabaseManager.factoryReset();
321         mDatabaseManager.mMetadataCache.clear();
322         // Wait for clear database
323         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
324 
325     }
326 
327     @Test
testSetGetCustomMeta()328     public void testSetGetCustomMeta() {
329         int badKey = 100;
330         byte[] value = "input value".getBytes();
331 
332         // Device is not in database
333         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_MANUFACTURER_NAME,
334                 value, true);
335         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_MODEL_NAME,
336                 value, true);
337         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_SOFTWARE_VERSION,
338                 value, true);
339         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_HARDWARE_VERSION,
340                 value, true);
341         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_COMPANION_APP,
342                 value, true);
343         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_MAIN_ICON,
344                 value, true);
345         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET,
346                 value, true);
347         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_UNTETHERED_LEFT_ICON,
348                 value, true);
349         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_UNTETHERED_RIGHT_ICON,
350                 value, true);
351         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_UNTETHERED_CASE_ICON,
352                 value, true);
353         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY,
354                 value, true);
355         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY,
356                 value, true);
357         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY,
358                 value, true);
359         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_UNTETHERED_LEFT_CHARGING,
360                 value, true);
361         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_UNTETHERED_RIGHT_CHARGING,
362                 value, true);
363         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_UNTETHERED_CASE_CHARGING,
364                 value, true);
365         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI,
366                 value, true);
367         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_DEVICE_TYPE,
368                 value, true);
369         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_MAIN_BATTERY,
370                 value, true);
371         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_MAIN_CHARGING,
372                 value, true);
373         testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD,
374                 value, true);
375         testSetGetCustomMetaCase(false,
376                 BluetoothDevice.METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD,
377                 value, true);
378         testSetGetCustomMetaCase(false,
379                 BluetoothDevice.METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD,
380                 value, true);
381         testSetGetCustomMetaCase(false,
382                 BluetoothDevice.METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD,
383                 value, true);
384         testSetGetCustomMetaCase(false, badKey, value, false);
385 
386         // Device is in database
387         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_MANUFACTURER_NAME,
388                 value, true);
389         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_MODEL_NAME,
390                 value, true);
391         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_SOFTWARE_VERSION,
392                 value, true);
393         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_HARDWARE_VERSION,
394                 value, true);
395         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_COMPANION_APP,
396                 value, true);
397         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_MAIN_ICON,
398                 value, true);
399         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET,
400                 value, true);
401         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_UNTETHERED_LEFT_ICON,
402                 value, true);
403         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_UNTETHERED_RIGHT_ICON,
404                 value, true);
405         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_UNTETHERED_CASE_ICON,
406                 value, true);
407         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY,
408                 value, true);
409         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY,
410                 value, true);
411         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY,
412                 value, true);
413         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_UNTETHERED_LEFT_CHARGING,
414                 value, true);
415         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_UNTETHERED_RIGHT_CHARGING,
416                 value, true);
417         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_UNTETHERED_CASE_CHARGING,
418                 value, true);
419         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI,
420                 value, true);
421         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_DEVICE_TYPE,
422                 value, true);
423         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_MAIN_BATTERY,
424                 value, true);
425         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_MAIN_CHARGING,
426                 value, true);
427         testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD,
428                 value, true);
429         testSetGetCustomMetaCase(true,
430                 BluetoothDevice.METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD,
431                 value, true);
432         testSetGetCustomMetaCase(true,
433                 BluetoothDevice.METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD,
434                 value, true);
435         testSetGetCustomMetaCase(true,
436                 BluetoothDevice.METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD,
437                 value, true);
438     }
439 
440     @Test
testSetConnection()441     public void testSetConnection() {
442         // Verify pre-conditions to ensure a fresh test
443         Assert.assertEquals(0, mDatabaseManager.mMetadataCache.size());
444         Assert.assertNotNull(mTestDevice);
445         Assert.assertNotNull(mTestDevice2);
446         Assert.assertNull(mDatabaseManager.getMostRecentlyConnectedA2dpDevice());
447 
448         // Set the first device's connection
449         mDatabaseManager.setConnection(mTestDevice, true);
450         // Wait for database update
451         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
452         Assert.assertTrue(mDatabaseManager
453                 .mMetadataCache.get(mTestDevice.getAddress()).is_active_a2dp_device);
454         List<BluetoothDevice> mostRecentlyConnectedDevicesOrdered =
455                 mDatabaseManager.getMostRecentlyConnectedDevices();
456         Assert.assertEquals(mTestDevice, mDatabaseManager.getMostRecentlyConnectedA2dpDevice());
457         Assert.assertEquals(1, mostRecentlyConnectedDevicesOrdered.size());
458         Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(0));
459 
460         // Setting the second device's connection
461         mDatabaseManager.setConnection(mTestDevice2, true);
462         // Wait for database update
463         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
464         Assert.assertFalse(mDatabaseManager
465                 .mMetadataCache.get(mTestDevice.getAddress()).is_active_a2dp_device);
466         Assert.assertTrue(mDatabaseManager
467                 .mMetadataCache.get(mTestDevice2.getAddress()).is_active_a2dp_device);
468         Assert.assertEquals(mTestDevice2, mDatabaseManager.getMostRecentlyConnectedA2dpDevice());
469         mostRecentlyConnectedDevicesOrdered =
470                 mDatabaseManager.getMostRecentlyConnectedDevices();
471         Assert.assertEquals(2, mostRecentlyConnectedDevicesOrdered.size());
472         Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(0));
473         Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(1));
474 
475         // Connect first test device again
476         mDatabaseManager.setConnection(mTestDevice, true);
477         // Wait for database update
478         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
479         Assert.assertTrue(mDatabaseManager
480                 .mMetadataCache.get(mTestDevice.getAddress()).is_active_a2dp_device);
481         Assert.assertFalse(mDatabaseManager
482                 .mMetadataCache.get(mTestDevice2.getAddress()).is_active_a2dp_device);
483         Assert.assertEquals(mTestDevice, mDatabaseManager.getMostRecentlyConnectedA2dpDevice());
484         mostRecentlyConnectedDevicesOrdered =
485                 mDatabaseManager.getMostRecentlyConnectedDevices();
486         Assert.assertEquals(2, mostRecentlyConnectedDevicesOrdered.size());
487         Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(0));
488         Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(1));
489 
490         // Disconnect first test device's connection
491         mDatabaseManager.setDisconnection(mTestDevice);
492         // Wait for database update
493         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
494         Assert.assertFalse(mDatabaseManager
495                 .mMetadataCache.get(mTestDevice.getAddress()).is_active_a2dp_device);
496         Assert.assertFalse(mDatabaseManager
497                 .mMetadataCache.get(mTestDevice2.getAddress()).is_active_a2dp_device);
498         Assert.assertNull(mDatabaseManager.getMostRecentlyConnectedA2dpDevice());
499         mostRecentlyConnectedDevicesOrdered =
500                 mDatabaseManager.getMostRecentlyConnectedDevices();
501         Assert.assertEquals(2, mostRecentlyConnectedDevicesOrdered.size());
502         Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(0));
503         Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(1));
504 
505         // Connect third test device (non-a2dp device)
506         mDatabaseManager.setConnection(mTestDevice3, false);
507         // Wait for database update
508         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
509         Assert.assertFalse(mDatabaseManager
510                 .mMetadataCache.get(mTestDevice.getAddress()).is_active_a2dp_device);
511         Assert.assertFalse(mDatabaseManager
512                 .mMetadataCache.get(mTestDevice2.getAddress()).is_active_a2dp_device);
513         Assert.assertFalse(mDatabaseManager
514                 .mMetadataCache.get(mTestDevice3.getAddress()).is_active_a2dp_device);
515         Assert.assertNull(mDatabaseManager.getMostRecentlyConnectedA2dpDevice());
516         mostRecentlyConnectedDevicesOrdered =
517                 mDatabaseManager.getMostRecentlyConnectedDevices();
518         Assert.assertEquals(3, mostRecentlyConnectedDevicesOrdered.size());
519         Assert.assertEquals(mTestDevice3, mostRecentlyConnectedDevicesOrdered.get(0));
520         Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(1));
521         Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(2));
522 
523         // Connect first test device again
524         mDatabaseManager.setConnection(mTestDevice, true);
525         // Wait for database update
526         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
527         Assert.assertTrue(mDatabaseManager
528                 .mMetadataCache.get(mTestDevice.getAddress()).is_active_a2dp_device);
529         Assert.assertFalse(mDatabaseManager
530                 .mMetadataCache.get(mTestDevice2.getAddress()).is_active_a2dp_device);
531         Assert.assertFalse(mDatabaseManager
532                 .mMetadataCache.get(mTestDevice3.getAddress()).is_active_a2dp_device);
533         Assert.assertEquals(mTestDevice, mDatabaseManager.getMostRecentlyConnectedA2dpDevice());
534         mostRecentlyConnectedDevicesOrdered =
535                 mDatabaseManager.getMostRecentlyConnectedDevices();
536         Assert.assertEquals(3, mostRecentlyConnectedDevicesOrdered.size());
537         Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(0));
538         Assert.assertEquals(mTestDevice3, mostRecentlyConnectedDevicesOrdered.get(1));
539         Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(2));
540 
541         // Connect third test device again and ensure it doesn't reset active a2dp device
542         mDatabaseManager.setConnection(mTestDevice3, false);
543         // Wait for database update
544         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
545         Assert.assertTrue(mDatabaseManager
546                 .mMetadataCache.get(mTestDevice.getAddress()).is_active_a2dp_device);
547         Assert.assertFalse(mDatabaseManager
548                 .mMetadataCache.get(mTestDevice2.getAddress()).is_active_a2dp_device);
549         Assert.assertFalse(mDatabaseManager
550                 .mMetadataCache.get(mTestDevice3.getAddress()).is_active_a2dp_device);
551         Assert.assertEquals(mTestDevice, mDatabaseManager.getMostRecentlyConnectedA2dpDevice());
552         mostRecentlyConnectedDevicesOrdered =
553                 mDatabaseManager.getMostRecentlyConnectedDevices();
554         Assert.assertEquals(3, mostRecentlyConnectedDevicesOrdered.size());
555         Assert.assertEquals(mTestDevice3, mostRecentlyConnectedDevicesOrdered.get(0));
556         Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(1));
557         Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(2));
558 
559         // Disconnect second test device
560         mDatabaseManager.setDisconnection(mTestDevice2);
561         // Wait for database update
562         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
563         Assert.assertTrue(mDatabaseManager
564                 .mMetadataCache.get(mTestDevice.getAddress()).is_active_a2dp_device);
565         Assert.assertFalse(mDatabaseManager
566                 .mMetadataCache.get(mTestDevice2.getAddress()).is_active_a2dp_device);
567         Assert.assertFalse(mDatabaseManager
568                 .mMetadataCache.get(mTestDevice3.getAddress()).is_active_a2dp_device);
569         Assert.assertEquals(mTestDevice, mDatabaseManager.getMostRecentlyConnectedA2dpDevice());
570         mostRecentlyConnectedDevicesOrdered =
571                 mDatabaseManager.getMostRecentlyConnectedDevices();
572         Assert.assertEquals(3, mostRecentlyConnectedDevicesOrdered.size());
573         Assert.assertEquals(mTestDevice3, mostRecentlyConnectedDevicesOrdered.get(0));
574         Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(1));
575         Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(2));
576 
577         // Disconnect first test device
578         mDatabaseManager.setDisconnection(mTestDevice);
579         // Wait for database update
580         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
581         Assert.assertFalse(mDatabaseManager
582                 .mMetadataCache.get(mTestDevice.getAddress()).is_active_a2dp_device);
583         Assert.assertFalse(mDatabaseManager
584                 .mMetadataCache.get(mTestDevice2.getAddress()).is_active_a2dp_device);
585         Assert.assertFalse(mDatabaseManager
586                 .mMetadataCache.get(mTestDevice3.getAddress()).is_active_a2dp_device);
587         Assert.assertNull(mDatabaseManager.getMostRecentlyConnectedA2dpDevice());
588         mostRecentlyConnectedDevicesOrdered =
589                 mDatabaseManager.getMostRecentlyConnectedDevices();
590         Assert.assertEquals(3, mostRecentlyConnectedDevicesOrdered.size());
591         Assert.assertEquals(mTestDevice3, mostRecentlyConnectedDevicesOrdered.get(0));
592         Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(1));
593         Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(2));
594 
595         // Disconnect third test device
596         mDatabaseManager.setDisconnection(mTestDevice3);
597         // Wait for database update
598         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
599         Assert.assertFalse(mDatabaseManager
600                 .mMetadataCache.get(mTestDevice.getAddress()).is_active_a2dp_device);
601         Assert.assertFalse(mDatabaseManager
602                 .mMetadataCache.get(mTestDevice2.getAddress()).is_active_a2dp_device);
603         Assert.assertFalse(mDatabaseManager
604                 .mMetadataCache.get(mTestDevice3.getAddress()).is_active_a2dp_device);
605         Assert.assertNull(mDatabaseManager.getMostRecentlyConnectedA2dpDevice());
606         mostRecentlyConnectedDevicesOrdered =
607                 mDatabaseManager.getMostRecentlyConnectedDevices();
608         Assert.assertEquals(3, mostRecentlyConnectedDevicesOrdered.size());
609         Assert.assertEquals(mTestDevice3, mostRecentlyConnectedDevicesOrdered.get(0));
610         Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(1));
611         Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(2));
612 
613         mDatabaseManager.factoryReset();
614         mDatabaseManager.mMetadataCache.clear();
615         // Wait for clear database
616         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
617     }
618 
619     @Test
testDatabaseMigration_100_101()620     public void testDatabaseMigration_100_101() throws IOException {
621         // Create a database with version 100
622         SupportSQLiteDatabase db = testHelper.createDatabase(DB_NAME, 100);
623         Cursor cursor = db.query("SELECT * FROM metadata");
624 
625         // pbap_client_priority should not in version 100
626         assertHasColumn(cursor, "pbap_client_priority", false);
627 
628         // Migrate database from 100 to 101
629         db.close();
630         db = testHelper.runMigrationsAndValidate(DB_NAME, 101, true,
631                 MetadataDatabase.MIGRATION_100_101);
632         cursor = db.query("SELECT * FROM metadata");
633 
634         // Check whether pbap_client_priority exists in version 101
635         assertHasColumn(cursor, "pbap_client_priority", true);
636     }
637 
638     @Test
testDatabaseMigration_101_102()639     public void testDatabaseMigration_101_102() throws IOException {
640         String testString = "TEST STRING";
641 
642         // Create a database with version 101
643         SupportSQLiteDatabase db = testHelper.createDatabase(DB_NAME, 101);
644         Cursor cursor = db.query("SELECT * FROM metadata");
645 
646         // insert a device to the database
647         ContentValues device = new ContentValues();
648         device.put("address", TEST_BT_ADDR);
649         device.put("migrated", false);
650         device.put("a2dpSupportsOptionalCodecs", -1);
651         device.put("a2dpOptionalCodecsEnabled", -1);
652         device.put("a2dp_priority", -1);
653         device.put("a2dp_sink_priority", -1);
654         device.put("hfp_priority", -1);
655         device.put("hfp_client_priority", -1);
656         device.put("hid_host_priority", -1);
657         device.put("pan_priority", -1);
658         device.put("pbap_priority", -1);
659         device.put("pbap_client_priority", -1);
660         device.put("map_priority", -1);
661         device.put("sap_priority", -1);
662         device.put("hearing_aid_priority", -1);
663         device.put("map_client_priority", -1);
664         device.put("manufacturer_name", testString);
665         device.put("model_name", testString);
666         device.put("software_version", testString);
667         device.put("hardware_version", testString);
668         device.put("companion_app", testString);
669         device.put("main_icon", testString);
670         device.put("is_unthethered_headset", testString);
671         device.put("unthethered_left_icon", testString);
672         device.put("unthethered_right_icon", testString);
673         device.put("unthethered_case_icon", testString);
674         device.put("unthethered_left_battery", testString);
675         device.put("unthethered_right_battery", testString);
676         device.put("unthethered_case_battery", testString);
677         device.put("unthethered_left_charging", testString);
678         device.put("unthethered_right_charging", testString);
679         device.put("unthethered_case_charging", testString);
680         assertThat(db.insert("metadata", SQLiteDatabase.CONFLICT_IGNORE, device),
681                 CoreMatchers.not(-1));
682 
683         // Check the metadata names on version 101
684         assertHasColumn(cursor, "is_unthethered_headset", true);
685         assertHasColumn(cursor, "unthethered_left_icon", true);
686         assertHasColumn(cursor, "unthethered_right_icon", true);
687         assertHasColumn(cursor, "unthethered_case_icon", true);
688         assertHasColumn(cursor, "unthethered_left_battery", true);
689         assertHasColumn(cursor, "unthethered_right_battery", true);
690         assertHasColumn(cursor, "unthethered_case_battery", true);
691         assertHasColumn(cursor, "unthethered_left_charging", true);
692         assertHasColumn(cursor, "unthethered_right_charging", true);
693         assertHasColumn(cursor, "unthethered_case_charging", true);
694 
695         // Migrate database from 101 to 102
696         db.close();
697         db = testHelper.runMigrationsAndValidate(DB_NAME, 102, true,
698                 MetadataDatabase.MIGRATION_101_102);
699         cursor = db.query("SELECT * FROM metadata");
700 
701         // metadata names should be changed on version 102
702         assertHasColumn(cursor, "is_unthethered_headset", false);
703         assertHasColumn(cursor, "unthethered_left_icon", false);
704         assertHasColumn(cursor, "unthethered_right_icon", false);
705         assertHasColumn(cursor, "unthethered_case_icon", false);
706         assertHasColumn(cursor, "unthethered_left_battery", false);
707         assertHasColumn(cursor, "unthethered_right_battery", false);
708         assertHasColumn(cursor, "unthethered_case_battery", false);
709         assertHasColumn(cursor, "unthethered_left_charging", false);
710         assertHasColumn(cursor, "unthethered_right_charging", false);
711         assertHasColumn(cursor, "unthethered_case_charging", false);
712 
713         assertHasColumn(cursor, "is_untethered_headset", true);
714         assertHasColumn(cursor, "untethered_left_icon", true);
715         assertHasColumn(cursor, "untethered_right_icon", true);
716         assertHasColumn(cursor, "untethered_case_icon", true);
717         assertHasColumn(cursor, "untethered_left_battery", true);
718         assertHasColumn(cursor, "untethered_right_battery", true);
719         assertHasColumn(cursor, "untethered_case_battery", true);
720         assertHasColumn(cursor, "untethered_left_charging", true);
721         assertHasColumn(cursor, "untethered_right_charging", true);
722         assertHasColumn(cursor, "untethered_case_charging", true);
723 
724         while (cursor.moveToNext()) {
725             // Check whether metadata data type are blob
726             assertColumnBlob(cursor, "manufacturer_name");
727             assertColumnBlob(cursor, "model_name");
728             assertColumnBlob(cursor, "software_version");
729             assertColumnBlob(cursor, "hardware_version");
730             assertColumnBlob(cursor, "companion_app");
731             assertColumnBlob(cursor, "main_icon");
732             assertColumnBlob(cursor, "is_untethered_headset");
733             assertColumnBlob(cursor, "untethered_left_icon");
734             assertColumnBlob(cursor, "untethered_right_icon");
735             assertColumnBlob(cursor, "untethered_case_icon");
736             assertColumnBlob(cursor, "untethered_left_battery");
737             assertColumnBlob(cursor, "untethered_right_battery");
738             assertColumnBlob(cursor, "untethered_case_battery");
739             assertColumnBlob(cursor, "untethered_left_charging");
740             assertColumnBlob(cursor, "untethered_right_charging");
741             assertColumnBlob(cursor, "untethered_case_charging");
742 
743             // Check whether metadata values are migrated to version 102 successfully
744             assertColumnBlobData(cursor, "manufacturer_name", testString.getBytes());
745             assertColumnBlobData(cursor, "model_name", testString.getBytes());
746             assertColumnBlobData(cursor, "software_version", testString.getBytes());
747             assertColumnBlobData(cursor, "hardware_version", testString.getBytes());
748             assertColumnBlobData(cursor, "companion_app", testString.getBytes());
749             assertColumnBlobData(cursor, "main_icon", testString.getBytes());
750             assertColumnBlobData(cursor, "is_untethered_headset", testString.getBytes());
751             assertColumnBlobData(cursor, "untethered_left_icon", testString.getBytes());
752             assertColumnBlobData(cursor, "untethered_right_icon", testString.getBytes());
753             assertColumnBlobData(cursor, "untethered_case_icon", testString.getBytes());
754             assertColumnBlobData(cursor, "untethered_left_battery", testString.getBytes());
755             assertColumnBlobData(cursor, "untethered_right_battery", testString.getBytes());
756             assertColumnBlobData(cursor, "untethered_case_battery", testString.getBytes());
757             assertColumnBlobData(cursor, "untethered_left_charging", testString.getBytes());
758             assertColumnBlobData(cursor, "untethered_right_charging", testString.getBytes());
759             assertColumnBlobData(cursor, "untethered_case_charging", testString.getBytes());
760         }
761     }
762 
763     @Test
testDatabaseMigration_102_103()764     public void testDatabaseMigration_102_103() throws IOException {
765         String testString = "TEST STRING";
766 
767         // Create a database with version 102
768         SupportSQLiteDatabase db = testHelper.createDatabase(DB_NAME, 102);
769         Cursor cursor = db.query("SELECT * FROM metadata");
770 
771         // insert a device to the database
772         ContentValues device = new ContentValues();
773         device.put("address", TEST_BT_ADDR);
774         device.put("migrated", false);
775         device.put("a2dpSupportsOptionalCodecs", -1);
776         device.put("a2dpOptionalCodecsEnabled", -1);
777         device.put("a2dp_priority", 1000);
778         device.put("a2dp_sink_priority", 1000);
779         device.put("hfp_priority", 1000);
780         device.put("hfp_client_priority", 1000);
781         device.put("hid_host_priority", 1000);
782         device.put("pan_priority", 1000);
783         device.put("pbap_priority", 1000);
784         device.put("pbap_client_priority", 1000);
785         device.put("map_priority", 1000);
786         device.put("sap_priority", 1000);
787         device.put("hearing_aid_priority", 1000);
788         device.put("map_client_priority", 1000);
789         device.put("manufacturer_name", testString);
790         device.put("model_name", testString);
791         device.put("software_version", testString);
792         device.put("hardware_version", testString);
793         device.put("companion_app", testString);
794         device.put("main_icon", testString);
795         device.put("is_untethered_headset", testString);
796         device.put("untethered_left_icon", testString);
797         device.put("untethered_right_icon", testString);
798         device.put("untethered_case_icon", testString);
799         device.put("untethered_left_battery", testString);
800         device.put("untethered_right_battery", testString);
801         device.put("untethered_case_battery", testString);
802         device.put("untethered_left_charging", testString);
803         device.put("untethered_right_charging", testString);
804         device.put("untethered_case_charging", testString);
805         assertThat(db.insert("metadata", SQLiteDatabase.CONFLICT_IGNORE, device),
806                 CoreMatchers.not(-1));
807 
808         // Check the metadata names on version 102
809         assertHasColumn(cursor, "a2dp_priority", true);
810         assertHasColumn(cursor, "a2dp_sink_priority", true);
811         assertHasColumn(cursor, "hfp_priority", true);
812         assertHasColumn(cursor, "hfp_client_priority", true);
813         assertHasColumn(cursor, "hid_host_priority", true);
814         assertHasColumn(cursor, "pan_priority", true);
815         assertHasColumn(cursor, "pbap_priority", true);
816         assertHasColumn(cursor, "pbap_client_priority", true);
817         assertHasColumn(cursor, "map_priority", true);
818         assertHasColumn(cursor, "sap_priority", true);
819         assertHasColumn(cursor, "hearing_aid_priority", true);
820         assertHasColumn(cursor, "map_client_priority", true);
821 
822         // Migrate database from 102 to 103
823         db.close();
824         db = testHelper.runMigrationsAndValidate(DB_NAME, 103, true,
825                 MetadataDatabase.MIGRATION_102_103);
826         cursor = db.query("SELECT * FROM metadata");
827 
828         // metadata names should be changed on version 103
829         assertHasColumn(cursor, "a2dp_priority", false);
830         assertHasColumn(cursor, "a2dp_sink_priority", false);
831         assertHasColumn(cursor, "hfp_priority", false);
832         assertHasColumn(cursor, "hfp_client_priority", false);
833         assertHasColumn(cursor, "hid_host_priority", false);
834         assertHasColumn(cursor, "pan_priority", false);
835         assertHasColumn(cursor, "pbap_priority", false);
836         assertHasColumn(cursor, "pbap_client_priority", false);
837         assertHasColumn(cursor, "map_priority", false);
838         assertHasColumn(cursor, "sap_priority", false);
839         assertHasColumn(cursor, "hearing_aid_priority", false);
840         assertHasColumn(cursor, "map_client_priority", false);
841 
842         assertHasColumn(cursor, "a2dp_connection_policy", true);
843         assertHasColumn(cursor, "a2dp_sink_connection_policy", true);
844         assertHasColumn(cursor, "hfp_connection_policy", true);
845         assertHasColumn(cursor, "hfp_client_connection_policy", true);
846         assertHasColumn(cursor, "hid_host_connection_policy", true);
847         assertHasColumn(cursor, "pan_connection_policy", true);
848         assertHasColumn(cursor, "pbap_connection_policy", true);
849         assertHasColumn(cursor, "pbap_client_connection_policy", true);
850         assertHasColumn(cursor, "map_connection_policy", true);
851         assertHasColumn(cursor, "sap_connection_policy", true);
852         assertHasColumn(cursor, "hearing_aid_connection_policy", true);
853         assertHasColumn(cursor, "map_client_connection_policy", true);
854 
855         while (cursor.moveToNext()) {
856             // Check PRIORITY_AUTO_CONNECT (1000) was replaced with CONNECTION_POLICY_ALLOWED (100)
857             assertColumnIntData(cursor, "a2dp_connection_policy", 100);
858             assertColumnIntData(cursor, "a2dp_sink_connection_policy", 100);
859             assertColumnIntData(cursor, "hfp_connection_policy", 100);
860             assertColumnIntData(cursor, "hfp_client_connection_policy", 100);
861             assertColumnIntData(cursor, "hid_host_connection_policy", 100);
862             assertColumnIntData(cursor, "pan_connection_policy", 100);
863             assertColumnIntData(cursor, "pbap_connection_policy", 100);
864             assertColumnIntData(cursor, "pbap_client_connection_policy", 100);
865             assertColumnIntData(cursor, "map_connection_policy", 100);
866             assertColumnIntData(cursor, "sap_connection_policy", 100);
867             assertColumnIntData(cursor, "hearing_aid_connection_policy", 100);
868             assertColumnIntData(cursor, "map_client_connection_policy", 100);
869 
870             // Check whether metadata data type are blob
871             assertColumnBlob(cursor, "manufacturer_name");
872             assertColumnBlob(cursor, "model_name");
873             assertColumnBlob(cursor, "software_version");
874             assertColumnBlob(cursor, "hardware_version");
875             assertColumnBlob(cursor, "companion_app");
876             assertColumnBlob(cursor, "main_icon");
877             assertColumnBlob(cursor, "is_untethered_headset");
878             assertColumnBlob(cursor, "untethered_left_icon");
879             assertColumnBlob(cursor, "untethered_right_icon");
880             assertColumnBlob(cursor, "untethered_case_icon");
881             assertColumnBlob(cursor, "untethered_left_battery");
882             assertColumnBlob(cursor, "untethered_right_battery");
883             assertColumnBlob(cursor, "untethered_case_battery");
884             assertColumnBlob(cursor, "untethered_left_charging");
885             assertColumnBlob(cursor, "untethered_right_charging");
886             assertColumnBlob(cursor, "untethered_case_charging");
887 
888             // Check whether metadata values are migrated to version 103 successfully
889             assertColumnBlobData(cursor, "manufacturer_name", testString.getBytes());
890             assertColumnBlobData(cursor, "model_name", testString.getBytes());
891             assertColumnBlobData(cursor, "software_version", testString.getBytes());
892             assertColumnBlobData(cursor, "hardware_version", testString.getBytes());
893             assertColumnBlobData(cursor, "companion_app", testString.getBytes());
894             assertColumnBlobData(cursor, "main_icon", testString.getBytes());
895             assertColumnBlobData(cursor, "is_untethered_headset", testString.getBytes());
896             assertColumnBlobData(cursor, "untethered_left_icon", testString.getBytes());
897             assertColumnBlobData(cursor, "untethered_right_icon", testString.getBytes());
898             assertColumnBlobData(cursor, "untethered_case_icon", testString.getBytes());
899             assertColumnBlobData(cursor, "untethered_left_battery", testString.getBytes());
900             assertColumnBlobData(cursor, "untethered_right_battery", testString.getBytes());
901             assertColumnBlobData(cursor, "untethered_case_battery", testString.getBytes());
902             assertColumnBlobData(cursor, "untethered_left_charging", testString.getBytes());
903             assertColumnBlobData(cursor, "untethered_right_charging", testString.getBytes());
904             assertColumnBlobData(cursor, "untethered_case_charging", testString.getBytes());
905         }
906     }
907 
908     @Test
testDatabaseMigration_103_104()909     public void testDatabaseMigration_103_104() throws IOException {
910         String testString = "TEST STRING";
911 
912         // Create a database with version 103
913         SupportSQLiteDatabase db = testHelper.createDatabase(DB_NAME, 103);
914 
915         // insert a device to the database
916         ContentValues device = new ContentValues();
917         device.put("address", TEST_BT_ADDR);
918         device.put("migrated", false);
919         device.put("a2dpSupportsOptionalCodecs", -1);
920         device.put("a2dpOptionalCodecsEnabled", -1);
921         device.put("a2dp_connection_policy", 100);
922         device.put("a2dp_sink_connection_policy", 100);
923         device.put("hfp_connection_policy", 100);
924         device.put("hfp_client_connection_policy", 100);
925         device.put("hid_host_connection_policy", 100);
926         device.put("pan_connection_policy", 100);
927         device.put("pbap_connection_policy", 100);
928         device.put("pbap_client_connection_policy", 100);
929         device.put("map_connection_policy", 100);
930         device.put("sap_connection_policy", 100);
931         device.put("hearing_aid_connection_policy", 100);
932         device.put("map_client_connection_policy", 100);
933         device.put("manufacturer_name", testString);
934         device.put("model_name", testString);
935         device.put("software_version", testString);
936         device.put("hardware_version", testString);
937         device.put("companion_app", testString);
938         device.put("main_icon", testString);
939         device.put("is_untethered_headset", testString);
940         device.put("untethered_left_icon", testString);
941         device.put("untethered_right_icon", testString);
942         device.put("untethered_case_icon", testString);
943         device.put("untethered_left_battery", testString);
944         device.put("untethered_right_battery", testString);
945         device.put("untethered_case_battery", testString);
946         device.put("untethered_left_charging", testString);
947         device.put("untethered_right_charging", testString);
948         device.put("untethered_case_charging", testString);
949         assertThat(db.insert("metadata", SQLiteDatabase.CONFLICT_IGNORE, device),
950                 CoreMatchers.not(-1));
951 
952         // Migrate database from 103 to 104
953         db.close();
954         db = testHelper.runMigrationsAndValidate(DB_NAME, 104, true,
955                 MetadataDatabase.MIGRATION_103_104);
956         Cursor cursor = db.query("SELECT * FROM metadata");
957 
958         assertHasColumn(cursor, "last_active_time", true);
959         assertHasColumn(cursor, "is_active_a2dp_device", true);
960 
961         while (cursor.moveToNext()) {
962             // Check the two new columns were added with their default values
963             assertColumnIntData(cursor, "last_active_time", -1);
964             assertColumnIntData(cursor, "is_active_a2dp_device", 0);
965         }
966     }
967 
968     @Test
testDatabaseMigration_104_105()969     public void testDatabaseMigration_104_105() throws IOException {
970         // Create a database with version 104
971         SupportSQLiteDatabase db = testHelper.createDatabase(DB_NAME, 104);
972 
973         // insert a device to the database
974         ContentValues device = new ContentValues();
975         device.put("address", TEST_BT_ADDR);
976 
977         // Migrate database from 104 to 105
978         db.close();
979         db = testHelper.runMigrationsAndValidate(DB_NAME, 105, true,
980                 MetadataDatabase.MIGRATION_104_105);
981         Cursor cursor = db.query("SELECT * FROM metadata");
982 
983         assertHasColumn(cursor, "device_type", true);
984         assertHasColumn(cursor, "main_battery", true);
985         assertHasColumn(cursor, "main_charging", true);
986         assertHasColumn(cursor, "main_low_battery_threshold", true);
987         assertHasColumn(cursor, "untethered_right_low_battery_threshold", true);
988         assertHasColumn(cursor, "untethered_left_low_battery_threshold", true);
989         assertHasColumn(cursor, "untethered_case_low_battery_threshold", true);
990 
991         while (cursor.moveToNext()) {
992             // Check the old column have the original value
993             assertColumnBlobData(cursor, "address", TEST_BT_ADDR.getBytes());
994 
995             // Check the new columns were added with their default values
996             assertColumnBlobData(cursor, "device_type", null);
997             assertColumnBlobData(cursor, "main_battery", null);
998             assertColumnBlobData(cursor, "main_charging", null);
999             assertColumnBlobData(cursor, "main_low_battery_threshold", null);
1000             assertColumnBlobData(cursor, "untethered_right_low_battery_threshold", null);
1001             assertColumnBlobData(cursor, "untethered_left_low_battery_threshold", null);
1002             assertColumnBlobData(cursor, "untethered_case_low_battery_threshold", null);
1003         }
1004     }
1005 
1006     @Test
testDatabaseMigration_105_106()1007     public void testDatabaseMigration_105_106() throws IOException {
1008         String testString = "TEST STRING";
1009 
1010         // Create a database with version 105
1011         SupportSQLiteDatabase db = testHelper.createDatabase(DB_NAME, 105);
1012 
1013         // insert a device to the database
1014         ContentValues device = new ContentValues();
1015         device.put("address", TEST_BT_ADDR);
1016         device.put("migrated", false);
1017         assertThat(db.insert("metadata", SQLiteDatabase.CONFLICT_IGNORE, device),
1018                 CoreMatchers.not(-1));
1019 
1020         // Migrate database from 105 to 106
1021         db.close();
1022         db = testHelper.runMigrationsAndValidate(DB_NAME, 106, true,
1023                 MetadataDatabase.MIGRATION_105_106);
1024         Cursor cursor = db.query("SELECT * FROM metadata");
1025 
1026         assertHasColumn(cursor, "le_audio_connection_policy", true);
1027 
1028         while (cursor.moveToNext()) {
1029             // Check the new columns was added with default value
1030             assertColumnIntData(cursor, "le_audio_connection_policy", 100);
1031         }
1032     }
1033 
1034     /**
1035      * Helper function to check whether the database has the expected column
1036      */
assertHasColumn(Cursor cursor, String columnName, boolean hasColumn)1037     void assertHasColumn(Cursor cursor, String columnName, boolean hasColumn) {
1038         if (hasColumn) {
1039             assertThat(cursor.getColumnIndex(columnName), CoreMatchers.not(-1));
1040         } else {
1041             assertThat(cursor.getColumnIndex(columnName), CoreMatchers.is(-1));
1042         }
1043     }
1044 
1045     /**
1046      * Helper function to check whether the database has the expected value
1047      */
assertColumnIntData(Cursor cursor, String columnName, int value)1048     void assertColumnIntData(Cursor cursor, String columnName, int value) {
1049         assertThat(cursor.getInt(cursor.getColumnIndex(columnName)), CoreMatchers.is(value));
1050     }
1051 
1052     /**
1053      * Helper function to check whether the column data type is BLOB
1054      */
assertColumnBlob(Cursor cursor, String columnName)1055     void assertColumnBlob(Cursor cursor, String columnName) {
1056         assertThat(cursor.getType(cursor.getColumnIndex(columnName)),
1057                 CoreMatchers.is(Cursor.FIELD_TYPE_BLOB));
1058     }
1059 
1060     /**
1061      * Helper function to check the BLOB data in a column is expected
1062      */
assertColumnBlobData(Cursor cursor, String columnName, byte[] data)1063     void assertColumnBlobData(Cursor cursor, String columnName, byte[] data) {
1064         assertThat(cursor.getBlob(cursor.getColumnIndex(columnName)),
1065                 CoreMatchers.is(data));
1066     }
1067 
restartDatabaseManagerHelper()1068     void restartDatabaseManagerHelper() {
1069         Metadata data = new Metadata(LOCAL_STORAGE);
1070         data.migrated = true;
1071         mDatabase.insert(data);
1072 
1073         mDatabaseManager.cleanup();
1074         mDatabaseManager.start(mDatabase);
1075         // Wait for handler thread finish its task.
1076         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
1077 
1078         // Remove local storage
1079         mDatabaseManager.mMetadataCache.remove(LOCAL_STORAGE);
1080         mDatabaseManager.deleteDatabase(data);
1081         // Wait for handler thread finish its task.
1082         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
1083     }
1084 
testSetGetProfileConnectionPolicyCase(boolean stored, int connectionPolicy, int expectedConnectionPolicy, boolean expectedSetResult)1085     void testSetGetProfileConnectionPolicyCase(boolean stored, int connectionPolicy,
1086             int expectedConnectionPolicy, boolean expectedSetResult) {
1087         if (stored) {
1088             Metadata data = new Metadata(TEST_BT_ADDR);
1089             mDatabaseManager.mMetadataCache.put(TEST_BT_ADDR, data);
1090             mDatabase.insert(data);
1091         }
1092         Assert.assertEquals(expectedSetResult,
1093                 mDatabaseManager.setProfileConnectionPolicy(mTestDevice,
1094                 BluetoothProfile.HEADSET, connectionPolicy));
1095         Assert.assertEquals(expectedConnectionPolicy,
1096                 mDatabaseManager.getProfileConnectionPolicy(mTestDevice, BluetoothProfile.HEADSET));
1097         // Wait for database update
1098         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
1099 
1100         List<Metadata> list = mDatabase.load();
1101 
1102         // Check number of metadata in the database
1103         if (!stored) {
1104             if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
1105                     && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
1106                 // Database won't be updated
1107                 Assert.assertEquals(0, list.size());
1108                 return;
1109             }
1110         }
1111         Assert.assertEquals(1, list.size());
1112 
1113         // Check whether the device is in database
1114         restartDatabaseManagerHelper();
1115         Assert.assertEquals(expectedConnectionPolicy,
1116                 mDatabaseManager.getProfileConnectionPolicy(mTestDevice, BluetoothProfile.HEADSET));
1117 
1118         mDatabaseManager.factoryReset();
1119         mDatabaseManager.mMetadataCache.clear();
1120         // Wait for clear database
1121         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
1122     }
1123 
testSetGetA2dpOptionalCodecsCase(int test, boolean stored, int value, int expectedValue)1124     void testSetGetA2dpOptionalCodecsCase(int test, boolean stored, int value, int expectedValue) {
1125         if (stored) {
1126             Metadata data = new Metadata(TEST_BT_ADDR);
1127             mDatabaseManager.mMetadataCache.put(TEST_BT_ADDR, data);
1128             mDatabase.insert(data);
1129         }
1130         if (test == A2DP_SUPPORT_OP_CODEC_TEST) {
1131             mDatabaseManager.setA2dpSupportsOptionalCodecs(mTestDevice, value);
1132             Assert.assertEquals(expectedValue,
1133                     mDatabaseManager.getA2dpSupportsOptionalCodecs(mTestDevice));
1134         } else {
1135             mDatabaseManager.setA2dpOptionalCodecsEnabled(mTestDevice, value);
1136             Assert.assertEquals(expectedValue,
1137                     mDatabaseManager.getA2dpOptionalCodecsEnabled(mTestDevice));
1138         }
1139         // Wait for database update
1140         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
1141 
1142         List<Metadata> list = mDatabase.load();
1143 
1144         // Check number of metadata in the database
1145         if (!stored) {
1146             // Database won't be updated
1147             Assert.assertEquals(0, list.size());
1148             return;
1149         }
1150         Assert.assertEquals(1, list.size());
1151 
1152         // Check whether the device is in database
1153         restartDatabaseManagerHelper();
1154         if (test == A2DP_SUPPORT_OP_CODEC_TEST) {
1155             Assert.assertEquals(expectedValue,
1156                     mDatabaseManager.getA2dpSupportsOptionalCodecs(mTestDevice));
1157         } else {
1158             Assert.assertEquals(expectedValue,
1159                     mDatabaseManager.getA2dpOptionalCodecsEnabled(mTestDevice));
1160         }
1161 
1162         mDatabaseManager.factoryReset();
1163         mDatabaseManager.mMetadataCache.clear();
1164         // Wait for clear database
1165         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
1166     }
1167 
testSetGetCustomMetaCase(boolean stored, int key, byte[] value, boolean expectedResult)1168     void testSetGetCustomMetaCase(boolean stored, int key, byte[] value, boolean expectedResult) {
1169         byte[] testValue = "test value".getBytes();
1170         int verifyTime = 1;
1171         if (stored) {
1172             Metadata data = new Metadata(TEST_BT_ADDR);
1173             mDatabaseManager.mMetadataCache.put(TEST_BT_ADDR, data);
1174             mDatabase.insert(data);
1175             Assert.assertEquals(expectedResult,
1176                     mDatabaseManager.setCustomMeta(mTestDevice, key, testValue));
1177             verify(mAdapterService).metadataChanged(TEST_BT_ADDR, key, testValue);
1178             verifyTime++;
1179         }
1180         Assert.assertEquals(expectedResult,
1181                 mDatabaseManager.setCustomMeta(mTestDevice, key, value));
1182         if (expectedResult) {
1183             // Check for callback and get value
1184             verify(mAdapterService, times(verifyTime)).metadataChanged(TEST_BT_ADDR, key, value);
1185             Assert.assertEquals(value,
1186                     mDatabaseManager.getCustomMeta(mTestDevice, key));
1187         } else {
1188             Assert.assertNull(mDatabaseManager.getCustomMeta(mTestDevice, key));
1189             return;
1190         }
1191         // Wait for database update
1192         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
1193 
1194         // Check whether the value is saved in database
1195         restartDatabaseManagerHelper();
1196         Assert.assertArrayEquals(value,
1197                 mDatabaseManager.getCustomMeta(mTestDevice, key));
1198 
1199         mDatabaseManager.factoryReset();
1200         mDatabaseManager.mMetadataCache.clear();
1201         // Wait for clear database
1202         TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper());
1203     }
1204 }
1205