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.sdp;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static org.mockito.Mockito.verify;
21 
22 import android.bluetooth.BluetoothAdapter;
23 import android.bluetooth.BluetoothDevice;
24 import android.bluetooth.BluetoothProfile;
25 import android.bluetooth.BluetoothUuid;
26 import android.bluetooth.SdpDipRecord;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.os.Bundle;
31 import android.os.Looper;
32 import android.os.ParcelUuid;
33 
34 import androidx.test.InstrumentationRegistry;
35 import androidx.test.filters.SmallTest;
36 import androidx.test.runner.AndroidJUnit4;
37 
38 import com.android.bluetooth.R;
39 import com.android.bluetooth.sdp.SdpManager;
40 import com.android.bluetooth.TestUtils;
41 import com.android.bluetooth.btservice.AbstractionLayer;
42 import com.android.bluetooth.btservice.AdapterService;
43 import com.android.bluetooth.Utils;
44 
45 import org.junit.After;
46 import org.junit.Assume;
47 import org.junit.Before;
48 import org.junit.Rule;
49 import org.junit.Test;
50 import org.junit.runner.RunWith;
51 import org.mockito.ArgumentCaptor;
52 import org.mockito.Mock;
53 import org.mockito.MockitoAnnotations;
54 
55 @SmallTest
56 @RunWith(AndroidJUnit4.class)
57 public class DipTest {
58     private BluetoothAdapter mAdapter;
59     private Context mTargetContext;
60     private SdpManager mSdpManager;
61     private BluetoothDevice mTestDevice;
62 
63     private ArgumentCaptor<Intent> mIntentArgument = ArgumentCaptor.forClass(Intent.class);
64     private ArgumentCaptor<String> mStringArgument = ArgumentCaptor.forClass(String.class);
65     private ArgumentCaptor<Bundle> mBundleArgument = ArgumentCaptor.forClass(Bundle.class);
66 
67     @Mock private AdapterService mAdapterService = null;
68 
69     @Before
setUp()70     public void setUp() throws Exception {
71         mTargetContext = InstrumentationRegistry.getTargetContext();
72         // Set up mocks and test assets
73         MockitoAnnotations.initMocks(this);
74 
75         TestUtils.setAdapterService(mAdapterService);
76 
77         if (Looper.myLooper() == null) {
78             Looper.prepare();
79         }
80 
81         mAdapter = BluetoothAdapter.getDefaultAdapter();
82         mSdpManager = SdpManager.init(mAdapterService);
83 
84         // Get a device for testing
85         mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05");
86     }
87 
88     @After
tearDown()89     public void tearDown() throws Exception {
90     }
91 
verifyDipSdpRecordIntent(ArgumentCaptor<Intent> intentArgument, int status, BluetoothDevice device, byte[] uuid, int specificationId, int vendorId, int vendorIdSource, int productId, int version, boolean primaryRecord)92     private void verifyDipSdpRecordIntent(ArgumentCaptor<Intent> intentArgument,
93             int status, BluetoothDevice device,
94             byte[] uuid,  int specificationId,
95             int vendorId, int vendorIdSource,
96             int productId, int version,
97             boolean primaryRecord) {
98         Intent intent = intentArgument.getValue();
99 
100         assertThat(intent).isNotEqualTo(null);
101         assertThat(intent.getAction()).isEqualTo(BluetoothDevice.ACTION_SDP_RECORD);
102         assertThat(device).isEqualTo(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE));
103         assertThat(Utils.byteArrayToUuid(uuid)[0]).isEqualTo(intent.getParcelableExtra(BluetoothDevice.EXTRA_UUID));
104         assertThat(status).isEqualTo(intent.getIntExtra(BluetoothDevice.EXTRA_SDP_SEARCH_STATUS, -1));
105 
106         SdpDipRecord record = intent.getParcelableExtra(BluetoothDevice.EXTRA_SDP_RECORD);
107         assertThat(record).isNotEqualTo(null);
108         assertThat(specificationId).isEqualTo(record.getSpecificationId());
109         assertThat(vendorId).isEqualTo(record.getVendorId());
110         assertThat(vendorIdSource).isEqualTo(record.getVendorIdSource());
111         assertThat(productId).isEqualTo(record.getProductId());
112         assertThat(version).isEqualTo(record.getVersion());
113         assertThat(primaryRecord).isEqualTo(record.getPrimaryRecord());
114     }
115 
116     /**
117      * Test that an outgoing connection/disconnection succeeds
118      */
119     @Test
120     @SmallTest
testDipCallbackSuccess()121     public void testDipCallbackSuccess() {
122         // DIP uuid in bytes
123         byte[] uuid = {0, 0, 18, 0, 0, 0, 16, 0, -128, 0, 0, -128, 95, -101, 52, -5};
124         int specificationId = 0x0103;
125         int vendorId = 0x18d1;
126         int vendorIdSource = 1;
127         int productId = 0x1234;
128         int version = 0x0100;
129         boolean primaryRecord = true;
130         boolean moreResults = false;
131 
132         mSdpManager.sdpSearch(mTestDevice, BluetoothUuid.DIP);
133         mSdpManager.sdpDipRecordFoundCallback(AbstractionLayer.BT_STATUS_SUCCESS,
134                 Utils.getByteAddress(mTestDevice), uuid, specificationId,
135                 vendorId, vendorIdSource, productId, version, primaryRecord, moreResults);
136         verify(mAdapterService).sendBroadcast(mIntentArgument.capture(), mStringArgument.capture(),
137                 mBundleArgument.capture());
138         verifyDipSdpRecordIntent(mIntentArgument, AbstractionLayer.BT_STATUS_SUCCESS, mTestDevice,
139                 uuid, specificationId, vendorId, vendorIdSource, productId, version, primaryRecord);
140     }
141 }
142