View Javadoc

1   /**
2    *  BlueCove - Java library for Bluetooth
3    *  Copyright (C) 2006-2007 Vlad Skarzhevskyy
4    * 
5    *  Licensed to the Apache Software Foundation (ASF) under one
6    *  or more contributor license agreements.  See the NOTICE file
7    *  distributed with this work for additional information
8    *  regarding copyright ownership.  The ASF licenses this file
9    *  to you under the Apache License, Version 2.0 (the
10   *  "License"); you may not use this file except in compliance
11   *  with the License.  You may obtain a copy of the License at
12   *
13   *    http://www.apache.org/licenses/LICENSE-2.0
14   *
15   *  Unless required by applicable law or agreed to in writing,
16   *  software distributed under the License is distributed on an
17   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18   *  KIND, either express or implied.  See the License for the
19   *  specific language governing permissions and limitations
20   *  under the License.
21   *
22   *  @author vlads
23   *  @version $Id: ServiceRecordTester.java 2607 2008-12-17 23:51:33Z skarzhevskyy $
24   */
25  package net.sf.bluecove;
26  
27  import java.util.Enumeration;
28  import java.util.Vector;
29  
30  import javax.bluetooth.BluetoothStateException;
31  import javax.bluetooth.DataElement;
32  import javax.bluetooth.LocalDevice;
33  import javax.bluetooth.ServiceRecord;
34  import javax.bluetooth.UUID;
35  
36  import org.bluecove.tester.log.Logger;
37  import org.bluecove.tester.util.RuntimeDetect;
38  
39  import junit.framework.Assert;
40  import junit.framework.AssertionFailedError;
41  import net.sf.bluecove.util.BluetoothTypesInfo;
42  import net.sf.bluecove.util.CollectionUtils;
43  
44  /**
45   * 
46   */
47  public class ServiceRecordTester {
48  
49  	public static final int ServiceClassIDList = 0x0001;
50  
51  	private static Vector allTestServiceAttributes = new Vector();
52  
53  	static {
54  		buildAllTestServiceAttributes();
55  	}
56  
57  	public static boolean hasServiceClassUUID(ServiceRecord servRecord, UUID uuid) {
58  		DataElement attrDataElement = servRecord.getAttributeValue(ServiceClassIDList);
59  		if ((attrDataElement == null) || (attrDataElement.getDataType() != DataElement.DATSEQ)
60  				|| attrDataElement.getSize() == 0) {
61  			Logger.warn("Bogus ServiceClassIDList");
62  			if (RuntimeDetect.isBlueCove) {
63  				return false;
64  			}
65  
66  			// Avetana version 3.17
67  			if ((attrDataElement != null) && (attrDataElement.getDataType() == DataElement.UUID)) {
68  				return uuid.equals(attrDataElement.getValue());
69  			}
70  
71  			return false;
72  		}
73  		// Logger.debug("test ServiceClassIDList:" +
74  		// BluetoothTypesInfo.toString(attrDataElement));
75  
76  		Object value = attrDataElement.getValue();
77  		if ((value == null) || (!(value instanceof Enumeration))) {
78  			Logger.warn("Bogus Value in DATSEQ");
79  			if (value != null) {
80  				Logger.error("DATSEQ class " + value.getClass().getName());
81  			}
82  			return false;
83  		}
84  		for (Enumeration e = (Enumeration) value; e.hasMoreElements();) {
85  			Object element = e.nextElement();
86  			if (!(element instanceof DataElement)) {
87  				Logger.warn("Bogus element in DATSEQ, " + value.getClass().getName());
88  				continue;
89  			}
90  			DataElement dataElement = (DataElement) element;
91  			if ((dataElement.getDataType() == DataElement.UUID)) {
92  				if (uuid.equals(dataElement.getValue())) {
93  					return true;
94  				} else {
95  					// Logger.debug("not same " +
96  					// BluetoothTypesInfo.toString((UUID)dataElement.getValue()));
97  				}
98  			} else {
99  				// Logger.debug("test not UUID:" +
100 				// BluetoothTypesInfo.toString(dataElement));
101 			}
102 		}
103 
104 		return false;
105 	}
106 
107 	public static boolean hasServiceClassBlieCoveUUID(ServiceRecord servRecord) {
108 		return hasServiceClassUUID(servRecord, Configuration.blueCoveUUID())
109 				|| hasServiceClassUUID(servRecord, Configuration.blueCoveL2CAPUUID());
110 	}
111 
112 	public static boolean equals(DataElement de1, DataElement de2) {
113 		if ((de1 == null) || (de2 == null)) {
114 			return false;
115 		}
116 		try {
117 			if (de1.getDataType() != de2.getDataType()) {
118 				return false;
119 			}
120 			switch (de1.getDataType()) {
121 			case DataElement.U_INT_1:
122 			case DataElement.U_INT_2:
123 			case DataElement.U_INT_4:
124 			case DataElement.INT_1:
125 			case DataElement.INT_2:
126 			case DataElement.INT_4:
127 			case DataElement.INT_8:
128 				return (de1.getLong() == de2.getLong());
129 			case DataElement.URL:
130 			case DataElement.STRING:
131 			case DataElement.UUID:
132 				return de1.getValue().equals(de2.getValue());
133 			case DataElement.INT_16:
134 			case DataElement.U_INT_8:
135 			case DataElement.U_INT_16:
136 				byte[] byteAray1 = (byte[]) de1.getValue();
137 				byte[] byteAray2 = (byte[]) de2.getValue();
138 				if (byteAray1.length != byteAray2.length) {
139 					return false;
140 				}
141 				for (int k = 0; k < byteAray1.length; k++) {
142 					if (byteAray1[k] != byteAray2[k]) {
143 						return false;
144 					}
145 				}
146 				return true;
147 			case DataElement.NULL:
148 				return true;
149 			case DataElement.BOOL:
150 				return (de1.getBoolean() == de2.getBoolean());
151 			case DataElement.DATSEQ:
152 			case DataElement.DATALT:
153 				Enumeration en1 = (Enumeration) de1.getValue();
154 				Enumeration en2 = (Enumeration) de2.getValue();
155 				for (; en1.hasMoreElements() && en2.hasMoreElements();) {
156 					DataElement d1 = (DataElement) en1.nextElement();
157 					DataElement d2 = (DataElement) en2.nextElement();
158 					if (!equals(d1, d2)) {
159 						return false;
160 					}
161 				}
162 				if (en1.hasMoreElements() || en2.hasMoreElements()) {
163 					return false;
164 				}
165 				return true;
166 			default:
167 				return false;
168 			}
169 		} catch (Throwable e) {
170 			Logger.error("DataElement equals", e);
171 			return false;
172 		}
173 	}
174 
175 	public static boolean testServiceAttributes(ServiceRecord servRecord, String servicesOnDeviceName,
176 			String servicesOnDeviceAddress) {
177 
178 		boolean isBlueCoveTestService = false;
179 
180 		boolean hadError = false;
181 
182 		long variableData = 0;
183 
184 		if (!Configuration.testServiceAttributes.booleanValue()
185 				|| ("0".equals(LocalDevice.getProperty("bluetooth.sd.attr.retrievable.max")))) {
186 			return hasServiceClassBlieCoveUUID(servRecord);
187 		}
188 
189 		boolean canTestLong = true;
190 		DataElement flagDataElement = servRecord.getAttributeValue(Consts.TEST_SERVICE_ATTRIBUTE_INT_ID);
191 		if (flagDataElement != null) {
192 			if (flagDataElement.getLong() == Consts.TEST_SERVICE_ATTRIBUTE_INT_VALUE) {
193 				canTestLong = false;
194 			}
195 		}
196 		if (canTestLong && Configuration.testAllServiceAttributes.booleanValue()) {
197 			isBlueCoveTestService = hasServiceClassBlieCoveUUID(servRecord);
198 			if (isBlueCoveTestService) {
199 				compareAllServiceAttributes(servRecord, servicesOnDeviceName);
200 			} else {
201 				Logger.debug("NOT a BlueCove service");
202 			}
203 			return isBlueCoveTestService;
204 		}
205 		if (!canTestLong && Configuration.testAllServiceAttributes.booleanValue()) {
206 			Logger.info("can't test all service Attributes");
207 		}
208 
209 		try {
210 			int[] attributeIDs = servRecord.getAttributeIDs();
211 			// Logger.debug("attributes " + attributeIDs.length);
212 
213 			boolean foundName = false;
214 			boolean foundInt = false;
215 			boolean foundStr = false;
216 			boolean foundUrl = false;
217 			boolean foundLong = false;
218 			boolean foundBytes = false;
219 
220 			boolean foundIntOK = false;
221 			boolean foundUrlOK = false;
222 			boolean foundBytesOK = false;
223 
224 			for (int j = 0; j < attributeIDs.length; j++) {
225 				int id = attributeIDs[j];
226 				try {
227 					DataElement attrDataElement = servRecord.getAttributeValue(id);
228 					Assert.assertNotNull("attrValue null", attrDataElement);
229 					switch (id) {
230 					case BluetoothTypesInfo.ServiceClassIDList:
231 						if (!hasServiceClassBlieCoveUUID(servRecord)) {
232 							TestResponderClient.failure.addFailure("ServiceClassUUID not found on "
233 									+ servicesOnDeviceName);
234 						} else {
235 							isBlueCoveTestService = true;
236 							if (Configuration.useServiceClassExtUUID.booleanValue()
237 									&& !hasServiceClassUUID(servRecord, Consts.uuidSrvClassExt)) {
238 								Logger.warn("srv SrvClassExt attr. not found");
239 								TestResponderClient.failure.addFailure("SrvClassExt UUID not found on "
240 										+ servicesOnDeviceName);
241 							}
242 						}
243 						break;
244 					case 0x0100:
245 						foundName = true;
246 						if (!Configuration.testIgnoreNotWorkingServiceAttributes.booleanValue()) {
247 							String nameValue = (String) attrDataElement.getValue();
248 							Assert.assertTrue("name [" + nameValue + "]", nameValue
249 									.startsWith((Consts.RESPONDER_SERVERNAME)));
250 							isBlueCoveTestService = true;
251 						}
252 						break;
253 					case Consts.TEST_SERVICE_ATTRIBUTE_INT_ID:
254 						foundInt = true;
255 						Assert.assertEquals("int type", Consts.TEST_SERVICE_ATTRIBUTE_INT_TYPE, attrDataElement
256 								.getDataType());
257 						Assert.assertEquals("int", Consts.TEST_SERVICE_ATTRIBUTE_INT_VALUE, attrDataElement.getLong());
258 						isBlueCoveTestService = true;
259 						foundIntOK = true;
260 						break;
261 					case Consts.TEST_SERVICE_ATTRIBUTE_LONG_ID:
262 						foundLong = true;
263 						Assert.assertEquals("long type", Consts.TEST_SERVICE_ATTRIBUTE_LONG_TYPE, attrDataElement
264 								.getDataType());
265 						if (!Configuration.testIgnoreNotWorkingServiceAttributes.booleanValue()) {
266 							Assert.assertEquals("long", Consts.TEST_SERVICE_ATTRIBUTE_LONG_VALUE, attrDataElement
267 									.getLong());
268 							isBlueCoveTestService = true;
269 						}
270 						break;
271 					case Consts.TEST_SERVICE_ATTRIBUTE_STR_ID:
272 						foundStr = true;
273 						Assert.assertEquals("str type", DataElement.STRING, attrDataElement.getDataType());
274 						if (!Configuration.testIgnoreNotWorkingServiceAttributes.booleanValue()) {
275 							Assert.assertEquals("str", Consts.TEST_SERVICE_ATTRIBUTE_STR_VALUE, attrDataElement
276 									.getValue());
277 							isBlueCoveTestService = true;
278 						}
279 						break;
280 					case Consts.TEST_SERVICE_ATTRIBUTE_URL_ID:
281 						foundUrl = true;
282 						int urlType = attrDataElement.getDataType();
283 						// URL is String on Widcomm
284 						Assert.assertTrue("url type", (DataElement.URL == urlType) || (DataElement.STRING == urlType));
285 						if (DataElement.URL != urlType) {
286 							Logger.warn("attr URL decoded as STRING");
287 						}
288 						Assert.assertEquals("url", Consts.TEST_SERVICE_ATTRIBUTE_URL_VALUE, attrDataElement.getValue());
289 						isBlueCoveTestService = true;
290 						foundUrlOK = true;
291 						break;
292 					case Consts.TEST_SERVICE_ATTRIBUTE_BYTES_ID:
293 						foundBytes = true;
294 						String byteArrayTypeName = BluetoothTypesInfo
295 								.toStringDataElementType(Consts.TEST_SERVICE_ATTRIBUTE_BYTES_TYPE);
296 						Assert.assertEquals("byte[] " + byteArrayTypeName + " type",
297 								Consts.TEST_SERVICE_ATTRIBUTE_BYTES_TYPE, attrDataElement.getDataType());
298 						byte[] byteAray;
299 						try {
300 							byteAray = (byte[]) attrDataElement.getValue();
301 						} catch (Throwable e) {
302 							Logger.warn("attr  " + byteArrayTypeName + " " + id + " " + e.getMessage());
303 							hadError = true;
304 							break;
305 						}
306 						Assert.assertEquals("byteAray.len of " + byteArrayTypeName,
307 								Consts.TEST_SERVICE_ATTRIBUTE_BYTES_VALUE.length, byteAray.length);
308 						for (int k = 0; k < byteAray.length; k++) {
309 							if (Configuration.testIgnoreNotWorkingServiceAttributes.booleanValue()
310 									&& Configuration.stackWIDCOMM && k >= 4) {
311 								// INT_16 are truncated in discovery
312 								break;
313 							}
314 							Assert.assertEquals("byte[" + k + "] of " + byteArrayTypeName,
315 									Consts.TEST_SERVICE_ATTRIBUTE_BYTES_VALUE[k], byteAray[k]);
316 						}
317 						isBlueCoveTestService = true;
318 						foundBytesOK = true;
319 						break;
320 					case Consts.VARIABLE_SERVICE_ATTRIBUTE_BYTES_ID:
321 						Assert.assertEquals("var U_INT_4 type", DataElement.U_INT_4, attrDataElement.getDataType());
322 						try {
323 							variableData = attrDataElement.getLong();
324 							// Logger.debug("Var info:" + variableData);
325 						} catch (Throwable e) {
326 							Logger.warn("attr " + id + " " + e.getMessage());
327 							hadError = true;
328 							break;
329 						}
330 					case Consts.SERVICE_ATTRIBUTE_BYTES_SERVER_INFO:
331 						Logger.debug("Server info:" + attrDataElement.getValue());
332 						try {
333 							Assert.assertEquals("BTAddress", servicesOnDeviceAddress.toUpperCase(),
334 									getAddressFromBTSystemInfo(attrDataElement.getValue().toString()));
335 						} catch (AssertionFailedError e) {
336 							Logger.error("Wrong SR on " + servicesOnDeviceName, e);
337 							TestResponderClient.failure.addFailure("Wrong SR on " + servicesOnDeviceName, e);
338 							return false;
339 						}
340 						break;
341 					default:
342 						if (!Configuration.testIgnoreNotWorkingServiceAttributes.booleanValue()) {
343 							Logger.debug("attribute " + id + " "
344 									+ BluetoothTypesInfo.toStringDataElementType(attrDataElement.getDataType()));
345 						}
346 					}
347 
348 				} catch (AssertionFailedError e) {
349 					Logger.warn("attr " + id + " " + e.getMessage());
350 					// countFailure++;
351 					hadError = true;
352 				}
353 			}
354 			if ((!Configuration.testIgnoreNotWorkingServiceAttributes.booleanValue()) && (!foundName)) {
355 				Logger.warn("srv name attr. not found");
356 				TestResponderClient.failure.addFailure("srv name attr. not found on " + servicesOnDeviceName);
357 			}
358 			if (!foundInt) {
359 				Logger.warn("srv INT attr. not found");
360 				TestResponderClient.failure.addFailure("srv INT attr. not found on " + servicesOnDeviceName);
361 			}
362 			if ((!Configuration.testIgnoreNotWorkingServiceAttributes.booleanValue()) && (!foundLong)) {
363 				Logger.warn("srv long attr. not found");
364 				TestResponderClient.failure.addFailure("srv long attr. not found on " + servicesOnDeviceName);
365 			}
366 			if ((!Configuration.testIgnoreNotWorkingServiceAttributes.booleanValue()) && (!foundStr)) {
367 				Logger.warn("srv STR attr. not found");
368 				TestResponderClient.failure.addFailure("srv STR attr. not found on " + servicesOnDeviceName);
369 			}
370 			if (!foundUrl) {
371 				Logger.warn("srv URL attr. not found");
372 				TestResponderClient.failure.addFailure("srv URL attr. not found on " + servicesOnDeviceName);
373 			}
374 			if (!foundBytes) {
375 				Logger.warn("srv byte[] attr. not found");
376 				TestResponderClient.failure.addFailure("srv byte[] attr. not found on " + servicesOnDeviceName);
377 			}
378 			// if (variableData == 0) {
379 			// Logger.warn("srv var data attr. not found");
380 			// TestResponderClient.failure.addFailure("srv var data attr. not
381 			// found on " + servicesOnDeviceName);
382 			// }
383 			if (foundName && foundUrl && foundInt && foundStr && foundLong && foundBytes && !hadError) {
384 				Logger.info("all service Attr OK");
385 				TestResponderClient.countSuccess++;
386 			} else if ((Configuration.testIgnoreNotWorkingServiceAttributes.booleanValue()) && foundUrl && foundInt
387 					&& foundBytes && !hadError) {
388 				Logger.info("service Attr found");
389 				TestResponderClient.countSuccess++;
390 			}
391 			if (foundIntOK && foundUrlOK && foundBytesOK) {
392 				Logger.info("Common Service Attr OK");
393 			}
394 		} catch (Throwable e) {
395 			Logger.error("attrs", e);
396 		}
397 
398 		if (isBlueCoveTestService) {
399 			RemoteDeviceInfo.deviceServiceFound(servRecord.getHostDevice(), variableData);
400 		}
401 
402 		return isBlueCoveTestService;
403 	}
404 
405 	private static void buildAllTestServiceAttributes() {
406 		try {
407 
408 			final boolean testIntTypes = true;
409 			final boolean testSimpleSequence = true;
410 
411 			final boolean extraTestNULL = false;
412 			final boolean extraTestInt = false;
413 			final boolean extraTestInt16 = false;
414 			final boolean extraTestUUIDTypes = false;
415 			final boolean extraTestComplextSequence = false;
416 			final boolean extraTestLargeSequence = false;
417 
418 			if (extraTestNULL) {
419 				allTestServiceAttributes.addElement(new DataElement(DataElement.NULL));
420 			}
421 
422 			if (testIntTypes) {
423 				// Just some arbitrary number the same on client and server.
424 				allTestServiceAttributes.addElement(new DataElement(DataElement.U_INT_1, 0xBC));
425 				allTestServiceAttributes.addElement(new DataElement(DataElement.U_INT_2, 0xABCD));
426 				allTestServiceAttributes.addElement(new DataElement(DataElement.U_INT_4, 0xABCDEF40l));
427 				allTestServiceAttributes.addElement(new DataElement(DataElement.INT_1, -0x1E));
428 				allTestServiceAttributes.addElement(new DataElement(DataElement.INT_2, -0x7EFD));
429 				allTestServiceAttributes.addElement(new DataElement(DataElement.INT_4, -0x2BC7EF35l));
430 				allTestServiceAttributes.addElement(new DataElement(DataElement.INT_8, -0x7F893012AB39FB72l));
431 			}
432 
433 			if (extraTestInt16) {
434 				allTestServiceAttributes.addElement(new DataElement(DataElement.U_INT_8, new byte[] { 1, -2, 3, 4, -5,
435 						6, 7, -8 }));
436 				allTestServiceAttributes.addElement(new DataElement(DataElement.INT_16, new byte[] { 11, -22, 33, 44,
437 						-5, 6, 77, 88, 9, -10, 11, 12, -13, 14, 15, 16 }));
438 				allTestServiceAttributes.addElement(new DataElement(DataElement.U_INT_16, new byte[] { 21, -32, 43, 54,
439 						-65, 76, 87, 98, 11, -110, 111, 112, -113, 114, 115, 16 }));
440 			}
441 
442 			// There are limit on number of attributes we can test on WIDCOMM
443 			if (extraTestInt) {
444 				allTestServiceAttributes.addElement(new DataElement(DataElement.U_INT_1, 0));
445 
446 				allTestServiceAttributes.addElement(new DataElement(DataElement.U_INT_2, 0));
447 				allTestServiceAttributes.addElement(new DataElement(DataElement.U_INT_4, 0));
448 
449 				allTestServiceAttributes.addElement(new DataElement(DataElement.INT_1, 0));
450 				allTestServiceAttributes.addElement(new DataElement(DataElement.INT_1, 0x4C));
451 
452 				allTestServiceAttributes.addElement(new DataElement(DataElement.INT_2, 0));
453 				allTestServiceAttributes.addElement(new DataElement(DataElement.INT_2, 0x5BCD));
454 
455 				allTestServiceAttributes.addElement(new DataElement(DataElement.INT_4, 0));
456 				allTestServiceAttributes.addElement(new DataElement(DataElement.INT_4, 0x1BCDEF35l));
457 
458 				allTestServiceAttributes.addElement(new DataElement(DataElement.INT_8, 0));
459 				allTestServiceAttributes.addElement(new DataElement(DataElement.INT_8, 0x3eC6EF355892EA8Cl));
460 
461 			}
462 
463 			allTestServiceAttributes.addElement(new DataElement(DataElement.UUID, new UUID(
464 					"E10C0FE1121111A11111161911110003", false)));
465 
466 			if (extraTestUUIDTypes) {
467 				allTestServiceAttributes.addElement(new DataElement(DataElement.UUID, new UUID(
468 						"0000110500001000800000805f9b34fb", false)));
469 				allTestServiceAttributes.addElement(new DataElement(DataElement.UUID, new UUID(0x1105)));
470 				allTestServiceAttributes.addElement(new DataElement(DataElement.UUID, new UUID(0x21301107)));
471 				allTestServiceAttributes.addElement(new DataElement(DataElement.UUID, new UUID(
472 						"2130110800001000800000805f9b34fb", false)));
473 			}
474 
475 			if (testSimpleSequence) {
476 				allTestServiceAttributes.addElement(new DataElement(DataElement.STRING, "BlueCove-2007"));
477 				allTestServiceAttributes
478 						.addElement(new DataElement(DataElement.STRING, CommunicationData.stringUTFData));
479 				DataElement seq1 = new DataElement(DataElement.DATSEQ);
480 				seq1.addElement(new DataElement(DataElement.STRING, "BlueCove-seq1"));
481 				seq1.addElement(new DataElement(DataElement.U_INT_1, 0x12));
482 				allTestServiceAttributes.addElement(seq1);
483 				allTestServiceAttributes.addElement(new DataElement(true));
484 			}
485 
486 			if (extraTestComplextSequence) {
487 				DataElement seq2 = new DataElement(DataElement.DATSEQ);
488 				DataElement seq21 = new DataElement(DataElement.DATSEQ);
489 				seq21.addElement(new DataElement(DataElement.STRING, "BlueCove-seq2.1"));
490 				seq21.addElement(new DataElement(DataElement.U_INT_1, 0x22));
491 				seq2.addElement(seq21);
492 				DataElement seq22 = new DataElement(DataElement.DATSEQ);
493 				seq22.addElement(new DataElement(DataElement.STRING, "BlueCove-seq2.2"));
494 				seq22.addElement(new DataElement(DataElement.U_INT_2, 0x2));
495 				seq22.addElement(new DataElement(DataElement.U_INT_2, 0x3));
496 				// This do not work on WIDCOMM
497 				// DataElement seq23 = new DataElement(DataElement.DATSEQ);
498 				// seq23.addElement(new DataElement(DataElement.STRING,
499 				// "BlueCove-seq2.3"));
500 				// seq22.addElement(seq23);
501 				seq2.addElement(seq22);
502 				// This do not work on WIDCOMM
503 				// seq2.addElement(new DataElement(DataElement.U_INT_1, 0x44));
504 				allTestServiceAttributes.addElement(seq2);
505 			}
506 
507 			if (extraTestLargeSequence) {
508 				DataElement seqLong = new DataElement(DataElement.DATSEQ);
509 				for (int i = 0; i < 100; i++) {
510 					seqLong.addElement(new DataElement(DataElement.STRING, "BlueCove-long-seq " + i));
511 				}
512 				allTestServiceAttributes.addElement(seqLong);
513 			}
514 
515 		} catch (Throwable e) {
516 			Logger.error("attrs create", e);
517 		}
518 	}
519 
520 	public static void addAllTestServiceAttributes(ServiceRecord servRecord) {
521 
522 		servRecord.setAttributeValue(Consts.TEST_SERVICE_ATTRIBUTE_INT_ID, new DataElement(
523 				Consts.TEST_SERVICE_ATTRIBUTE_INT_TYPE, Consts.TEST_SERVICE_ATTRIBUTE_INT_VALUE_TEST_ALL));
524 
525 		for (int i = 0; i < allTestServiceAttributes.size(); i++) {
526 			DataElement de = (DataElement) allTestServiceAttributes.elementAt(i);
527 			servRecord.setAttributeValue(Consts.SERVICE_ATTRIBUTE_ALL_START + i, de);
528 		}
529 	}
530 
531 	public static int allTestServiceAttributesSize() {
532 		return allTestServiceAttributes.size();
533 	}
534 
535 	public static void compareAllServiceAttributes(ServiceRecord servRecord, String servicesOnDeviceName) {
536 		int[] ids = servRecord.getAttributeIDs();
537 		if (ids == null) {
538 			String errorText = "attributes are NULL";
539 			Logger.error(errorText);
540 			TestResponderClient.failure.addFailure(errorText + " on " + servicesOnDeviceName);
541 			return;
542 		}
543 		if (ids.length == 0) {
544 			String errorText = "not attributes";
545 			Logger.error(errorText);
546 			TestResponderClient.failure.addFailure(errorText + " on " + servicesOnDeviceName);
547 			return;
548 		}
549 		int countError = 0;
550 		int countSuccess = 0;
551 		int countFound = 0;
552 		boolean[] found = new boolean[allTestServiceAttributes.size()];
553 		Vector sorted = new Vector();
554 		for (int i = 0; i < ids.length; i++) {
555 			sorted.addElement(new Integer(ids[i]));
556 		}
557 		CollectionUtils.sort(sorted);
558 		for (Enumeration en = sorted.elements(); en.hasMoreElements();) {
559 			int id = ((Integer) en.nextElement()).intValue();
560 			int index = id - Consts.SERVICE_ATTRIBUTE_ALL_START;
561 			if ((index < 0) || (index > allTestServiceAttributes.size())) {
562 				continue;
563 			}
564 			found[index] = true;
565 			countFound++;
566 			DataElement deGot = servRecord.getAttributeValue(id);
567 			DataElement deExpect = (DataElement) allTestServiceAttributes.elementAt(index);
568 			if (equals(deGot, deExpect)) {
569 				Logger.debug("ServAttr OK " + BluetoothTypesInfo.toString(deGot));
570 				countSuccess += 1;
571 			} else {
572 				countError += 1;
573 				Logger.error("ServAttr " + id + " expected " + BluetoothTypesInfo.toString(deExpect));
574 				Logger.error("ServAttr " + id + " received " + BluetoothTypesInfo.toString(deGot));
575 			}
576 		}
577 
578 		if (countSuccess != allTestServiceAttributes.size()) {
579 			if (countFound != allTestServiceAttributes.size()) {
580 				String errorText = "missing attributes, found " + countFound + " expect "
581 						+ allTestServiceAttributes.size();
582 				Logger.error(errorText);
583 				TestResponderClient.failure.addFailure(errorText + " on " + servicesOnDeviceName);
584 			}
585 
586 			if (countSuccess != 0) {
587 				for (int i = 0; i < allTestServiceAttributes.size(); i++) {
588 					if (found[i]) {
589 						continue;
590 					}
591 					DataElement de = (DataElement) allTestServiceAttributes.elementAt(i);
592 					Logger.error("ServAttr missing " + BluetoothTypesInfo.toString(de));
593 				}
594 			}
595 		} else {
596 			Logger.info("All Service Attr found - OK");
597 			TestResponderClient.countSuccess++;
598 		}
599 	}
600 
601 	private static final String ADDRESS = "address:";
602 
603 	public static String getBTSystemInfo() {
604 		try {
605 			LocalDevice localDevice = LocalDevice.getLocalDevice();
606 			StringBuffer buf = new StringBuffer();
607 			buf.append(ADDRESS).append(localDevice.getBluetoothAddress()).append(";");
608 			buf.append(" name:").append(localDevice.getFriendlyName()).append(";");
609 			return buf.toString();
610 		} catch (BluetoothStateException e) {
611 			return "error";
612 		}
613 	}
614 
615 	public static String getAddressFromBTSystemInfo(String sysInfoAttr) {
616 		if ((sysInfoAttr == null) || (sysInfoAttr.length() < 6)) {
617 			return null;
618 		}
619 		int startIndex = sysInfoAttr.indexOf(ADDRESS);
620 		if (startIndex == -1) {
621 			return null;
622 		}
623 		startIndex += ADDRESS.length();
624 		int endIndex = sysInfoAttr.indexOf(';', startIndex);
625 		if (endIndex == -1) {
626 			return null;
627 		}
628 		return sysInfoAttr.substring(startIndex, endIndex).toUpperCase();
629 	}
630 }