1192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta/*
2192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * Copyright (C) 2014 The Android Open Source Project
3192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta *
4192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * Licensed under the Apache License, Version 2.0 (the "License");
5192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * you may not use this file except in compliance with the License.
6192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * You may obtain a copy of the License at
7192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta *
8192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta *      http://www.apache.org/licenses/LICENSE-2.0
9192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta *
10192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * Unless required by applicable law or agreed to in writing, software
11192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * distributed under the License is distributed on an "AS IS" BASIS,
12192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * See the License for the specific language governing permissions and
14192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * limitations under the License.
15192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta */
16192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
17192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptapackage android.bluetooth.client.pbap;
18192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
19192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport android.bluetooth.BluetoothAdapter;
20192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport android.bluetooth.BluetoothDevice;
21192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport android.bluetooth.BluetoothSocket;
22192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport android.os.Handler;
23192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport android.os.Handler.Callback;
24192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport android.os.HandlerThread;
25192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport android.os.Message;
26192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport android.os.Process;
27192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport android.util.Log;
28192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
29192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport java.io.IOException;
30192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport java.util.UUID;
31192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
32192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaclass BluetoothPbapSession implements Callback {
33192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private static final String TAG = "android.bluetooth.client.pbap.BluetoothPbapSession";
34192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
35192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    /* local use only */
36192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private static final int RFCOMM_CONNECTED = 1;
37192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private static final int RFCOMM_FAILED = 2;
38192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
39192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    /* to BluetoothPbapClient */
40192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public static final int REQUEST_COMPLETED = 3;
41192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public static final int REQUEST_FAILED = 4;
42192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public static final int SESSION_CONNECTING = 5;
43192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public static final int SESSION_CONNECTED = 6;
44192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public static final int SESSION_DISCONNECTED = 7;
45192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public static final int AUTH_REQUESTED = 8;
46192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public static final int AUTH_TIMEOUT = 9;
47192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
48192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public static final int ACTION_LISTING = 14;
49192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public static final int ACTION_VCARD = 15;
50192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public static final int ACTION_PHONEBOOK_SIZE = 16;
51192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
52192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private static final String PBAP_UUID =
53192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            "0000112f-0000-1000-8000-00805f9b34fb";
54192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
55192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private final BluetoothAdapter mAdapter;
56192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private final BluetoothDevice mDevice;
57192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
58192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private final Handler mParentHandler;
59192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
60192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private final HandlerThread mHandlerThread;
61192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private final Handler mSessionHandler;
62192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
63192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private RfcommConnectThread mConnectThread;
64192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private BluetoothPbapObexTransport mTransport;
65192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
66192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private BluetoothPbapObexSession mObexSession;
67192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
68192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private BluetoothPbapRequest mPendingRequest = null;
69192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
70192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public BluetoothPbapSession(BluetoothDevice device, Handler handler) {
71192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
72192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        mAdapter = BluetoothAdapter.getDefaultAdapter();
73192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        if (mAdapter == null) {
74192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            throw new NullPointerException("No Bluetooth adapter in the system");
75192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        }
76192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
77192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        mDevice = device;
78192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        mParentHandler = handler;
79192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        mConnectThread = null;
80192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        mTransport = null;
81192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        mObexSession = null;
82192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
83192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        mHandlerThread = new HandlerThread("PBAP session handler",
84192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                Process.THREAD_PRIORITY_BACKGROUND);
85192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        mHandlerThread.start();
86192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        mSessionHandler = new Handler(mHandlerThread.getLooper(), this);
87192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    }
88192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
89192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    @Override
90192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public boolean handleMessage(Message msg) {
91192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        Log.d(TAG, "Handler: msg: " + msg.what);
92192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
93192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        switch (msg.what) {
94192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            case RFCOMM_FAILED:
95192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mConnectThread = null;
96192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
97192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mParentHandler.obtainMessage(SESSION_DISCONNECTED).sendToTarget();
98192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
99192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                if (mPendingRequest != null) {
100192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                    mParentHandler.obtainMessage(REQUEST_FAILED, mPendingRequest).sendToTarget();
101192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                    mPendingRequest = null;
102192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                }
103192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                break;
104192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
105192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            case RFCOMM_CONNECTED:
106192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mConnectThread = null;
107192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mTransport = (BluetoothPbapObexTransport) msg.obj;
108192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                startObexSession();
109192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                break;
110192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
111192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            case BluetoothPbapObexSession.OBEX_SESSION_FAILED:
112192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                stopObexSession();
113192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
114192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mParentHandler.obtainMessage(SESSION_DISCONNECTED).sendToTarget();
115192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
116192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                if (mPendingRequest != null) {
117192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                    mParentHandler.obtainMessage(REQUEST_FAILED, mPendingRequest).sendToTarget();
118192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                    mPendingRequest = null;
119192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                }
120192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                break;
121192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
122192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            case BluetoothPbapObexSession.OBEX_SESSION_CONNECTED:
123192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mParentHandler.obtainMessage(SESSION_CONNECTED).sendToTarget();
124192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
125192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                if (mPendingRequest != null) {
126192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                    mObexSession.schedule(mPendingRequest);
127192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                    mPendingRequest = null;
128192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                }
129192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                break;
130192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
131192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            case BluetoothPbapObexSession.OBEX_SESSION_DISCONNECTED:
132192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mParentHandler.obtainMessage(SESSION_DISCONNECTED).sendToTarget();
133192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                stopRfcomm();
134192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                break;
135192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
136192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            case BluetoothPbapObexSession.OBEX_SESSION_REQUEST_COMPLETED:
137192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                /* send to parent, process there */
138192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mParentHandler.obtainMessage(REQUEST_COMPLETED, msg.obj).sendToTarget();
139192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                break;
140192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
141192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            case BluetoothPbapObexSession.OBEX_SESSION_REQUEST_FAILED:
142192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                /* send to parent, process there */
143192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mParentHandler.obtainMessage(REQUEST_FAILED, msg.obj).sendToTarget();
144192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                break;
145192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
146192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            case BluetoothPbapObexSession.OBEX_SESSION_AUTHENTICATION_REQUEST:
147192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                /* send to parent, process there */
148192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mParentHandler.obtainMessage(AUTH_REQUESTED).sendToTarget();
149192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
150192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mSessionHandler
151192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                        .sendMessageDelayed(
152192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                                mSessionHandler
153192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                                        .obtainMessage(BluetoothPbapObexSession.OBEX_SESSION_AUTHENTICATION_TIMEOUT),
154192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                                30000);
155192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                break;
156192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
157192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            case BluetoothPbapObexSession.OBEX_SESSION_AUTHENTICATION_TIMEOUT:
158192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                /* stop authentication */
159192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                setAuthResponse(null);
160192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
161192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mParentHandler.obtainMessage(AUTH_TIMEOUT).sendToTarget();
162192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                break;
163192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
164192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            default:
165192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                return false;
166192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        }
167192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
168192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        return true;
169192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    }
170192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
171192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public void start() {
172192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        Log.d(TAG, "start");
173192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
174192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        startRfcomm();
175192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    }
176192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
177192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public void stop() {
178192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        Log.d(TAG, "Stop");
179192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
180192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        stopObexSession();
181192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        stopRfcomm();
182192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    }
183192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
184192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public void abort() {
185192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        Log.d(TAG, "abort");
186192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
187192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        /* fail pending request immediately */
188192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        if (mPendingRequest != null) {
189192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            mParentHandler.obtainMessage(REQUEST_FAILED, mPendingRequest).sendToTarget();
190192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            mPendingRequest = null;
191192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        }
192192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
193192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        if (mObexSession != null) {
194192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            mObexSession.abort();
195192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        }
196192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    }
197192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
198192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public boolean makeRequest(BluetoothPbapRequest request) {
199192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        Log.v(TAG, "makeRequest: " + request.getClass().getSimpleName());
200192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
201192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        if (mPendingRequest != null) {
202192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            Log.w(TAG, "makeRequest: request already queued, exiting");
203192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            return false;
204192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        }
205192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
206192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        if (mObexSession == null) {
207192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            mPendingRequest = request;
208192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
209192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            /*
210192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta             * since there is no pending request and no session it's safe to
211192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta             * assume that RFCOMM does not exist either and we should start
212192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta             * connecting it
213192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta             */
214192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            startRfcomm();
215192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
216192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            return true;
217192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        }
218192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
219192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        return mObexSession.schedule(request);
220192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    }
221192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
222192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    public boolean setAuthResponse(String key) {
223192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        Log.d(TAG, "setAuthResponse key=" + key);
224192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
225192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        mSessionHandler
226192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                .removeMessages(BluetoothPbapObexSession.OBEX_SESSION_AUTHENTICATION_TIMEOUT);
227192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
228192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        /* does not make sense to set auth response when OBEX session is down */
229192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        if (mObexSession == null) {
230192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            return false;
231192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        }
232192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
233192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        return mObexSession.setAuthReply(key);
234192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    }
235192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
236192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private void startRfcomm() {
237192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        Log.d(TAG, "startRfcomm");
238192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
239192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        if (mConnectThread == null && mObexSession == null) {
240192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            mParentHandler.obtainMessage(SESSION_CONNECTING).sendToTarget();
241192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
242192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            mConnectThread = new RfcommConnectThread();
243192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            mConnectThread.start();
244192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        }
245192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
246192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        /*
247192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta         * don't care if mConnectThread is not null - it means RFCOMM is being
248192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta         * connected anyway
249192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta         */
250192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    }
251192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
252192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private void stopRfcomm() {
253192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        Log.d(TAG, "stopRfcomm");
254192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
255192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        if (mConnectThread != null) {
256192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            try {
257192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mConnectThread.join();
258192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            } catch (InterruptedException e) {
259192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            }
260192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
261192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            mConnectThread = null;
262192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        }
263192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
264192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        if (mTransport != null) {
265192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            try {
266192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mTransport.close();
267192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            } catch (IOException e) {
268192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            }
269192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
270192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            mTransport = null;
271192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        }
272192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    }
273192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
274192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private void startObexSession() {
275192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        Log.d(TAG, "startObexSession");
276192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
277192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        mObexSession = new BluetoothPbapObexSession(mTransport);
278192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        mObexSession.start(mSessionHandler);
279192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    }
280192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
281192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private void stopObexSession() {
282192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        Log.d(TAG, "stopObexSession");
283192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
284192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        if (mObexSession != null) {
285192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            mObexSession.stop();
286192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            mObexSession = null;
287192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        }
288192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    }
289192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
290192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    private class RfcommConnectThread extends Thread {
291192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        private static final String TAG = "RfcommConnectThread";
292192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
293192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        private BluetoothSocket mSocket;
294192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
295192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        public RfcommConnectThread() {
296192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            super("RfcommConnectThread");
297192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        }
298192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
299192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        @Override
300192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        public void run() {
301192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            if (mAdapter.isDiscovering()) {
302192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mAdapter.cancelDiscovery();
303192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            }
304192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
305192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            try {
306192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mSocket = mDevice.createRfcommSocketToServiceRecord(UUID.fromString(PBAP_UUID));
307192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mSocket.connect();
308192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
309192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                BluetoothPbapObexTransport transport;
310192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                transport = new BluetoothPbapObexTransport(mSocket);
311192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
312192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mSessionHandler.obtainMessage(RFCOMM_CONNECTED, transport).sendToTarget();
313192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            } catch (IOException e) {
314192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                closeSocket();
315192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                mSessionHandler.obtainMessage(RFCOMM_FAILED).sendToTarget();
316192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            }
317192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
318192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        }
319192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta
320192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        private void closeSocket() {
321192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            try {
322192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                if (mSocket != null) {
323192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                    mSocket.close();
324192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                }
325192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            } catch (IOException e) {
326192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta                Log.e(TAG, "Error when closing socket", e);
327192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta            }
328192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta        }
329192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta    }
330192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta}
331