blob: 89bf075790f5aa837e4a4929ab3dd59ac94f8639 [file] [log] [blame]
/*
* Copyright (c) 2008-2009, Motorola, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the Motorola, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package com.android.bluetooth.opp;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import com.android.bluetooth.R;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import javax.obex.Authenticator;
import javax.obex.HeaderSet;
import javax.obex.ObexTransport;
import javax.obex.Operation;
import javax.obex.ResponseCodes;
import javax.obex.ServerRequestHandler;
import javax.obex.ServerSession;
public class TestActivity extends Activity {
public String currentInsert;
public int mCurrentByte = 0;
EditText mUpdateView;
EditText mAckView;
EditText mDeleteView;
EditText mInsertView;
EditText mAddressView;
EditText mMediaView;
TestTcpServer mServer;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
String action = intent.getAction();
Context c = getBaseContext();
if (Intent.ACTION_SEND.equals(action)) {
/*
* Other application is trying to share a file via Bluetooth,
* probably Pictures, or vCard. The Intent should contain an
* EXTRA_STREAM with the data to attach.
*/
String type = intent.getType();
Uri stream = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (stream != null && type != null) {
/*
* if (MimeUtility.mimeTypeMatches(type,
* Email.ACCEPTABLE_ATTACHMENT_SEND_TYPES)) {
* addAttachment(stream);
*/
Log.v(Constants.TAG,
" Get share intent with Uri " + stream + " mimetype is " + type);
// Log.v(Constants.TAG, " trying Uri function " +
// stream.getAuthority() + " " + Uri.parse(stream));
Cursor cursor = c.getContentResolver().query(stream, null, null, null, null);
cursor.close();
}
/* start insert a record */
/*
* ContentValues values = new ContentValues();
* values.put(BluetoothShare.URI, stream.toString());
* values.put(BluetoothShare.DESTINATION, "FF:FF:FF:00:00:00");
* values.put(BluetoothShare.DIRECTION,
* BluetoothShare.DIRECTION_OUTBOUND); final Uri contentUri =
* getContentResolver().insert(BluetoothShare.CONTENT_URI, values);
* Log.v(Constants.TAG, "insert contentUri: " + contentUri);
*/
}
/*
* Context c = getBaseContext(); c.startService(new Intent(c,
* BluetoothOppService.class));
*/
setContentView(R.layout.testactivity_main);
Button mInsertRecord = (Button) findViewById(R.id.insert_record);
Button mDeleteRecord = (Button) findViewById(R.id.delete_record);
Button mUpdateRecord = (Button) findViewById(R.id.update_record);
Button mAckRecord = (Button) findViewById(R.id.ack_record);
Button mDeleteAllRecord = (Button) findViewById(R.id.deleteAll_record);
mUpdateView = (EditText) findViewById(R.id.update_text);
mAckView = (EditText) findViewById(R.id.ack_text);
mDeleteView = (EditText) findViewById(R.id.delete_text);
mInsertView = (EditText) findViewById(R.id.insert_text);
mAddressView = (EditText) findViewById(R.id.address_text);
mMediaView = (EditText) findViewById(R.id.media_text);
mInsertRecord.setOnClickListener(insertRecordListener);
mDeleteRecord.setOnClickListener(deleteRecordListener);
mUpdateRecord.setOnClickListener(updateRecordListener);
mAckRecord.setOnClickListener(ackRecordListener);
mDeleteAllRecord.setOnClickListener(deleteAllRecordListener);
Button mStartTcpServer = (Button) findViewById(R.id.start_server);
mStartTcpServer.setOnClickListener(startTcpServerListener);
Button mNotifyTcpServer = (Button) findViewById(R.id.notify_server);
mNotifyTcpServer.setOnClickListener(notifyTcpServerListener);
/* parse insert result Uri */
/*
* String id = contentUri.getPathSegments().get(1); Log.v(Constants.TAG,
* "insert record id is " + id); Uri contentUri1 =
* Uri.parse(BluetoothShare.CONTENT_URI + "/" + id);
*/
/* update a single column of a record */
/*
* ContentValues updateValues = new ContentValues();
* updateValues.put(BluetoothShare.TOTAL_BYTES, 120000);
* getContentResolver().update(contentUri1,updateValues,null,null);
*/
/* query a single column of a record */
/*
* Cursor queryC = getContentResolver().query(contentUri1, null, null,
* null, null); if (queryC != null) { if (queryC.moveToFirst()) { int
* currentByteColumn =
* queryC.getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES); int
* currentByte = queryC.getInt(currentByteColumn);
*/
/* update a column of a record */
/*
* for(int i =0;i<100;i++){ currentByte ++;
* updateValues.put(BluetoothShare.CURRENT_BYTES, currentByte);
* getContentResolver().update(contentUri1,updateValues,null,null); } }
* }
*/
/* query whole data base */
/*
* Cursor c = managedQuery(contentUri1, new String [] {"_id",
* BluetoothShare.URI, BluetoothShare.STATUS,
* BluetoothShare.TOTAL_BYTES, BluetoothShare.CURRENT_BYTES,
* BluetoothShare._DATA, BluetoothShare.DIRECTION,
* BluetoothShare.MIMETYPE, BluetoothShare.DESTINATION,
* BluetoothShare.VISIBILITY, BluetoothShare.USER_CONFIRMATION,
* BluetoothShare.TIMESTAMP}, null, null, null); Log.v(Constants.TAG,
* "query " + contentUri1 +" get " + c.getCount()+" records");
*/
/* delete a record */
/*
* Uri contentUri2 = Uri.parse(BluetoothShare.CONTENT_URI + "/" + 1);
* getContentResolver().delete(contentUri2, null, null);
*/
}
public OnClickListener insertRecordListener = new OnClickListener() {
@Override
public void onClick(View view) {
String address = null;
if (mAddressView.getText().length() != 0) {
address = mAddressView.getText().toString();
Log.v(Constants.TAG, "Send to address " + address);
}
if (address == null) {
address = "00:17:83:58:5D:CC";
}
Integer media = null;
if (mMediaView.getText().length() != 0) {
media = Integer.parseInt(mMediaView.getText().toString().trim());
Log.v(Constants.TAG, "Send media no. " + media);
}
if (media == null) {
media = 1;
}
ContentValues values = new ContentValues();
values.put(BluetoothShare.URI, "content://media/external/images/media/" + media);
// values.put(BluetoothShare.DESTINATION, "FF:FF:FF:00:00:00");
// baibai Q9 test
// values.put(BluetoothShare.DESTINATION, "12:34:56:78:9A:BC");
// java's nokia
// values.put(BluetoothShare.DESTINATION, "00:1B:33:F0:58:FB");
// Assis phone
// values.put(BluetoothShare.DESTINATION, "00:17:E5:5D:74:F3");
// Jackson E6
// values.put(BluetoothShare.DESTINATION, "00:1A:1B:7F:1E:F0");
// Baibai V950
// values.put(BluetoothShare.DESTINATION, "00:17:83:58:5D:CC");
// Baibai NSC1173
// values.put(BluetoothShare.DESTINATION, "00:16:41:49:5B:F3");
values.put(BluetoothShare.DESTINATION, address);
values.put(BluetoothShare.DIRECTION, BluetoothShare.DIRECTION_OUTBOUND);
Long ts = System.currentTimeMillis();
values.put(BluetoothShare.TIMESTAMP, ts);
Integer records = null;
if (mInsertView.getText().length() != 0) {
records = Integer.parseInt(mInsertView.getText().toString().trim());
Log.v(Constants.TAG, "parseInt " + records);
}
if (records == null) {
records = 1;
}
for (int i = 0; i < records; i++) {
Uri contentUri = getContentResolver().insert(BluetoothShare.CONTENT_URI, values);
Log.v(Constants.TAG, "insert contentUri: " + contentUri);
currentInsert = contentUri.getPathSegments().get(1);
Log.v(Constants.TAG, "currentInsert = " + currentInsert);
}
}
};
public OnClickListener deleteRecordListener = new OnClickListener() {
@Override
public void onClick(View view) {
Uri contentUri =
Uri.parse(BluetoothShare.CONTENT_URI + "/" + mDeleteView.getText().toString());
getContentResolver().delete(contentUri, null, null);
}
};
public OnClickListener updateRecordListener = new OnClickListener() {
@Override
public void onClick(View view) {
Uri contentUri =
Uri.parse(BluetoothShare.CONTENT_URI + "/" + mUpdateView.getText().toString());
ContentValues updateValues = new ContentValues();
// mCurrentByte ++;
// updateValues.put(BluetoothShare.TOTAL_BYTES, "120000");
// updateValues.put(BluetoothShare.CURRENT_BYTES, mCurrentByte);
// updateValues.put(BluetoothShare.VISIBILITY,
// BluetoothShare.VISIBILITY_HIDDEN);
updateValues.put(BluetoothShare.USER_CONFIRMATION,
BluetoothShare.USER_CONFIRMATION_CONFIRMED);
getContentResolver().update(contentUri, updateValues, null, null);
}
};
public OnClickListener ackRecordListener = new OnClickListener() {
@Override
public void onClick(View view) {
Uri contentUri =
Uri.parse(BluetoothShare.CONTENT_URI + "/" + mAckView.getText().toString());
ContentValues updateValues = new ContentValues();
// mCurrentByte ++;
// updateValues.put(BluetoothShare.TOTAL_BYTES, "120000");
// updateValues.put(BluetoothShare.CURRENT_BYTES, mCurrentByte);
updateValues.put(BluetoothShare.VISIBILITY, BluetoothShare.VISIBILITY_HIDDEN);
// updateValues.put(BluetoothShare.USER_CONFIRMATION,
// BluetoothShare.USER_CONFIRMATION_CONFIRMED);
getContentResolver().update(contentUri, updateValues, null, null);
}
};
public OnClickListener deleteAllRecordListener = new OnClickListener() {
@Override
public void onClick(View view) {
Uri contentUri = Uri.parse(String.valueOf(BluetoothShare.CONTENT_URI));
getContentResolver().delete(contentUri, null, null);
}
};
public OnClickListener startTcpServerListener = new OnClickListener() {
@Override
public void onClick(View view) {
mServer = new TestTcpServer();
Thread serverThread = new Thread(mServer);
serverThread.start();
}
};
public OnClickListener notifyTcpServerListener = new OnClickListener() {
@Override
public void onClick(View view) {
final Thread notifyThread = new Thread() {
@Override
public void run() {
synchronized (mServer) {
mServer.a = true;
mServer.notify();
}
}
};
notifyThread.start();
}
};
}
/**
* This class listens on OPUSH channel for incoming connection
*/
class TestTcpListener {
private static final String TAG = "BtOppRfcommListener";
private static final boolean D = Constants.DEBUG;
private static final boolean V = Constants.VERBOSE;
private volatile boolean mInterrupted;
private Thread mSocketAcceptThread;
private Handler mCallback;
private static final int ACCEPT_WAIT_TIMEOUT = 5000;
public static final int DEFAULT_OPP_CHANNEL = 12;
public static final int MSG_INCOMING_BTOPP_CONNECTION = 100;
private int mBtOppRfcommChannel = -1;
TestTcpListener() {
this(DEFAULT_OPP_CHANNEL);
}
TestTcpListener(int channel) {
mBtOppRfcommChannel = channel;
}
public synchronized boolean start(Handler callback) {
if (mSocketAcceptThread == null) {
mCallback = callback;
mSocketAcceptThread = new Thread(TAG) {
ServerSocket mServerSocket;
@Override
public void run() {
if (D) {
Log.d(TAG, "RfcommSocket listen thread starting");
}
try {
if (V) {
Log.v(TAG,
"Create server RfcommSocket on channel" + mBtOppRfcommChannel);
}
mServerSocket = new ServerSocket(6500, 1);
} catch (IOException e) {
Log.e(TAG, "Error listing on channel" + mBtOppRfcommChannel);
mInterrupted = true;
}
while (!mInterrupted) {
try {
mServerSocket.setSoTimeout(ACCEPT_WAIT_TIMEOUT);
Socket clientSocket = mServerSocket.accept();
if (clientSocket == null) {
if (V) {
Log.v(TAG, "incomming connection time out");
}
} else {
if (D) {
Log.d(TAG, "RfcommSocket connected!");
}
Log.d(TAG,
"remote addr is " + clientSocket.getRemoteSocketAddress());
TestTcpTransport transport = new TestTcpTransport(clientSocket);
Message msg = Message.obtain();
msg.setTarget(mCallback);
msg.what = MSG_INCOMING_BTOPP_CONNECTION;
msg.obj = transport;
msg.sendToTarget();
}
} catch (SocketException e) {
Log.e(TAG, "Error accept connection " + e);
} catch (IOException e) {
Log.e(TAG, "Error accept connection " + e);
}
if (mInterrupted) {
Log.e(TAG, "socketAcceptThread thread was interrupted (2), exiting");
}
}
if (D) {
Log.d(TAG, "RfcommSocket listen thread finished");
}
}
};
mInterrupted = false;
mSocketAcceptThread.start();
}
return true;
}
public synchronized void stop() {
if (mSocketAcceptThread != null) {
if (D) {
Log.d(TAG, "stopping Connect Thread");
}
mInterrupted = true;
try {
mSocketAcceptThread.interrupt();
if (V) {
Log.v(TAG, "waiting for thread to terminate");
}
mSocketAcceptThread.join();
mSocketAcceptThread = null;
mCallback = null;
} catch (InterruptedException e) {
if (V) {
Log.v(TAG, "Interrupted waiting for Accept Thread to join");
}
}
}
}
}
class TestTcpServer extends ServerRequestHandler implements Runnable {
private static final String TAG = "ServerRequestHandler";
private static final boolean V = Constants.VERBOSE;
static final int PORT = 6500;
public boolean a = false;
// TextView serverStatus = null;
@Override
public void run() {
try {
updateStatus("[server:] listen on port " + PORT);
TestTcpSessionNotifier rsn = new TestTcpSessionNotifier(PORT);
updateStatus("[server:] Now waiting for a client to connect");
rsn.acceptAndOpen(this);
updateStatus("[server:] A client is now connected");
} catch (Exception ex) {
updateStatus("[server:] Caught the error: " + ex);
}
}
TestTcpServer() {
updateStatus("enter construtor of TcpServer");
}
@Override
public int onConnect(HeaderSet request, HeaderSet reply) {
updateStatus("[server:] The client has created an OBEX session");
/* sleep for 2000 ms to wait for the batch contains all ShareInfos */
synchronized (this) {
try {
while (!a) {
wait(500);
}
} catch (InterruptedException e) {
if (V) {
Log.v(TAG, "Interrupted waiting for markBatchFailed");
}
}
}
updateStatus("[server:] we accpet the seesion");
return ResponseCodes.OBEX_HTTP_OK;
}
@Override
public int onPut(Operation op) {
FileOutputStream fos = null;
try {
java.io.InputStream is = op.openInputStream();
updateStatus("Got data bytes " + is.available() + " name " + op.getReceivedHeader()
.getHeader(HeaderSet.NAME) + " type " + op.getType());
File f = new File((String) op.getReceivedHeader().getHeader(HeaderSet.NAME));
fos = new FileOutputStream(f);
byte[] b = new byte[1000];
int len;
while (is.available() > 0 && (len = is.read(b)) > 0) {
fos.write(b, 0, len);
}
fos.close();
is.close();
updateStatus("[server:] Wrote data to " + f.getAbsolutePath());
} catch (Exception e) {
if (fos != null) {
try {
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
e.printStackTrace();
}
return ResponseCodes.OBEX_HTTP_OK;
}
@Override
public void onDisconnect(HeaderSet req, HeaderSet resp) {
updateStatus("[server:] The client has disconnected the OBEX session");
}
@Override
public void updateStatus(String message) {
Log.v(TAG, "\n" + message);
}
@Override
public void onAuthenticationFailure(byte[] userName) {
}
@Override
public int onSetPath(HeaderSet request, HeaderSet reply, boolean backup, boolean create) {
return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
}
@Override
public int onDelete(HeaderSet request, HeaderSet reply) {
return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
}
@Override
public int onGet(Operation op) {
return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
}
}
class TestTcpSessionNotifier {
/* implements SessionNotifier */
ServerSocket mServer = null;
Socket mConn = null;
private static final String TAG = "TestTcpSessionNotifier";
TestTcpSessionNotifier(int port) throws IOException {
mServer = new ServerSocket(port);
}
public ServerSession acceptAndOpen(ServerRequestHandler handler, Authenticator auth)
throws IOException {
try {
mConn = mServer.accept();
} catch (Exception ex) {
Log.v(TAG, "ex");
}
TestTcpTransport tt = new TestTcpTransport(mConn);
return new ServerSession((ObexTransport) tt, handler, auth);
}
public ServerSession acceptAndOpen(ServerRequestHandler handler) throws IOException {
return acceptAndOpen(handler, null);
}
}
class TestTcpTransport implements ObexTransport {
Socket mSocket = null;
TestTcpTransport(Socket s) {
super();
this.mSocket = s;
}
@Override
public void close() throws IOException {
mSocket.close();
}
@Override
public DataInputStream openDataInputStream() throws IOException {
return new DataInputStream(openInputStream());
}
@Override
public DataOutputStream openDataOutputStream() throws IOException {
return new DataOutputStream(openOutputStream());
}
@Override
public InputStream openInputStream() throws IOException {
return mSocket.getInputStream();
}
@Override
public OutputStream openOutputStream() throws IOException {
return mSocket.getOutputStream();
}
@Override
public void connect() throws IOException {
// TODO Auto-generated method stub
}
@Override
public void create() throws IOException {
// TODO Auto-generated method stub
}
@Override
public void disconnect() throws IOException {
// TODO Auto-generated method stub
}
@Override
public void listen() throws IOException {
// TODO Auto-generated method stub
}
public boolean isConnected() throws IOException {
return mSocket.isConnected();
}
@Override
public int getMaxTransmitPacketSize() {
return -1;
}
@Override
public int getMaxReceivePacketSize() {
return -1;
}
@Override
public boolean isSrmSupported() {
// TODO: It should be possible to use SRM in TCP connections
return false;
}
}