OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / core / java / android / bluetooth / BluetoothAudioGateway.java
1 /*
2  * Copyright (C) 2007 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 android.bluetooth;
18
19 import java.lang.Thread;
20
21 import android.os.Message;
22 import android.os.Handler;
23 import android.util.Log;
24
25 /**
26  * Listens for incoming RFCOMM connection for the headset / handsfree service.
27  *
28  * TODO: Use the new generic BluetoothSocket class instead of this legacy code
29  *
30  * @hide
31  */
32 public final class BluetoothAudioGateway {
33     private static final String TAG = "BT Audio Gateway";
34     private static final boolean DBG = false;
35
36     private int mNativeData;
37     static { classInitNative(); }
38
39     /* in */
40     private int mHandsfreeAgRfcommChannel = -1;
41     private int mHeadsetAgRfcommChannel   = -1;
42
43     /* out - written by native code */
44     private String mConnectingHeadsetAddress;
45     private int mConnectingHeadsetRfcommChannel; /* -1 when not connected */
46     private int mConnectingHeadsetSocketFd;
47     private String mConnectingHandsfreeAddress;
48     private int mConnectingHandsfreeRfcommChannel; /* -1 when not connected */
49     private int mConnectingHandsfreeSocketFd;
50     private int mTimeoutRemainingMs; /* in/out */
51
52     private final BluetoothAdapter mAdapter;
53
54     public static final int DEFAULT_HF_AG_CHANNEL = 10;
55     public static final int DEFAULT_HS_AG_CHANNEL = 11;
56
57     public BluetoothAudioGateway(BluetoothAdapter adapter) {
58         this(adapter, DEFAULT_HF_AG_CHANNEL, DEFAULT_HS_AG_CHANNEL);
59     }
60
61     public BluetoothAudioGateway(BluetoothAdapter adapter, int handsfreeAgRfcommChannel,
62                 int headsetAgRfcommChannel) {
63         mAdapter = adapter;
64         mHandsfreeAgRfcommChannel = handsfreeAgRfcommChannel;
65         mHeadsetAgRfcommChannel = headsetAgRfcommChannel;
66         initializeNativeDataNative();
67     }
68
69     private Thread mConnectThead;
70     private volatile boolean mInterrupted;
71     private static final int SELECT_WAIT_TIMEOUT = 1000;
72
73     private Handler mCallback;
74
75     public class IncomingConnectionInfo {
76         public BluetoothAdapter mAdapter;
77         public BluetoothDevice mRemoteDevice;
78         public int mSocketFd;
79         public int mRfcommChan;
80         IncomingConnectionInfo(BluetoothAdapter adapter, BluetoothDevice remoteDevice,
81                 int socketFd, int rfcommChan) {
82             mAdapter = adapter;
83             mRemoteDevice = remoteDevice;
84             mSocketFd = socketFd;
85             mRfcommChan = rfcommChan;
86         }
87     }
88
89     public static final int MSG_INCOMING_HEADSET_CONNECTION   = 100;
90     public static final int MSG_INCOMING_HANDSFREE_CONNECTION = 101;
91
92     public synchronized boolean start(Handler callback) {
93
94         if (mConnectThead == null) {
95             mCallback = callback;
96             mConnectThead = new Thread(TAG) {
97                     public void run() {
98                         if (DBG) log("Connect Thread starting");
99                         while (!mInterrupted) {
100                             //Log.i(TAG, "waiting for connect");
101                             mConnectingHeadsetRfcommChannel = -1;
102                             mConnectingHandsfreeRfcommChannel = -1;
103                             if (waitForHandsfreeConnectNative(SELECT_WAIT_TIMEOUT) == false) {
104                                 if (mTimeoutRemainingMs > 0) {
105                                     try {
106                                         Log.i(TAG, "select thread timed out, but " + 
107                                               mTimeoutRemainingMs + "ms of waiting remain.");
108                                         Thread.sleep(mTimeoutRemainingMs);
109                                     } catch (InterruptedException e) {
110                                         Log.i(TAG, "select thread was interrupted (2), exiting");
111                                         mInterrupted = true;
112                                     }
113                                 }
114                             }
115                             else {
116                                 Log.i(TAG, "connect notification!");
117                                 /* A device connected (most likely just one, but 
118                                    it is possible for two separate devices, one 
119                                    a headset and one a handsfree, to connect
120                                    simultaneously. 
121                                 */
122                                 if (mConnectingHeadsetRfcommChannel >= 0) {
123                                     Log.i(TAG, "Incoming connection from headset " + 
124                                           mConnectingHeadsetAddress + " on channel " + 
125                                           mConnectingHeadsetRfcommChannel);
126                                     Message msg = Message.obtain(mCallback);
127                                     msg.what = MSG_INCOMING_HEADSET_CONNECTION;
128                                     msg.obj = new IncomingConnectionInfo(
129                                         mAdapter,
130                                         mAdapter.getRemoteDevice(mConnectingHeadsetAddress),
131                                         mConnectingHeadsetSocketFd,
132                                         mConnectingHeadsetRfcommChannel);
133                                     msg.sendToTarget();
134                                 }
135                                 if (mConnectingHandsfreeRfcommChannel >= 0) {
136                                     Log.i(TAG, "Incoming connection from handsfree " + 
137                                           mConnectingHandsfreeAddress + " on channel " + 
138                                           mConnectingHandsfreeRfcommChannel);
139                                     Message msg = Message.obtain();
140                                     msg.setTarget(mCallback);
141                                     msg.what = MSG_INCOMING_HANDSFREE_CONNECTION;
142                                     msg.obj = new IncomingConnectionInfo(
143                                         mAdapter,
144                                         mAdapter.getRemoteDevice(mConnectingHandsfreeAddress),
145                                         mConnectingHandsfreeSocketFd,
146                                         mConnectingHandsfreeRfcommChannel);
147                                     msg.sendToTarget();
148                                 }
149                             }
150                         }
151                         if (DBG) log("Connect Thread finished");
152                     }
153                 };
154
155             if (setUpListeningSocketsNative() == false) {
156                 Log.e(TAG, "Could not set up listening socket, exiting");
157                 return false;
158             }
159
160             mInterrupted = false;
161             mConnectThead.start();
162         }
163
164         return true;
165     }
166
167     public synchronized void stop() {
168         if (mConnectThead != null) {
169             if (DBG) log("stopping Connect Thread");
170             mInterrupted = true;
171             try {
172                 mConnectThead.interrupt();
173                 if (DBG) log("waiting for thread to terminate");
174                 mConnectThead.join();
175                 mConnectThead = null;
176                 mCallback = null;
177                 tearDownListeningSocketsNative();
178             } catch (InterruptedException e) {
179                 Log.w(TAG, "Interrupted waiting for Connect Thread to join");
180             }
181         }
182     }
183
184     protected void finalize() throws Throwable {
185         try {
186             cleanupNativeDataNative();
187         } finally {
188             super.finalize();
189         }
190     }
191
192     private static native void classInitNative();
193     private native void initializeNativeDataNative();
194     private native void cleanupNativeDataNative();
195     private native boolean waitForHandsfreeConnectNative(int timeoutMs);
196     private native boolean setUpListeningSocketsNative();
197     private native void tearDownListeningSocketsNative();
198
199     private static void log(String msg) {
200         Log.d(TAG, msg);
201     }
202 }