summaryrefslogtreecommitdiffstats
path: root/src/android/bluetooth/client/map/BluetoothMnsService.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/android/bluetooth/client/map/BluetoothMnsService.java')
-rw-r--r--src/android/bluetooth/client/map/BluetoothMnsService.java195
1 files changed, 195 insertions, 0 deletions
diff --git a/src/android/bluetooth/client/map/BluetoothMnsService.java b/src/android/bluetooth/client/map/BluetoothMnsService.java
new file mode 100644
index 0000000..42175e0
--- /dev/null
+++ b/src/android/bluetooth/client/map/BluetoothMnsService.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.client.map;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothServerSocket;
+import android.bluetooth.BluetoothSocket;
+import android.os.Handler;
+import android.os.Message;
+import android.os.ParcelUuid;
+import android.util.Log;
+import android.util.SparseArray;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.lang.ref.WeakReference;
+
+import javax.obex.ServerSession;
+
+class BluetoothMnsService {
+
+ private static final String TAG = "BluetoothMnsService";
+
+ private static final ParcelUuid MAP_MNS =
+ ParcelUuid.fromString("00001133-0000-1000-8000-00805F9B34FB");
+
+ static final int MSG_EVENT = 1;
+
+ /* for BluetoothMasClient */
+ static final int EVENT_REPORT = 1001;
+
+ /* these are shared across instances */
+ static private SparseArray<Handler> mCallbacks = null;
+ static private SocketAcceptThread mAcceptThread = null;
+ static private Handler mSessionHandler = null;
+ static private BluetoothServerSocket mServerSocket = null;
+
+ private static class SessionHandler extends Handler {
+
+ private final WeakReference<BluetoothMnsService> mService;
+
+ SessionHandler(BluetoothMnsService service) {
+ mService = new WeakReference<BluetoothMnsService>(service);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ Log.d(TAG, "Handler: msg: " + msg.what);
+
+ switch (msg.what) {
+ case MSG_EVENT:
+ int instanceId = msg.arg1;
+
+ synchronized (mCallbacks) {
+ Handler cb = mCallbacks.get(instanceId);
+
+ if (cb != null) {
+ BluetoothMapEventReport ev = (BluetoothMapEventReport) msg.obj;
+ cb.obtainMessage(EVENT_REPORT, ev).sendToTarget();
+ } else {
+ Log.w(TAG, "Got event for instance which is not registered: "
+ + instanceId);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ private static class SocketAcceptThread extends Thread {
+
+ private boolean mInterrupted = false;
+
+ @Override
+ public void run() {
+
+ if (mServerSocket != null) {
+ Log.w(TAG, "Socket already created, exiting");
+ return;
+ }
+
+ try {
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ mServerSocket = adapter.listenUsingEncryptedRfcommWithServiceRecord(
+ "MAP Message Notification Service", MAP_MNS.getUuid());
+ } catch (IOException e) {
+ mInterrupted = true;
+ Log.e(TAG, "I/O exception when trying to create server socket", e);
+ }
+
+ while (!mInterrupted) {
+ try {
+ Log.v(TAG, "waiting to accept connection...");
+
+ BluetoothSocket sock = mServerSocket.accept();
+
+ Log.v(TAG, "new incoming connection from "
+ + sock.getRemoteDevice().getName());
+
+ // session will live until closed by remote
+ BluetoothMnsObexServer srv = new BluetoothMnsObexServer(mSessionHandler);
+ BluetoothMapRfcommTransport transport = new BluetoothMapRfcommTransport(
+ sock);
+ new ServerSession(transport, srv, null);
+ } catch (IOException ex) {
+ Log.v(TAG, "I/O exception when waiting to accept (aborted?)");
+ mInterrupted = true;
+ }
+ }
+
+ if (mServerSocket != null) {
+ try {
+ mServerSocket.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+
+ mServerSocket = null;
+ }
+ }
+ }
+
+ BluetoothMnsService() {
+ Log.v(TAG, "BluetoothMnsService()");
+
+ if (mCallbacks == null) {
+ Log.v(TAG, "BluetoothMnsService(): allocating callbacks");
+ mCallbacks = new SparseArray<Handler>();
+ }
+
+ if (mSessionHandler == null) {
+ Log.v(TAG, "BluetoothMnsService(): allocating session handler");
+ mSessionHandler = new SessionHandler(this);
+ }
+ }
+
+ public void registerCallback(int instanceId, Handler callback) {
+ Log.v(TAG, "registerCallback()");
+
+ synchronized (mCallbacks) {
+ mCallbacks.put(instanceId, callback);
+
+ if (mAcceptThread == null) {
+ Log.v(TAG, "registerCallback(): starting MNS server");
+ mAcceptThread = new SocketAcceptThread();
+ mAcceptThread.setName("BluetoothMnsAcceptThread");
+ mAcceptThread.start();
+ }
+ }
+ }
+
+ public void unregisterCallback(int instanceId) {
+ Log.v(TAG, "unregisterCallback()");
+
+ synchronized (mCallbacks) {
+ mCallbacks.remove(instanceId);
+
+ if (mCallbacks.size() == 0) {
+ Log.v(TAG, "unregisterCallback(): shutting down MNS server");
+
+ if (mServerSocket != null) {
+ try {
+ mServerSocket.close();
+ } catch (IOException e) {
+ }
+
+ mServerSocket = null;
+ }
+
+ mAcceptThread.interrupt();
+
+ try {
+ mAcceptThread.join(5000);
+ } catch (InterruptedException e) {
+ }
+
+ mAcceptThread = null;
+ }
+ }
+ }
+}