TestActivity.java revision 888485a3f5fe991116c5536bb6d6903d47b63a70
1/* 2 * Copyright (c) 2008-2009, Motorola, Inc. 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * - Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * - Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * - Neither the name of the Motorola, Inc. nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33package com.android.bluetooth.opp; 34 35import com.android.bluetooth.R; 36 37import android.app.Activity; 38import android.content.ContentValues; 39import android.content.Context; 40import android.content.Intent; 41import android.database.Cursor; 42import android.net.Uri; 43import android.os.Bundle; 44import android.os.Handler; 45import android.os.Message; 46import android.util.Log; 47import android.widget.Button; 48import android.widget.EditText; 49import android.view.View; 50import android.view.View.OnClickListener; 51 52import java.io.DataInputStream; 53import java.io.DataOutputStream; 54import java.io.File; 55import java.io.FileOutputStream; 56import java.io.IOException; 57import java.io.InputStream; 58import java.io.OutputStream; 59import java.net.ServerSocket; 60import java.net.Socket; 61import java.net.SocketException; 62 63import javax.obex.Authenticator; 64import javax.obex.HeaderSet; 65import javax.obex.ObexTransport; 66import javax.obex.Operation; 67import javax.obex.ResponseCodes; 68import javax.obex.ServerRequestHandler; 69import javax.obex.ServerSession; 70 71public class TestActivity extends Activity { 72 73 public String currentInsert; 74 75 public int mCurrentByte = 0; 76 77 EditText mUpdateView; 78 79 EditText mAckView; 80 81 EditText mDeleteView; 82 83 EditText mInsertView; 84 85 EditText mAddressView; 86 87 EditText mMediaView; 88 89 TestTcpServer server; 90 91 /** Called when the activity is first created. */ 92 @Override 93 public void onCreate(Bundle savedInstanceState) { 94 super.onCreate(savedInstanceState); 95 96 Intent intent = getIntent(); 97 98 String action = intent.getAction(); 99 100 Context c = getBaseContext(); 101 102 if (Intent.ACTION_SEND.equals(action)) { 103 /* 104 * Other application is trying to share a file via Bluetooth, 105 * probably Pictures, or vCard. The Intent should contain an 106 * EXTRA_STREAM with the data to attach. 107 */ 108 109 String type = intent.getType(); 110 Uri stream = (Uri)intent.getParcelableExtra(Intent.EXTRA_STREAM); 111 112 if (stream != null && type != null) { 113 /* 114 * if (MimeUtility.mimeTypeMatches(type, 115 * Email.ACCEPTABLE_ATTACHMENT_SEND_TYPES)) { 116 * addAttachment(stream); 117 */ 118 Log.v(Constants.TAG, " Get share intent with Uri " + stream + " mimetype is " 119 + type); 120 // Log.v(Constants.TAG, " trying Uri function " + 121 // stream.getAuthority() + " " + Uri.parse(stream)); 122 Cursor cursor = c.getContentResolver().query(stream, null, null, null, null); 123 cursor.close(); 124 125 } 126 /* start insert a record */ 127 /* 128 * ContentValues values = new ContentValues(); 129 * values.put(BluetoothShare.URI, stream.toString()); 130 * values.put(BluetoothShare.DESTINATION, "FF:FF:FF:00:00:00"); 131 * values.put(BluetoothShare.DIRECTION, 132 * BluetoothShare.DIRECTION_OUTBOUND); final Uri contentUri = 133 * getContentResolver().insert(BluetoothShare.CONTENT_URI, values); 134 * Log.v(Constants.TAG, "insert contentUri: " + contentUri); 135 */ 136 } 137 /* 138 * Context c = getBaseContext(); c.startService(new Intent(c, 139 * BluetoothOppService.class)); 140 */ 141 142 setContentView(R.layout.testactivity_main); 143 144 Button mInsertRecord = (Button)findViewById(R.id.insert_record); 145 Button mDeleteRecord = (Button)findViewById(R.id.delete_record); 146 Button mUpdateRecord = (Button)findViewById(R.id.update_record); 147 148 Button mAckRecord = (Button)findViewById(R.id.ack_record); 149 150 Button mDeleteAllRecord = (Button)findViewById(R.id.deleteAll_record); 151 mUpdateView = (EditText)findViewById(R.id.update_text); 152 mAckView = (EditText)findViewById(R.id.ack_text); 153 mDeleteView = (EditText)findViewById(R.id.delete_text); 154 mInsertView = (EditText)findViewById(R.id.insert_text); 155 156 mAddressView = (EditText)findViewById(R.id.address_text); 157 mMediaView = (EditText)findViewById(R.id.media_text); 158 159 mInsertRecord.setOnClickListener(insertRecordListener); 160 mDeleteRecord.setOnClickListener(deleteRecordListener); 161 mUpdateRecord.setOnClickListener(updateRecordListener); 162 mAckRecord.setOnClickListener(ackRecordListener); 163 mDeleteAllRecord.setOnClickListener(deleteAllRecordListener); 164 165 Button mStartTcpServer = (Button)findViewById(R.id.start_server); 166 mStartTcpServer.setOnClickListener(startTcpServerListener); 167 168 Button mNotifyTcpServer = (Button)findViewById(R.id.notify_server); 169 mNotifyTcpServer.setOnClickListener(notifyTcpServerListener); 170 /* parse insert result Uri */ 171 /* 172 * String id = contentUri.getPathSegments().get(1); Log.v(Constants.TAG, 173 * "insert record id is " + id); Uri contentUri1 = 174 * Uri.parse(BluetoothShare.CONTENT_URI + "/" + id); 175 */ 176 /* update a single column of a record */ 177 /* 178 * ContentValues updateValues = new ContentValues(); 179 * updateValues.put(BluetoothShare.TOTAL_BYTES, 120000); 180 * getContentResolver().update(contentUri1,updateValues,null,null); 181 */ 182 /* query a single column of a record */ 183 /* 184 * Cursor queryC = getContentResolver().query(contentUri1, null, null, 185 * null, null); if (queryC != null) { if (queryC.moveToFirst()) { int 186 * currentByteColumn = 187 * queryC.getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES); int 188 * currentByte = queryC.getInt(currentByteColumn); 189 */ 190 /* update a column of a record */ 191 /* 192 * for(int i =0;i<100;i++){ currentByte ++; 193 * updateValues.put(BluetoothShare.CURRENT_BYTES, currentByte); 194 * getContentResolver().update(contentUri1,updateValues,null,null); } } 195 * } 196 */ 197 /* query whole data base */ 198 /* 199 * Cursor c = managedQuery(contentUri1, new String [] {"_id", 200 * BluetoothShare.URI, BluetoothShare.STATUS, 201 * BluetoothShare.TOTAL_BYTES, BluetoothShare.CURRENT_BYTES, 202 * BluetoothShare._DATA, BluetoothShare.DIRECTION, 203 * BluetoothShare.MIMETYPE, BluetoothShare.DESTINATION, 204 * BluetoothShare.VISIBILITY, BluetoothShare.USER_CONFIRMATION, 205 * BluetoothShare.TIMESTAMP}, null, null, null); Log.v(Constants.TAG, 206 * "query " + contentUri1 +" get " + c.getCount()+" records"); 207 */ 208 /* delete a record */ 209 /* 210 * Uri contentUri2 = Uri.parse(BluetoothShare.CONTENT_URI + "/" + 1); 211 * getContentResolver().delete(contentUri2, null, null); 212 */ 213 214 } 215 216 public OnClickListener insertRecordListener = new OnClickListener() { 217 public void onClick(View view) { 218 219 String address = null; 220 if (mAddressView.getText().length() != 0) { 221 address = mAddressView.getText().toString(); 222 Log.v(Constants.TAG, "Send to address " + address); 223 } 224 if (address == null) { 225 address = "00:17:83:58:5D:CC"; 226 } 227 228 Integer media = null; 229 if (mMediaView.getText().length() != 0) { 230 media = Integer.parseInt(mMediaView.getText().toString().trim()); 231 Log.v(Constants.TAG, "Send media no. " + media); 232 } 233 if (media == null) { 234 media = 1; 235 } 236 ContentValues values = new ContentValues(); 237 values.put(BluetoothShare.URI, "content://media/external/images/media/" + media); 238 // values.put(BluetoothShare.DESTINATION, "FF:FF:FF:00:00:00"); 239 // baibai Q9 test 240 // values.put(BluetoothShare.DESTINATION, "12:34:56:78:9A:BC"); 241 // java's nokia 242 // values.put(BluetoothShare.DESTINATION, "00:1B:33:F0:58:FB"); 243 // Assis phone 244 // values.put(BluetoothShare.DESTINATION, "00:17:E5:5D:74:F3"); 245 // Jackson E6 246 // values.put(BluetoothShare.DESTINATION, "00:1A:1B:7F:1E:F0"); 247 // Baibai V950 248 // values.put(BluetoothShare.DESTINATION, "00:17:83:58:5D:CC"); 249 // Baibai NSC1173 250 // values.put(BluetoothShare.DESTINATION, "00:16:41:49:5B:F3"); 251 252 values.put(BluetoothShare.DESTINATION, address); 253 254 values.put(BluetoothShare.DIRECTION, BluetoothShare.DIRECTION_OUTBOUND); 255 256 Long ts = System.currentTimeMillis(); 257 values.put(BluetoothShare.TIMESTAMP, ts); 258 259 Integer records = null; 260 if (mInsertView.getText().length() != 0) { 261 records = Integer.parseInt(mInsertView.getText().toString().trim()); 262 Log.v(Constants.TAG, "parseInt " + records); 263 } 264 if (records == null) { 265 records = 1; 266 } 267 for (int i = 0; i < records; i++) { 268 Uri contentUri = getContentResolver().insert(BluetoothShare.CONTENT_URI, values); 269 Log.v(Constants.TAG, "insert contentUri: " + contentUri); 270 currentInsert = contentUri.getPathSegments().get(1); 271 Log.v(Constants.TAG, "currentInsert = " + currentInsert); 272 } 273 274 } 275 }; 276 277 public OnClickListener deleteRecordListener = new OnClickListener() { 278 public void onClick(View view) { 279 Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" 280 + mDeleteView.getText().toString()); 281 getContentResolver().delete(contentUri, null, null); 282 } 283 }; 284 285 public OnClickListener updateRecordListener = new OnClickListener() { 286 public void onClick(View view) { 287 Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" 288 + mUpdateView.getText().toString()); 289 ContentValues updateValues = new ContentValues(); 290 // mCurrentByte ++; 291 // updateValues.put(BluetoothShare.TOTAL_BYTES, "120000"); 292 // updateValues.put(BluetoothShare.CURRENT_BYTES, mCurrentByte); 293 // updateValues.put(BluetoothShare.VISIBILITY, 294 // BluetoothShare.VISIBILITY_HIDDEN); 295 updateValues.put(BluetoothShare.USER_CONFIRMATION, 296 BluetoothShare.USER_CONFIRMATION_CONFIRMED); 297 getContentResolver().update(contentUri, updateValues, null, null); 298 } 299 }; 300 301 public OnClickListener ackRecordListener = new OnClickListener() { 302 public void onClick(View view) { 303 Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" 304 + mAckView.getText().toString()); 305 ContentValues updateValues = new ContentValues(); 306 // mCurrentByte ++; 307 // updateValues.put(BluetoothShare.TOTAL_BYTES, "120000"); 308 // updateValues.put(BluetoothShare.CURRENT_BYTES, mCurrentByte); 309 updateValues.put(BluetoothShare.VISIBILITY, BluetoothShare.VISIBILITY_HIDDEN); 310 // updateValues.put(BluetoothShare.USER_CONFIRMATION, 311 // BluetoothShare.USER_CONFIRMATION_CONFIRMED); 312 getContentResolver().update(contentUri, updateValues, null, null); 313 } 314 }; 315 316 public OnClickListener deleteAllRecordListener = new OnClickListener() { 317 public void onClick(View view) { 318 Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + ""); 319 getContentResolver().delete(contentUri, null, null); 320 } 321 }; 322 323 public OnClickListener startTcpServerListener = new OnClickListener() { 324 public void onClick(View view) { 325 server = new TestTcpServer(); 326 Thread server_thread = new Thread(server); 327 server_thread.start(); 328 329 } 330 }; 331 332 public OnClickListener notifyTcpServerListener = new OnClickListener() { 333 public void onClick(View view) { 334 final Thread notifyThread = new Thread() { 335 public void run() { 336 synchronized (server) { 337 server.a = true; 338 server.notify(); 339 } 340 } 341 342 }; 343 notifyThread.start(); 344 } 345 346 }; 347} 348 349/** 350 * This class listens on OPUSH channel for incoming connection 351 */ 352class TestTcpListener { 353 354 private static final String TAG = "BtOppRfcommListener"; 355 356 private static final boolean D = Constants.DEBUG; 357 358 private static final boolean V = Constants.VERBOSE; 359 360 private volatile boolean mInterrupted; 361 362 private Thread mSocketAcceptThread; 363 364 private Handler mCallback; 365 366 private static final int ACCEPT_WAIT_TIMEOUT = 5000; 367 368 public static final int DEFAULT_OPP_CHANNEL = 12; 369 370 public static final int MSG_INCOMING_BTOPP_CONNECTION = 100; 371 372 private int mBtOppRfcommChannel = -1; 373 374 public TestTcpListener() { 375 this(DEFAULT_OPP_CHANNEL); 376 } 377 378 public TestTcpListener(int channel) { 379 mBtOppRfcommChannel = channel; 380 } 381 382 public synchronized boolean start(Handler callback) { 383 if (mSocketAcceptThread == null) { 384 mCallback = callback; 385 mSocketAcceptThread = new Thread(TAG) { 386 ServerSocket mServerSocket; 387 388 public void run() { 389 if (D) Log.d(TAG, "RfcommSocket listen thread starting"); 390 try { 391 if (V) 392 Log.v(TAG, "Create server RfcommSocket on channel" 393 + mBtOppRfcommChannel); 394 mServerSocket = new ServerSocket(6500, 1); 395 } catch (IOException e) { 396 Log.e(TAG, "Error listing on channel" + mBtOppRfcommChannel); 397 mInterrupted = true; 398 } 399 while (!mInterrupted) { 400 try { 401 mServerSocket.setSoTimeout(ACCEPT_WAIT_TIMEOUT); 402 Socket clientSocket = mServerSocket.accept(); 403 if (clientSocket == null) { 404 if (V) Log.v(TAG, "incomming connection time out"); 405 } else { 406 if (D) Log.d(TAG, "RfcommSocket connected!"); 407 Log.d(TAG, "remote addr is " 408 + clientSocket.getRemoteSocketAddress()); 409 TestTcpTransport transport = new TestTcpTransport(clientSocket); 410 Message msg = Message.obtain(); 411 msg.setTarget(mCallback); 412 msg.what = MSG_INCOMING_BTOPP_CONNECTION; 413 msg.obj = transport; 414 msg.sendToTarget(); 415 } 416 } catch (SocketException e) { 417 Log.e(TAG, "Error accept connection " + e); 418 } catch (IOException e) { 419 Log.e(TAG, "Error accept connection " + e); 420 } 421 422 if (mInterrupted) { 423 Log.e(TAG, "socketAcceptThread thread was interrupted (2), exiting"); 424 } 425 } 426 if (D) Log.d(TAG, "RfcommSocket listen thread finished"); 427 } 428 }; 429 mInterrupted = false; 430 mSocketAcceptThread.start(); 431 432 } 433 return true; 434 435 } 436 437 public synchronized void stop() { 438 if (mSocketAcceptThread != null) { 439 if (D) Log.d(TAG, "stopping Connect Thread"); 440 mInterrupted = true; 441 try { 442 mSocketAcceptThread.interrupt(); 443 if (V) Log.v(TAG, "waiting for thread to terminate"); 444 mSocketAcceptThread.join(); 445 mSocketAcceptThread = null; 446 mCallback = null; 447 } catch (InterruptedException e) { 448 if (V) Log.v(TAG, "Interrupted waiting for Accept Thread to join"); 449 } 450 } 451 } 452 453} 454 455class TestTcpServer extends ServerRequestHandler implements Runnable { 456 private static final String TAG = "ServerRequestHandler"; 457 458 private static final boolean D = Constants.DEBUG; 459 460 private static final boolean V = Constants.VERBOSE; 461 462 static final int port = 6500; 463 464 public boolean a = false; 465 466 // TextView serverStatus = null; 467 public void run() { 468 try { 469 updateStatus("[server:] listen on port " + port); 470 TestTcpSessionNotifier rsn = new TestTcpSessionNotifier(port); 471 472 updateStatus("[server:] Now waiting for a client to connect"); 473 rsn.acceptAndOpen(this); 474 updateStatus("[server:] A client is now connected"); 475 } catch (Exception ex) { 476 updateStatus("[server:] Caught the error: " + ex); 477 } 478 } 479 480 public TestTcpServer() { 481 updateStatus("enter construtor of TcpServer"); 482 } 483 484 public int onConnect(HeaderSet request, HeaderSet reply) { 485 486 updateStatus("[server:] The client has created an OBEX session"); 487 /* sleep for 2000 ms to wait for the batch contains all ShareInfos */ 488 synchronized (this) { 489 try { 490 while (!a) { 491 wait(500); 492 } 493 } catch (InterruptedException e) { 494 if (V) Log.v(TAG, "Interrupted waiting for markBatchFailed"); 495 } 496 } 497 updateStatus("[server:] we accpet the seesion"); 498 return ResponseCodes.OBEX_HTTP_OK; 499 } 500 501 public int onPut(Operation op) { 502 FileOutputStream fos = null; 503 try { 504 java.io.InputStream is = op.openInputStream(); 505 506 updateStatus("Got data bytes " + is.available() + " name " 507 + op.getReceivedHeader().getHeader(HeaderSet.NAME) + " type " + op.getType()); 508 509 File f = new File((String)op.getReceivedHeader().getHeader(HeaderSet.NAME)); 510 fos = new FileOutputStream(f); 511 byte b[] = new byte[1000]; 512 int len; 513 514 while (is.available() > 0 && (len = is.read(b)) > 0) { 515 fos.write(b, 0, len); 516 } 517 518 fos.close(); 519 is.close(); 520 updateStatus("[server:] Wrote data to " + f.getAbsolutePath()); 521 } catch (Exception e) { 522 if (fos != null) { 523 try { 524 fos.close(); 525 } catch (IOException e1) { 526 e1.printStackTrace(); 527 } 528 } 529 e.printStackTrace(); 530 } 531 return ResponseCodes.OBEX_HTTP_OK; 532 } 533 534 public void onDisconnect(HeaderSet req, HeaderSet resp) { 535 updateStatus("[server:] The client has disconnected the OBEX session"); 536 } 537 538 public void updateStatus(String message) { 539 Log.v(TAG, "\n" + message); 540 } 541 542 public void onAuthenticationFailure(byte[] userName) { 543 } 544 545 public int onSetPath(HeaderSet request, HeaderSet reply, boolean backup, boolean create) { 546 547 return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED; 548 } 549 550 public int onDelete(HeaderSet request, HeaderSet reply) { 551 return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED; 552 } 553 554 public int onGet(Operation op) { 555 return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED; 556 } 557 558} 559 560class TestTcpSessionNotifier { 561 /* implements SessionNotifier */ 562 563 ServerSocket server = null; 564 565 Socket conn = null; 566 567 private static final String TAG = "TestTcpSessionNotifier"; 568 569 public TestTcpSessionNotifier(int port) throws IOException { 570 server = new ServerSocket(port); 571 } 572 573 public ServerSession acceptAndOpen(ServerRequestHandler handler, Authenticator auth) 574 throws IOException { 575 try { 576 conn = server.accept(); 577 578 } catch (Exception ex) { 579 Log.v(TAG, "ex"); 580 } 581 582 TestTcpTransport tt = new TestTcpTransport(conn); 583 584 return new ServerSession((ObexTransport)tt, handler, auth); 585 586 } 587 588 public ServerSession acceptAndOpen(ServerRequestHandler handler) throws IOException { 589 590 return acceptAndOpen(handler, null); 591 592 } 593 594} 595 596class TestTcpTransport implements ObexTransport { 597 598 Socket s = null; 599 600 public TestTcpTransport(Socket s) { 601 super(); 602 this.s = s; 603 } 604 605 public void close() throws IOException { 606 s.close(); 607 } 608 609 public DataInputStream openDataInputStream() throws IOException { 610 return new DataInputStream(openInputStream()); 611 } 612 613 public DataOutputStream openDataOutputStream() throws IOException { 614 return new DataOutputStream(openOutputStream()); 615 } 616 617 public InputStream openInputStream() throws IOException { 618 return s.getInputStream(); 619 } 620 621 public OutputStream openOutputStream() throws IOException { 622 return s.getOutputStream(); 623 } 624 625 public void connect() throws IOException { 626 // TODO Auto-generated method stub 627 628 } 629 630 public void create() throws IOException { 631 // TODO Auto-generated method stub 632 633 } 634 635 public void disconnect() throws IOException { 636 // TODO Auto-generated method stub 637 638 } 639 640 public void listen() throws IOException { 641 // TODO Auto-generated method stub 642 643 } 644 645 public boolean isConnected() throws IOException { 646 return s.isConnected(); 647 } 648 649} 650