1package com.android.bluetooth.tests; 2 3import java.io.IOException; 4import java.util.ArrayList; 5import java.util.Arrays; 6import java.util.concurrent.CountDownLatch; 7 8import javax.obex.HeaderSet; 9import javax.obex.Operation; 10import javax.obex.ServerRequestHandler; 11 12import junit.framework.Assert; 13import android.annotation.TargetApi; 14import android.bluetooth.BluetoothServerSocket; 15import android.bluetooth.BluetoothSocket; 16import android.net.LocalServerSocket; 17import android.net.LocalSocket; 18import android.os.Build; 19import android.os.RemoteException; 20import android.test.AndroidTestCase; 21import android.util.Log; 22 23import com.android.bluetooth.BluetoothObexTransport; 24import com.android.bluetooth.tests.TestSequencer.OPTYPE; 25 26@TargetApi(Build.VERSION_CODES.KITKAT) 27public class MapObexLevelTest extends AndroidTestCase implements ITestSequenceConfigurator { 28 protected static String TAG = "MapObexLevelTest"; 29 protected static final boolean D = true; 30 protected static final boolean TRACE = false; 31 protected static final boolean DELAY_PASS_30_SEC = true; 32 33 // 128 bit UUID for MAP MAS 34 static final byte[] MAS_TARGET = new byte[] { 35 (byte)0xBB, (byte)0x58, (byte)0x2B, (byte)0x40, 36 (byte)0x42, (byte)0x0C, (byte)0x11, (byte)0xDB, 37 (byte)0xB0, (byte)0xDE, (byte)0x08, (byte)0x00, 38 (byte)0x20, (byte)0x0C, (byte)0x9A, (byte)0x66 39 }; 40 41 // 128 bit UUID for MAP MNS 42 static final byte[] MNS_TARGET = new byte[] { 43 (byte)0xBB, (byte)0x58, (byte)0x2B, (byte)0x41, 44 (byte)0x42, (byte)0x0C, (byte)0x11, (byte)0xDB, 45 (byte)0xB0, (byte)0xDE, (byte)0x08, (byte)0x00, 46 (byte)0x20, (byte)0x0C, (byte)0x9A, (byte)0x66 47 }; 48 49 /* Message types */ 50 static final String TYPE_GET_FOLDER_LISTING = "x-obex/folder-listing"; 51 static final String TYPE_GET_MESSAGE_LISTING = "x-bt/MAP-msg-listing"; 52 static final String TYPE_GET_CONVO_LISTING = "x-bt/MAP-convo-listing"; 53 static final String TYPE_MESSAGE = "x-bt/message"; 54 static final String TYPE_SET_MESSAGE_STATUS = "x-bt/messageStatus"; 55 static final String TYPE_SET_NOTIFICATION_REGISTRATION = "x-bt/MAP-NotificationRegistration"; 56 static final String TYPE_MESSAGE_UPDATE = "x-bt/MAP-messageUpdate"; 57 static final String TYPE_GET_MAS_INSTANCE_INFORMATION = "x-bt/MASInstanceInformation"; 58 59 public void testFolder() { 60 testLocalSockets(new buildFolderTestSeq()); 61 } 62 63 public void testFolderServer() { 64 testServer(new buildFolderTestSeq()); 65 } 66 67 public void testFolderClient() { 68 testClient(new buildFolderTestSeq()); 69 } 70 71 protected class buildFolderTestSeq implements ITestSequenceBuilder { 72 @Override 73 public void build(TestSequencer sequencer) { 74 addConnectStep(sequencer); 75 76 MapStepsFolder.addGoToMsgFolderSteps(sequencer); 77 78 // MAP DISCONNECT Step 79 addDisconnectStep(sequencer); 80 } 81 } 82 83 84 public void testConvo() { 85 testLocalSockets(new buildConvoTestSeq()); 86 } 87 88 public void testConvoServer() { 89 testServer(new buildConvoTestSeq()); 90 } 91 92 public void testConvoClient() { 93 testClient(new buildConvoTestSeq()); 94 } 95 96 class buildConvoTestSeq implements ITestSequenceBuilder { 97 @Override 98 public void build(TestSequencer sequencer) { 99 addConnectStep(sequencer); 100 101 MapStepsFolder.addGoToMsgFolderSteps(sequencer); 102 103 MapStepsConvo.addConvoListingSteps(sequencer); 104 105 // MAP DISCONNECT Step 106 addDisconnectStep(sequencer); 107 } 108 } 109 110 /** 111 * Run the test sequence using a local socket on a single device. 112 * Throughput around 4000 kbyte/s - with a larger OBEX package size. 113 * 114 * Downside: Unable to get a BT-snoop file... 115 */ 116 protected void testLocalSockets(ITestSequenceBuilder builder) { 117 mContext = this.getContext(); 118 MapTestData.init(mContext); 119 Log.i(TAG,"Setting up sockets..."); 120 121 try { 122 /* Create and interconnect local pipes for transport */ 123 LocalServerSocket serverSock = new LocalServerSocket("com.android.bluetooth.tests.sock"); 124 LocalSocket clientSock = new LocalSocket(); 125 LocalSocket acceptSock; 126 127 clientSock.connect(serverSock.getLocalSocketAddress()); 128 129 acceptSock = serverSock.accept(); 130 131 /* Create the OBEX transport objects to wrap the pipes - enable SRM */ 132 ObexPipeTransport clientTransport = new ObexPipeTransport(clientSock.getInputStream(), 133 clientSock.getOutputStream(), true); 134 ObexPipeTransport serverTransport = new ObexPipeTransport(acceptSock.getInputStream(), 135 acceptSock.getOutputStream(), true); 136 137 TestSequencer sequencer = new TestSequencer(clientTransport, serverTransport, this); 138 139 builder.build(sequencer); 140 141 //Debug.startMethodTracing("ObexTrace"); 142 assertTrue(sequencer.run(mContext)); 143 //Debug.stopMethodTracing(); 144 145 clientSock.close(); 146 acceptSock.close(); 147 serverSock.close(); 148 } catch (IOException e) { 149 Log.e(TAG, "IOException", e); 150 } 151 } 152 153 /** 154 * Server side of a dual device test using a Bluetooth Socket. 155 * Enables the possibility to get a BT-snoop file. 156 * If you need the btsnoop from the device which completes the test with success 157 * you need to add a delay after the test ends, and fetch the file before this delay 158 * expires. When the test completes, the Bluetooth subsystem will be restarted, causing 159 * a new bt-snoop to overwrite the one used in test. 160 */ 161 public void testServer(ITestSequenceBuilder builder) { 162 mContext = this.getContext(); 163 MapTestData.init(mContext); 164 Log.i(TAG,"Setting up sockets..."); 165 166 try { 167 /* This will turn on BT and create a server socket on which accept can be called. */ 168 BluetoothServerSocket serverSocket=ObexTest.createServerSocket(BluetoothSocket.TYPE_L2CAP, true); 169 170 Log.i(TAG, "Waiting for client to connect..."); 171 BluetoothSocket socket = serverSocket.accept(); 172 Log.i(TAG, "Client connected..."); 173 174 BluetoothObexTransport serverTransport = new BluetoothObexTransport(socket); 175 176 TestSequencer sequencer = new TestSequencer(null, serverTransport, this); 177 178 builder.build(sequencer); 179 180 //Debug.startMethodTracing("ObexTrace"); 181 assertTrue(sequencer.run(mContext)); 182 //Debug.stopMethodTracing(); 183 184 serverSocket.close(); 185 socket.close(); 186 } catch (IOException e) { 187 Log.e(TAG, "IOException", e); 188 } 189 if(DELAY_PASS_30_SEC) { 190 Log.i(TAG, "\n\n\nTest done - please fetch logs within 30 seconds...\n\n\n"); 191 try { 192 Thread.sleep(30000); 193 } catch (InterruptedException e) {} 194 } 195 } 196 197 /** 198 * Server side of a dual device test using a Bluetooth Socket. 199 * Enables the possibility to get a BT-snoop file. 200 * If you need the btsnoop from the device which completes the test with success 201 * you need to add a delay after the test ends, and fetch the file before this delay 202 * expires. When the test completes, the Bluetooth subsystem will be restarted, causing 203 * a new bt-snoop to overwrite the one used in test. 204 */ 205 public void testClient(ITestSequenceBuilder builder) { 206 mContext = this.getContext(); 207 MapTestData.init(mContext); 208 Log.i(TAG, "Setting up sockets..."); 209 210 try { 211 /* This will turn on BT and connect */ 212 BluetoothSocket clientSock = 213 ObexTest.connectClientSocket(BluetoothSocket.TYPE_L2CAP, true, mContext); 214 215 BluetoothObexTransport clientTransport = new BluetoothObexTransport(clientSock); 216 217 TestSequencer sequencer = new TestSequencer(clientTransport, null, this); 218 219 builder.build(sequencer); 220 221 //Debug.startMethodTracing("ObexTrace"); 222 assertTrue(sequencer.run(mContext)); 223 //Debug.stopMethodTracing(); 224 225 clientSock.close(); 226 } catch (IOException e) { 227 Log.e(TAG, "IOException", e); 228 } 229 if(DELAY_PASS_30_SEC) { 230 Log.i(TAG, "\n\n\nTest done - please fetch logs within 30 seconds...\n\n\n"); 231 try { 232 Thread.sleep(30000); 233 } catch (InterruptedException e) {} 234 } 235 } 236 237 protected void addConnectStep(TestSequencer sequencer) { 238 SeqStep step; 239 240 // MAP CONNECT Step 241 step = sequencer.addStep(OPTYPE.CONNECT, null); 242 HeaderSet hs = new HeaderSet(); 243 hs.setHeader(HeaderSet.TARGET, MAS_TARGET); 244 step.mReqHeaders = hs; 245 step.mValidator = new MapConnectValidator(); 246 //step.mServerPreAction = new MapAddSmsMessages(); // could take in parameters 247 } 248 249 protected void addDisconnectStep(TestSequencer sequencer) { 250 sequencer.addStep(OPTYPE.DISCONNECT, ObexTest.getResponsecodevalidator()); 251 } 252 253 /* Functions to validate results */ 254 255 private class MapConnectValidator implements ISeqStepValidator { 256 @Override 257 public boolean validate(SeqStep step, HeaderSet response, Operation notUsed) 258 throws IOException { 259 Assert.assertNotNull(response); 260 byte[] who = (byte[])response.getHeader(HeaderSet.WHO); 261 Assert.assertNotNull(who); 262 Assert.assertTrue(Arrays.equals(who, MAS_TARGET)); 263 Assert.assertNotNull(response.getHeader(HeaderSet.CONNECTION_ID)); 264 return true; 265 } 266 } 267 268 /** 269 * This is the function creating the Obex Server to be used in this class. 270 * Here we use a mocked version of the MapObexServer class 271 */ 272 @Override 273 public ServerRequestHandler getObexServer(ArrayList<SeqStep> sequence, 274 CountDownLatch stopLatch) { 275 try { 276 return new MapObexTestServer(mContext, sequence, stopLatch); 277 } catch (RemoteException e) { 278 Log.e(TAG, "exception", e); 279 fail("Unable to create MapObexTestServer"); 280 } 281 return null; 282 } 283 284 285} 286 287