• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bluetooth.mapclient;
18 
19 import android.bluetooth.BluetoothDevice;
20 import android.bluetooth.BluetoothProfile;
21 import android.bluetooth.BluetoothServerSocket;
22 import android.bluetooth.BluetoothSocket;
23 import android.os.Handler;
24 import android.util.Log;
25 
26 import com.android.bluetooth.BluetoothObexTransport;
27 import com.android.bluetooth.IObexConnectionHandler;
28 import com.android.bluetooth.ObexServerSockets;
29 import com.android.bluetooth.Utils;
30 import com.android.bluetooth.sdp.SdpManager;
31 
32 import java.io.IOException;
33 
34 import javax.obex.ServerSession;
35 
36 /**
37  * Message Notification Server implementation
38  */
39 public class MnsService {
40     static final int MSG_EVENT = 1;
41     /* for Client */
42     static final int EVENT_REPORT = 1001;
43     private static final String TAG = "MnsService";
44     private static final Boolean DBG = MapClientService.DBG;
45     private static final Boolean VDBG = MapClientService.VDBG;
46     /* MAP version 1.4 */
47     private static final int MNS_VERSION = 0x0104;
48     /* these are shared across instances */
49     private static SocketAcceptor sAcceptThread = null;
50     private static Handler sSessionHandler = null;
51     private static BluetoothServerSocket sServerSocket = null;
52     private static ObexServerSockets sServerSockets = null;
53 
54     private static MapClientService sContext;
55     private volatile boolean mShutdown = false;         // Used to interrupt socket accept thread
56     private int mSdpHandle = -1;
57 
MnsService(MapClientService context)58     MnsService(MapClientService context) {
59         if (VDBG) {
60             Log.v(TAG, "MnsService()");
61         }
62         sContext = context;
63         sAcceptThread = new SocketAcceptor();
64         sServerSockets = ObexServerSockets.create(sAcceptThread);
65         SdpManager sdpManager = SdpManager.getDefaultManager();
66         if (sdpManager == null) {
67             Log.e(TAG, "SdpManager is null");
68             return;
69         }
70         mSdpHandle = sdpManager.createMapMnsRecord("MAP Message Notification Service",
71                 sServerSockets.getRfcommChannel(), sServerSockets.getL2capPsm(), MNS_VERSION,
72                 MasClient.MAP_SUPPORTED_FEATURES);
73     }
74 
stop()75     void stop() {
76         if (VDBG) {
77             Log.v(TAG, "stop()");
78         }
79         mShutdown = true;
80         cleanUpSdpRecord();
81         if (sServerSockets != null) {
82             sServerSockets.shutdown(false);
83             sServerSockets = null;
84         }
85     }
86 
cleanUpSdpRecord()87     private void cleanUpSdpRecord() {
88         if (mSdpHandle < 0) {
89             Log.e(TAG, "cleanUpSdpRecord, SDP record never created");
90             return;
91         }
92         int sdpHandle = mSdpHandle;
93         mSdpHandle = -1;
94         SdpManager sdpManager = SdpManager.getDefaultManager();
95         if (sdpManager == null) {
96             Log.e(TAG, "cleanUpSdpRecord failed, sdpManager is null, sdpHandle=" + sdpHandle);
97             return;
98         }
99         Log.i(TAG, "cleanUpSdpRecord, mSdpHandle=" + sdpHandle);
100         if (!sdpManager.removeSdpRecord(sdpHandle)) {
101             Log.e(TAG, "cleanUpSdpRecord, removeSdpRecord failed, sdpHandle=" + sdpHandle);
102         }
103     }
104 
105     private class SocketAcceptor implements IObexConnectionHandler {
106 
107         private boolean mInterrupted = false;
108 
109         /**
110          * Called when an unrecoverable error occurred in an accept thread.
111          * Close down the server socket, and restart.
112          * TODO: Change to message, to call start in correct context.
113          */
114         @Override
onAcceptFailed()115         public synchronized void onAcceptFailed() {
116             Log.e(TAG, "OnAcceptFailed");
117             sServerSockets = null; // Will cause a new to be created when calling start.
118             if (mShutdown) {
119                 Log.e(TAG, "Failed to accept incomming connection - " + "shutdown");
120             }
121         }
122 
123         @Override
onConnect(BluetoothDevice device, BluetoothSocket socket)124         public synchronized boolean onConnect(BluetoothDevice device, BluetoothSocket socket) {
125             if (DBG) {
126                 Log.d(TAG, "onConnect" + device + " SOCKET: " + socket);
127             }
128             /* Signal to the service that we have received an incoming connection.*/
129             MceStateMachine stateMachine = sContext.getMceStateMachineForDevice(device);
130             if (stateMachine == null) {
131                 Log.e(TAG, "Error: NO statemachine for device: " + device.getAddress()
132                         + " (name: " + Utils.getName(device));
133                 return false;
134             } else if (stateMachine.getState() != BluetoothProfile.STATE_CONNECTED) {
135                 Log.e(TAG, "Error: statemachine for device: " + device.getAddress()
136                         + " (name: " + Utils.getName(device) + ") is not currently CONNECTED : "
137                         + stateMachine.getCurrentState());
138                 return false;
139             }
140             MnsObexServer srv = new MnsObexServer(stateMachine, sServerSockets);
141             BluetoothObexTransport transport = new BluetoothObexTransport(socket);
142             try {
143                 new ServerSession(transport, srv, null);
144                 return true;
145             } catch (IOException e) {
146                 Log.e(TAG, e.toString());
147                 return false;
148             }
149         }
150     }
151 }
152