1b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh/*
2b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * Copyright (c) 2008-2009, Motorola, Inc.
3b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh *
4b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * All rights reserved.
5b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh *
6b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * Redistribution and use in source and binary forms, with or without
7b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * modification, are permitted provided that the following conditions are met:
8b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh *
9b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * - Redistributions of source code must retain the above copyright notice,
10b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * this list of conditions and the following disclaimer.
11b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh *
12b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * - Redistributions in binary form must reproduce the above copyright notice,
13b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * this list of conditions and the following disclaimer in the documentation
14b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * and/or other materials provided with the distribution.
15b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh *
16b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * - Neither the name of the Motorola, Inc. nor the names of its contributors
17b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * may be used to endorse or promote products derived from this software
18b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * without specific prior written permission.
19b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh *
20b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * POSSIBILITY OF SUCH DAMAGE.
31b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh */
322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
332c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanpackage com.android.bluetooth.pbap;
342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
354446eaa935994bc91d6d308303e8d27526b4590dLixin Yueimport android.app.Notification;
364446eaa935994bc91d6d308303e8d27526b4590dLixin Yueimport android.app.NotificationManager;
374446eaa935994bc91d6d308303e8d27526b4590dLixin Yueimport android.app.PendingIntent;
382c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport android.app.Service;
3941ef8d494511c040451f2f887cb31c3100746b61Nick Pellyimport android.bluetooth.BluetoothAdapter;
402c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport android.bluetooth.BluetoothDevice;
4137b69bd05e4b7a7d0e43575a6c22734b2d8c3f69Jackson Fanimport android.bluetooth.BluetoothPbap;
4272d2952fcde46d8c2adc68718957c2fe9f5fa3b0Jaikumar Ganeshimport android.bluetooth.BluetoothProfile;
432c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport android.bluetooth.BluetoothServerSocket;
4484ec2fa756c3e918b6083726271128096de57ffbJaikumar Ganeshimport android.bluetooth.BluetoothSocket;
4584ec2fa756c3e918b6083726271128096de57ffbJaikumar Ganeshimport android.bluetooth.IBluetooth;
4637b69bd05e4b7a7d0e43575a6c22734b2d8c3f69Jackson Fanimport android.bluetooth.IBluetoothPbap;
479f0d856f41d443ec23d5aa2eecfc561d7a3c01d1fredcimport android.bluetooth.BluetoothUuid;
4884ec2fa756c3e918b6083726271128096de57ffbJaikumar Ganeshimport android.content.Context;
4984ec2fa756c3e918b6083726271128096de57ffbJaikumar Ganeshimport android.content.Intent;
502c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport android.os.Handler;
512c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport android.os.IBinder;
522c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport android.os.Message;
532c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport android.os.PowerManager;
5484ec2fa756c3e918b6083726271128096de57ffbJaikumar Ganeshimport android.os.RemoteException;
5584ec2fa756c3e918b6083726271128096de57ffbJaikumar Ganeshimport android.os.ServiceManager;
562c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport android.telephony.TelephonyManager;
572f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.text.TextUtils;
582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport android.util.Log;
59bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
60bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport com.android.bluetooth.BluetoothObexTransport;
6137510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xuimport com.android.bluetooth.Utils;
629f0d856f41d443ec23d5aa2eecfc561d7a3c01d1fredc
639f0d856f41d443ec23d5aa2eecfc561d7a3c01d1fredc
6484ec2fa756c3e918b6083726271128096de57ffbJaikumar Ganeshimport com.android.bluetooth.R;
65b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport com.android.bluetooth.btservice.AdapterService;
6684ec2fa756c3e918b6083726271128096de57ffbJaikumar Ganesh
672c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport java.io.IOException;
682c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
692c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport javax.obex.ServerSession;
702c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
712c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanpublic class BluetoothPbapService extends Service {
722c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String TAG = "BluetoothPbapService";
732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
744446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    /**
752f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue     * To enable PBAP DEBUG/VERBOSE logging - run below cmd in adb shell, and
762f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue     * restart com.android.bluetooth process. only enable DEBUG log:
772f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue     * "setprop log.tag.BluetoothPbapService DEBUG"; enable both VERBOSE and
782f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue     * DEBUG log: "setprop log.tag.BluetoothPbapService VERBOSE"
794446eaa935994bc91d6d308303e8d27526b4590dLixin Yue     */
804446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
816654f5c903de510a70f9e72cd5ad7837b615d93ffredc    public static final boolean DEBUG = true;
824446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
83fd1da115cbf09b7dd9bca3c7d3a4fb816a835dc5Matthew Xie    public static final boolean VERBOSE = false;
842c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
852c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /**
862c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * Intent indicating incoming obex authentication request which is from
872c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * PCE(Carkit)
882c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     */
89d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    public static final String AUTH_CHALL_ACTION = "com.android.bluetooth.pbap.authchall";
902c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
912c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /**
922c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * Intent indicating obex session key input complete by user which is sent
932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * from BluetoothPbapActivity
942c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     */
95d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    public static final String AUTH_RESPONSE_ACTION = "com.android.bluetooth.pbap.authresponse";
962c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
972c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /**
982c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * Intent indicating user canceled obex authentication session key input
992c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * which is sent from BluetoothPbapActivity
1002c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     */
101d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    public static final String AUTH_CANCELLED_ACTION = "com.android.bluetooth.pbap.authcancelled";
1022c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /**
104d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue     * Intent indicating timeout for user confirmation, which is sent to
1052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * BluetoothPbapActivity
1062c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     */
107d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    public static final String USER_CONFIRM_TIMEOUT_ACTION =
1084446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            "com.android.bluetooth.pbap.userconfirmtimeout";
1092c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1102c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /**
1112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * Intent Extra name indicating session key which is sent from
1122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * BluetoothPbapActivity
1132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     */
114d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    public static final String EXTRA_SESSION_KEY = "com.android.bluetooth.pbap.sessionkey";
1152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public static final String THIS_PACKAGE_NAME = "com.android.bluetooth";
1172c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1182c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public static final int MSG_SERVERSESSION_CLOSE = 5000;
1192c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1202c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public static final int MSG_SESSION_ESTABLISHED = 5001;
1212c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1222c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public static final int MSG_SESSION_DISCONNECTED = 5002;
1232c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1242c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public static final int MSG_OBEX_AUTH_CHALL = 5003;
1252c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1268fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu    public static final int MSG_ACQUIRE_WAKE_LOCK = 5004;
1278fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu
1288fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu    public static final int MSG_RELEASE_WAKE_LOCK = 5005;
1298fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu
1302c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
1312c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
1332c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final int START_LISTENER = 1;
1352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final int USER_TIMEOUT = 2;
1372c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1382c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final int AUTH_TIMEOUT = 3;
1392c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1404446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
1414446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final int USER_CONFIRM_TIMEOUT_VALUE = 30000;
1424446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
1438fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu    private static final int RELEASE_WAKE_LOCK_DELAY = 10000;
1444446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
1454446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    // Ensure not conflict with Opp notification ID
1464446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final int NOTIFICATION_ID_ACCESS = -1000001;
1474446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
1484446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final int NOTIFICATION_ID_AUTH = -1000002;
1494446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
1502c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private PowerManager.WakeLock mWakeLock = null;
1512c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
15241ef8d494511c040451f2f887cb31c3100746b61Nick Pelly    private BluetoothAdapter mAdapter;
1532c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1542c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private SocketAcceptThread mAcceptThread = null;
1552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1564446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private BluetoothPbapAuthenticator mAuth = null;
1574446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
1582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private BluetoothPbapObexServer mPbapServer;
1592c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1602c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private ServerSession mServerSession = null;
1612c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private BluetoothServerSocket mServerSocket = null;
1632c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private BluetoothSocket mConnSocket = null;
1652c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1664446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private BluetoothDevice mRemoteDevice = null;
1672c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1682c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static String sLocalPhoneNum = null;
1692c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1702c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static String sLocalPhoneName = null;
1712c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1722c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static String sRemoteDeviceName = null;
1732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1742c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private boolean mHasStarted = false;
1752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1764446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private volatile boolean mInterrupted;
1774446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
1782c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private int mState;
1792c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1802c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private int mStartId = -1;
1812c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
182b5cc776c9353a203cdde97e62b25f05d9633d14cfredc    //private IBluetooth mBluetoothService;
18384ec2fa756c3e918b6083726271128096de57ffbJaikumar Ganesh
184fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee    private boolean mIsWaitingAuthorization = false;
1857eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie
1867eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie    // package and class name to which we send intent to check phone book access permission
1877eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie    private static final String ACCESS_AUTHORITY_PACKAGE = "com.android.settings";
1887eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie    private static final String ACCESS_AUTHORITY_CLASS =
1897eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie        "com.android.settings.bluetooth.BluetoothPermissionRequest";
1907eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie
1912c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public BluetoothPbapService() {
19237b69bd05e4b7a7d0e43575a6c22734b2d8c3f69Jackson Fan        mState = BluetoothPbap.STATE_DISCONNECTED;
1932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
1942c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1952c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
1962c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public void onCreate() {
1972c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        super.onCreate();
1984446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (VERBOSE) Log.v(TAG, "Pbap Service onCreate");
1994446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
2004446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        mInterrupted = false;
2013a88b20fcd71e42451e402d27374b19eeb2ff0daNick Pelly        mAdapter = BluetoothAdapter.getDefaultAdapter();
2022f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
2034446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (!mHasStarted) {
2042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            mHasStarted = true;
2054446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (VERBOSE) Log.v(TAG, "Starting PBAP service");
206c7a57f31515107366589bd6875c3cc4af1fc806efredc            BluetoothPbapConfig.init(this);
207f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly            int state = mAdapter.getState();
208f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly            if (state == BluetoothAdapter.STATE_ON) {
20977e6229d558b52c316fdba8dd29a6b26fb13fd28jhtop.kim                mSessionStatusHandler.sendMessage(mSessionStatusHandler
21077e6229d558b52c316fdba8dd29a6b26fb13fd28jhtop.kim                        .obtainMessage(START_LISTENER));
2112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
2122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
2132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
2142c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
2168222c7902a2281929fd31e840f6012038e6fa44aLixin Yue    public int onStartCommand(Intent intent, int flags, int startId) {
21731ba132491053bc86d419a7d51fc04af3299c076fredc        //int retCode = super.onStartCommand(intent, flags, startId);
21831ba132491053bc86d419a7d51fc04af3299c076fredc        //if (retCode == START_STICKY) {
2198222c7902a2281929fd31e840f6012038e6fa44aLixin Yue            mStartId = startId;
2208222c7902a2281929fd31e840f6012038e6fa44aLixin Yue            if (mAdapter == null) {
2218222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                Log.w(TAG, "Stopping BluetoothPbapService: "
2228222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                        + "device does not have BT or device is not ready");
2238222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                // Release all resources
2248222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                closeService();
2258222c7902a2281929fd31e840f6012038e6fa44aLixin Yue            } else {
2268222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                // No need to handle the null intent case, because we have
2278222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                // all restart work done in onCreate()
2288222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                if (intent != null) {
2298222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                    parseIntent(intent);
2308222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                }
2318222c7902a2281929fd31e840f6012038e6fa44aLixin Yue            }
23231ba132491053bc86d419a7d51fc04af3299c076fredc        //}
23331ba132491053bc86d419a7d51fc04af3299c076fredc        return START_NOT_STICKY;
2342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
2352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // process the intent from receiver
2372c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private void parseIntent(final Intent intent) {
2382f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String action = intent.getStringExtra("action");
239534bbd9a2347141644a684ce179b2cedf20541b4Pavlin Radoslavov        if (action == null) return;             // Nothing to do
2402f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (VERBOSE) Log.v(TAG, "action: " + action);
2412f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
242613bae227d65f61903e196944a9c718b4394f25aNick Pelly        int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
2436654f5c903de510a70f9e72cd5ad7837b615d93ffredc        if (VERBOSE) Log.v(TAG, "state: " + state);
2446654f5c903de510a70f9e72cd5ad7837b615d93ffredc
2454446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        boolean removeTimeoutMsg = true;
246f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly        if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
24715d36984a79d6e35c659edb0efdf929f0b526bd5Fred            if (state == BluetoothAdapter.STATE_TURNING_OFF) {
2487d6a3299b58c5b53de4016a2e199974b94ae90dfMathias Jeppsson                // Send any pending timeout now, as this service will be destroyed.
2497d6a3299b58c5b53de4016a2e199974b94ae90dfMathias Jeppsson                if (mSessionStatusHandler.hasMessages(USER_TIMEOUT)) {
2507eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                    Intent timeoutIntent =
2517eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                        new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL);
2527eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                    timeoutIntent.setClassName(ACCESS_AUTHORITY_PACKAGE, ACCESS_AUTHORITY_CLASS);
25370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                    timeoutIntent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
25470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                                     BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS);
255dca6152362544ce9d430ca8f2ece7d5dc0f278d1Jaikumar Ganesh                    sendBroadcast(timeoutIntent, BLUETOOTH_ADMIN_PERM);
2567d6a3299b58c5b53de4016a2e199974b94ae90dfMathias Jeppsson                }
2574446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                // Release all resources
2584446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                closeService();
2597d6a3299b58c5b53de4016a2e199974b94ae90dfMathias Jeppsson            } else {
2607d6a3299b58c5b53de4016a2e199974b94ae90dfMathias Jeppsson                removeTimeoutMsg = false;
2612c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
262fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee        } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)
263fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                && mIsWaitingAuthorization) {
2644216387d9887926cebd652f8d3807d780642fc87Hemant Gupta            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
2654216387d9887926cebd652f8d3807d780642fc87Hemant Gupta
2664216387d9887926cebd652f8d3807d780642fc87Hemant Gupta            if (mRemoteDevice == null || device == null) {
2674216387d9887926cebd652f8d3807d780642fc87Hemant Gupta                Log.e(TAG, "Unexpected error!");
2684216387d9887926cebd652f8d3807d780642fc87Hemant Gupta                return;
2694216387d9887926cebd652f8d3807d780642fc87Hemant Gupta            }
2704216387d9887926cebd652f8d3807d780642fc87Hemant Gupta
2714216387d9887926cebd652f8d3807d780642fc87Hemant Gupta            if (DEBUG) Log.d(TAG,"ACL disconnected for "+ device);
2724216387d9887926cebd652f8d3807d780642fc87Hemant Gupta
2734216387d9887926cebd652f8d3807d780642fc87Hemant Gupta            if (mRemoteDevice.equals(device)) {
2744216387d9887926cebd652f8d3807d780642fc87Hemant Gupta                Intent cancelIntent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL);
2754216387d9887926cebd652f8d3807d780642fc87Hemant Gupta                cancelIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
2764216387d9887926cebd652f8d3807d780642fc87Hemant Gupta                cancelIntent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
2774216387d9887926cebd652f8d3807d780642fc87Hemant Gupta                                      BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS);
2784216387d9887926cebd652f8d3807d780642fc87Hemant Gupta                sendBroadcast(cancelIntent);
279fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                mIsWaitingAuthorization = false;
2804216387d9887926cebd652f8d3807d780642fc87Hemant Gupta                stopObexServerSession();
2814216387d9887926cebd652f8d3807d780642fc87Hemant Gupta            }
2827eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie        } else if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY)) {
28370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            int requestType = intent.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
28470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                                           BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS);
28570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
286fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee            if ((!mIsWaitingAuthorization)
287fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    || (requestType != BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS)) {
2887eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                // this reply is not for us
2897eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                return;
2902c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
2917eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie
292fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee            mIsWaitingAuthorization = false;
2937eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie
2947eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie            if (intent.getIntExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT,
295fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                                   BluetoothDevice.CONNECTION_ACCESS_NO)
296fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    == BluetoothDevice.CONNECTION_ACCESS_YES) {
2977eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                if (intent.getBooleanExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, false)) {
298fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    boolean result = mRemoteDevice.setPhonebookAccessPermission(
299fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                            BluetoothDevice.ACCESS_ALLOWED);
300fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    if (VERBOSE) {
301fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        Log.v(TAG, "setPhonebookAccessPermission(ACCESS_ALLOWED) result=" + result);
302fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    }
3032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                }
3047eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                try {
3057eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                    if (mConnSocket != null) {
3067eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                        startObexServerSession();
3077eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                    } else {
3087eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                        stopObexServerSession();
3097eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                    }
3107eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                } catch (IOException ex) {
3117eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                    Log.e(TAG, "Caught the error: " + ex.toString());
3127eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                }
3137eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie            } else {
314fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                if (intent.getBooleanExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, false)) {
315fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    boolean result = mRemoteDevice.setPhonebookAccessPermission(
316fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                            BluetoothDevice.ACCESS_REJECTED);
317fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    if (VERBOSE) {
318fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        Log.v(TAG, "setPhonebookAccessPermission(ACCESS_REJECTED) result="
319fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                                + result);
320fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    }
321fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                }
3227eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                stopObexServerSession();
3232c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
324d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        } else if (action.equals(AUTH_RESPONSE_ACTION)) {
325d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            String sessionkey = intent.getStringExtra(EXTRA_SESSION_KEY);
3262c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            notifyAuthKeyInput(sessionkey);
327d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        } else if (action.equals(AUTH_CANCELLED_ACTION)) {
3282c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            notifyAuthCancelled();
3294446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        } else {
3304446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            removeTimeoutMsg = false;
3314446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
3324446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
3334446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (removeTimeoutMsg) {
3344446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            mSessionStatusHandler.removeMessages(USER_TIMEOUT);
3352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
3362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
3372c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
3382c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
3392c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public void onDestroy() {
3404446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (VERBOSE) Log.v(TAG, "Pbap Service onDestroy");
3414446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
3422c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        super.onDestroy();
34337b69bd05e4b7a7d0e43575a6c22734b2d8c3f69Jackson Fan        setState(BluetoothPbap.STATE_DISCONNECTED, BluetoothPbap.RESULT_CANCELED);
3448222c7902a2281929fd31e840f6012038e6fa44aLixin Yue        closeService();
3453fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mSessionStatusHandler != null) {
3463fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mSessionStatusHandler.removeCallbacksAndMessages(null);
3473fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        }
3482c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
3492c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
3502c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
3512c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public IBinder onBind(Intent intent) {
3524446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (VERBOSE) Log.v(TAG, "Pbap Service onBind");
35337b69bd05e4b7a7d0e43575a6c22734b2d8c3f69Jackson Fan        return mBinder;
3542c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
3552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
3564446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private void startRfcommSocketListener() {
3574446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (VERBOSE) Log.v(TAG, "Pbap Service startRfcommSocketListener");
3582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
3594446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (mAcceptThread == null) {
3604446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            mAcceptThread = new SocketAcceptThread();
3614446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            mAcceptThread.setName("BluetoothPbapAcceptThread");
3624446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            mAcceptThread.start();
3632c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
3642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
3652c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
3664446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private final boolean initSocket() {
3674446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (VERBOSE) Log.v(TAG, "Pbap Service initSocket");
3682c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
3697b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu        boolean initSocketOK = false;
3704446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        final int CREATE_RETRY_TIME = 10;
3712c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
3724446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        // It's possible that create will fail in some cases. retry for 10 times
3734446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        for (int i = 0; i < CREATE_RETRY_TIME && !mInterrupted; i++) {
3747b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu            initSocketOK = true;
3754446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            try {
3764446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                // It is mandatory for PSE to support initiation of bonding and
3774446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                // encryption.
3786458cffaca286611e898c75ad86e2d98c89008b6Matthew Xie                mServerSocket = mAdapter.listenUsingEncryptedRfcommWithServiceRecord
3796458cffaca286611e898c75ad86e2d98c89008b6Matthew Xie                    ("OBEX Phonebook Access Server", BluetoothUuid.PBAP_PSE.getUuid());
380e479e18951a375a548e617e86e3b1b7d121351a1Fred
3814446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            } catch (IOException e) {
3824446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                Log.e(TAG, "Error create RfcommServerSocket " + e.toString());
3834446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                initSocketOK = false;
3844446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
3854446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (!initSocketOK) {
38637e1e995fdfd6aecd53f1fd1f8f0928021472db1Kausik Sinnaswamy                // Need to break out of this loop if BT is being turned off.
38737e1e995fdfd6aecd53f1fd1f8f0928021472db1Kausik Sinnaswamy                if (mAdapter == null) break;
38837e1e995fdfd6aecd53f1fd1f8f0928021472db1Kausik Sinnaswamy                int state = mAdapter.getState();
38937e1e995fdfd6aecd53f1fd1f8f0928021472db1Kausik Sinnaswamy                if ((state != BluetoothAdapter.STATE_TURNING_ON) &&
39037e1e995fdfd6aecd53f1fd1f8f0928021472db1Kausik Sinnaswamy                    (state != BluetoothAdapter.STATE_ON)) {
39137e1e995fdfd6aecd53f1fd1f8f0928021472db1Kausik Sinnaswamy                    Log.w(TAG, "initServerSocket failed as BT is (being) turned off");
39237e1e995fdfd6aecd53f1fd1f8f0928021472db1Kausik Sinnaswamy                    break;
39337e1e995fdfd6aecd53f1fd1f8f0928021472db1Kausik Sinnaswamy                }
3947b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                try {
3957b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                    if (VERBOSE) Log.v(TAG, "wait 300 ms");
3967b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                    Thread.sleep(300);
3977b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                } catch (InterruptedException e) {
3987b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                    Log.e(TAG, "socketAcceptThread thread was interrupted (3)");
3997b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                    break;
4004446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                }
4014446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            } else {
4024446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                break;
4034446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
4044446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
4052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4067b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu        if (mInterrupted) {
4077b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu            initSocketOK = false;
4087b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu            // close server socket to avoid resource leakage
4097b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu            closeServerSocket();
4107b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu        }
4117b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu
4124446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (initSocketOK) {
4139f0d856f41d443ec23d5aa2eecfc561d7a3c01d1fredc            if (VERBOSE) Log.v(TAG, "Succeed to create listening socket ");
4142c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4154446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        } else {
4164446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            Log.e(TAG, "Error to create listening socket after " + CREATE_RETRY_TIME + " try");
4174446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
4184446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        return initSocketOK;
4192c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
4202c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4217b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu    private final synchronized void closeServerSocket() {
4227b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu        // exit SocketAcceptThread early
4237b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu        if (mServerSocket != null) {
4247b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu            try {
4257b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                // this will cause mServerSocket.accept() return early with IOException
4264446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                mServerSocket.close();
427ebdb4d92c0ea0b5e40afe0feec71105695d27a4czzy                mServerSocket = null;
4287b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu            } catch (IOException ex) {
4297b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                Log.e(TAG, "Close Server Socket error: " + ex);
4304446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
4312c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
4327b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu    }
4332c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4347b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu    private final synchronized void closeConnectionSocket() {
4357b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu        if (mConnSocket != null) {
4367b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu            try {
4374446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                mConnSocket.close();
438ebdb4d92c0ea0b5e40afe0feec71105695d27a4czzy                mConnSocket = null;
4397b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu            } catch (IOException e) {
4407b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                Log.e(TAG, "Close Connection Socket error: " + e.toString());
4414446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
4422c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
4432c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
4442c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4454446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private final void closeService() {
446ebdb4d92c0ea0b5e40afe0feec71105695d27a4czzy        if (VERBOSE) Log.v(TAG, "Pbap Service closeService in");
4474446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
4487b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu        // exit initSocket early
4497b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu        mInterrupted = true;
4507b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu        closeServerSocket();
4510eb2230d3b7c184a00599e8ab70331c599e9ef1cJaikumar Ganesh
4524446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (mAcceptThread != null) {
4534446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            try {
4544446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                mAcceptThread.shutdown();
4554446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                mAcceptThread.join();
4564446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                mAcceptThread = null;
4574446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            } catch (InterruptedException ex) {
4584446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                Log.w(TAG, "mAcceptThread close error" + ex);
4594446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
4604446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
4617b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu
4627b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu        if (mWakeLock != null) {
4637b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu            mWakeLock.release();
4647b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu            mWakeLock = null;
4657b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu        }
4667b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu
4674446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (mServerSession != null) {
4684446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            mServerSession.close();
4694446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            mServerSession = null;
4704446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
4714446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
4727b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu        closeConnectionSocket();
4737b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu
4744446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        mHasStarted = false;
475ebdb4d92c0ea0b5e40afe0feec71105695d27a4czzy        if (mStartId != -1 && stopSelfResult(mStartId)) {
4764446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (VERBOSE) Log.v(TAG, "successfully stopped pbap service");
477ebdb4d92c0ea0b5e40afe0feec71105695d27a4czzy            mStartId = -1;
4782c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
479ebdb4d92c0ea0b5e40afe0feec71105695d27a4czzy        if (VERBOSE) Log.v(TAG, "Pbap Service closeService out");
4802c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
4812c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4822c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private final void startObexServerSession() throws IOException {
4834446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (VERBOSE) Log.v(TAG, "Pbap Service startObexServerSession");
4844446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
4852c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        // acquire the wakeLock before start Obex transaction thread
4862c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (mWakeLock == null) {
4872c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
4882c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
4892c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    "StartingObexPbapTransaction");
4902c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            mWakeLock.setReferenceCounted(false);
4912c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            mWakeLock.acquire();
4922c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
4932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
4942c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (tm != null) {
4952c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            sLocalPhoneNum = tm.getLine1Number();
4962c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            sLocalPhoneName = tm.getLine1AlphaTag();
4972f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (TextUtils.isEmpty(sLocalPhoneName)) {
498cd5ed0c7d04119e508fbddfd9656ef8559e3e524Lixin Yue                sLocalPhoneName = this.getString(R.string.localPhoneName);
4992f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
5002c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
5012f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
5022f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        mPbapServer = new BluetoothPbapObexServer(mSessionStatusHandler, this);
5034446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        synchronized (this) {
5044446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            mAuth = new BluetoothPbapAuthenticator(mSessionStatusHandler);
5052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            mAuth.setChallenged(false);
5062c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            mAuth.setCancelled(false);
5072c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
508bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        BluetoothObexTransport transport = new BluetoothObexTransport(mConnSocket);
5092c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        mServerSession = new ServerSession(transport, mPbapServer, mAuth);
51037b69bd05e4b7a7d0e43575a6c22734b2d8c3f69Jackson Fan        setState(BluetoothPbap.STATE_CONNECTED);
5118fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu
5128fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu        mSessionStatusHandler.removeMessages(MSG_RELEASE_WAKE_LOCK);
5138fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu        mSessionStatusHandler.sendMessageDelayed(mSessionStatusHandler
5148fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu            .obtainMessage(MSG_RELEASE_WAKE_LOCK), RELEASE_WAKE_LOCK_DELAY);
5158fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu
5164446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (VERBOSE) {
517acab258c177d82338b1696360cd0b8c9821b0f03Lixin Yue            Log.v(TAG, "startObexServerSession() success!");
518acab258c177d82338b1696360cd0b8c9821b0f03Lixin Yue        }
5192c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
5202c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
5214446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private void stopObexServerSession() {
5224446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (VERBOSE) Log.v(TAG, "Pbap Service stopObexServerSession");
5232c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
5248fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu        mSessionStatusHandler.removeMessages(MSG_ACQUIRE_WAKE_LOCK);
5258fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu        mSessionStatusHandler.removeMessages(MSG_RELEASE_WAKE_LOCK);
5264446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        // Release the wake lock if obex transaction is over
5274446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (mWakeLock != null) {
5284446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            mWakeLock.release();
5294446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            mWakeLock = null;
5302c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
5312c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
5322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (mServerSession != null) {
5332c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            mServerSession.close();
5342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            mServerSession = null;
5352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
5362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
5372c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        mAcceptThread = null;
5384446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
5397b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu        closeConnectionSocket();
5407b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu
5414446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        // Last obex transaction is finished, we start to listen for incoming
5422c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        // connection again
54341ef8d494511c040451f2f887cb31c3100746b61Nick Pelly        if (mAdapter.isEnabled()) {
5449f0d856f41d443ec23d5aa2eecfc561d7a3c01d1fredc            startRfcommSocketListener();
5452c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
54637b69bd05e4b7a7d0e43575a6c22734b2d8c3f69Jackson Fan        setState(BluetoothPbap.STATE_DISCONNECTED);
5472c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
5482c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
5494446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private void notifyAuthKeyInput(final String key) {
5502f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        synchronized (mAuth) {
5512f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (key != null) {
5522f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                mAuth.setSessionKey(key);
5532f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
5544446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            mAuth.setChallenged(true);
5554446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            mAuth.notify();
5564446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
5574446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
5584446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
5594446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private void notifyAuthCancelled() {
5602f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        synchronized (mAuth) {
5614446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            mAuth.setCancelled(true);
5624446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            mAuth.notify();
5634446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
5644446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
5654446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
5662c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /**
5672c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * A thread that runs in the background waiting for remote rfcomm
5682c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * connect.Once a remote socket connected, this thread shall be
5692c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * shutdown.When the remote disconnect,this thread shall run again waiting
5702c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * for next request.
5712c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     */
5722c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private class SocketAcceptThread extends Thread {
5732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
5742c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        private boolean stopped = false;
5752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
5762c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        @Override
5772c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public void run() {
5787b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu            BluetoothServerSocket serverSocket;
5796458cffaca286611e898c75ad86e2d98c89008b6Matthew Xie            if (mServerSocket == null) {
5806458cffaca286611e898c75ad86e2d98c89008b6Matthew Xie                if (!initSocket()) {
5816458cffaca286611e898c75ad86e2d98c89008b6Matthew Xie                    return;
5826458cffaca286611e898c75ad86e2d98c89008b6Matthew Xie                }
5836458cffaca286611e898c75ad86e2d98c89008b6Matthew Xie            }
5846458cffaca286611e898c75ad86e2d98c89008b6Matthew Xie
5852c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            while (!stopped) {
5862c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                try {
5879f0d856f41d443ec23d5aa2eecfc561d7a3c01d1fredc                    if (VERBOSE) Log.v(TAG, "Accepting socket connection...");
5887b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                    serverSocket = mServerSocket;
5897b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                    if (serverSocket == null) {
5907b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                        Log.w(TAG, "mServerSocket is null");
5917b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                        break;
5927b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                    }
5937b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                    mConnSocket = serverSocket.accept();
5949f0d856f41d443ec23d5aa2eecfc561d7a3c01d1fredc                    if (VERBOSE) Log.v(TAG, "Accepted socket connection...");
5954446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
5967b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                    synchronized (BluetoothPbapService.this) {
5977b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                        if (mConnSocket == null) {
5987b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                            Log.w(TAG, "mConnSocket is null");
5997b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                            break;
6007b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                        }
6017b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                        mRemoteDevice = mConnSocket.getRemoteDevice();
6027b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                    }
6038222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                    if (mRemoteDevice == null) {
6048222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                        Log.i(TAG, "getRemoteDevice() = null");
6058222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                        break;
6068222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                    }
6078222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                    sRemoteDeviceName = mRemoteDevice.getName();
6088222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                    // In case getRemoteName failed and return null
6098222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                    if (TextUtils.isEmpty(sRemoteDeviceName)) {
6108222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                        sRemoteDeviceName = getString(R.string.defaultname);
6112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    }
612fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    int permission = mRemoteDevice.getPhonebookAccessPermission();
613fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    if (VERBOSE) Log.v(TAG, "getPhonebookAccessPermission() = " + permission);
614c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue
615fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    if (permission == BluetoothDevice.ACCESS_ALLOWED) {
6162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        try {
617fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                            if (VERBOSE) {
618fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                                Log.v(TAG, "incoming connection accepted from: " + sRemoteDeviceName
619fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                                        + " automatically as already allowed device");
620fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                            }
6212c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                            startObexServerSession();
6222c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        } catch (IOException ex) {
623fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                            Log.e(TAG, "Caught exception starting obex server session"
6242c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                                    + ex.toString());
6252c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        }
626fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    } else if (permission == BluetoothDevice.ACCESS_REJECTED) {
627fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        if (VERBOSE) {
628fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                            Log.v(TAG, "incoming connection rejected from: " + sRemoteDeviceName
629fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                                    + " automatically as already rejected device");
630fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        }
631fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        stopObexServerSession();
632fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    } else {  // permission == BluetoothDevice.ACCESS_UNKNOWN
633fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        // Send an Intent to Settings app to ask user preference.
634fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        Intent intent =
635fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                                new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST);
6367eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                        intent.setClassName(ACCESS_AUTHORITY_PACKAGE, ACCESS_AUTHORITY_CLASS);
6377eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                        intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
6387eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                                        BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS);
6397eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
6407eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                        intent.putExtra(BluetoothDevice.EXTRA_PACKAGE_NAME, getPackageName());
6417eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                        intent.putExtra(BluetoothDevice.EXTRA_CLASS_NAME,
6427eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                                        BluetoothPbapReceiver.class.getName());
64398df3e8ff33a6137d4ea13845b583aaee2670613Casper Bonde
644fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        mIsWaitingAuthorization = true;
645beb0497605ef61062d0565d85897f4c842845a8fAng Li                        sendOrderedBroadcast(intent, BLUETOOTH_ADMIN_PERM);
6467eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie
6477eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                        if (VERBOSE) Log.v(TAG, "waiting for authorization for connection from: "
6484446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                                + sRemoteDeviceName);
6494446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
6504446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                        // In case car kit time out and try to use HFP for
6514446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                        // phonebook
6524446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                        // access, while UI still there waiting for user to
6534446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                        // confirm
6542c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        mSessionStatusHandler.sendMessageDelayed(mSessionStatusHandler
6552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                                .obtainMessage(USER_TIMEOUT), USER_CONFIRM_TIMEOUT_VALUE);
656fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        // We will continue the process when we receive
657fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        // BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY from Settings app.
6582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    }
6592c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    stopped = true; // job done ,close this thread;
6604446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                } catch (IOException ex) {
6616654f5c903de510a70f9e72cd5ad7837b615d93ffredc                    stopped=true;
6626654f5c903de510a70f9e72cd5ad7837b615d93ffredc                    /*
6634446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    if (stopped) {
6644446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                        break;
6654446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    }
6666654f5c903de510a70f9e72cd5ad7837b615d93ffredc                    */
6674446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    if (VERBOSE) Log.v(TAG, "Accept exception: " + ex.toString());
6682c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                }
6692c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
6702c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
6712c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
6722c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        void shutdown() {
6732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            stopped = true;
6742c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            interrupt();
6752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
6762c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
6772c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
6784446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private final Handler mSessionStatusHandler = new Handler() {
6794446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        @Override
6804446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        public void handleMessage(Message msg) {
6814446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (VERBOSE) Log.v(TAG, "Handler(): got msg=" + msg.what);
6824446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
6834446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            switch (msg.what) {
6844446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                case START_LISTENER:
6854446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    if (mAdapter.isEnabled()) {
6869f0d856f41d443ec23d5aa2eecfc561d7a3c01d1fredc                        startRfcommSocketListener();
6874446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    } else {
6884446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                        closeService();// release all resources
6894446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    }
6904446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    break;
6914446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                case USER_TIMEOUT:
6927eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie                    Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL);
6934216387d9887926cebd652f8d3807d780642fc87Hemant Gupta                    intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
69470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                    intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
69570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                                    BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS);
6964446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    sendBroadcast(intent);
697fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    mIsWaitingAuthorization = false;
6984446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    stopObexServerSession();
6994446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    break;
7004446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                case AUTH_TIMEOUT:
7014446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    Intent i = new Intent(USER_CONFIRM_TIMEOUT_ACTION);
7024446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    sendBroadcast(i);
7034446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    removePbapNotification(NOTIFICATION_ID_AUTH);
7044446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    notifyAuthCancelled();
7054446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    break;
7064446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                case MSG_SERVERSESSION_CLOSE:
7074446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    stopObexServerSession();
7084446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    break;
7094446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                case MSG_SESSION_ESTABLISHED:
7104446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    break;
7114446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                case MSG_SESSION_DISCONNECTED:
7124446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    // case MSG_SERVERSESSION_CLOSE will handle ,so just skip
7134446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    break;
7144446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                case MSG_OBEX_AUTH_CHALL:
7154446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    createPbapNotification(AUTH_CHALL_ACTION);
7164446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    mSessionStatusHandler.sendMessageDelayed(mSessionStatusHandler
7174446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                            .obtainMessage(AUTH_TIMEOUT), USER_CONFIRM_TIMEOUT_VALUE);
7184446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    break;
7198fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                case MSG_ACQUIRE_WAKE_LOCK:
7208fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                    if (mWakeLock == null) {
7218fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                        PowerManager pm = (PowerManager)getSystemService(
7228fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                                          Context.POWER_SERVICE);
7238fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
7248fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                                    "StartingObexPbapTransaction");
7258fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                        mWakeLock.setReferenceCounted(false);
7268fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                        mWakeLock.acquire();
7278fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                        Log.w(TAG, "Acquire Wake Lock");
7288fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                    }
7298fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                    mSessionStatusHandler.removeMessages(MSG_RELEASE_WAKE_LOCK);
7308fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                    mSessionStatusHandler.sendMessageDelayed(mSessionStatusHandler
7318fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                      .obtainMessage(MSG_RELEASE_WAKE_LOCK), RELEASE_WAKE_LOCK_DELAY);
7328fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                    break;
7338fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                case MSG_RELEASE_WAKE_LOCK:
7348fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                    if (mWakeLock != null) {
7358fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                        mWakeLock.release();
7368fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                        mWakeLock = null;
7378fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                        Log.w(TAG, "Release Wake Lock");
7388fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                    }
7398fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu                    break;
7404446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                default:
7414446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    break;
7422c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
7432c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
7444446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    };
7452c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
7462c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private void setState(int state) {
747d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        setState(state, BluetoothPbap.RESULT_SUCCESS);
7482c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
7492c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
75037b69bd05e4b7a7d0e43575a6c22734b2d8c3f69Jackson Fan    private synchronized void setState(int state, int result) {
75137b69bd05e4b7a7d0e43575a6c22734b2d8c3f69Jackson Fan        if (state != mState) {
7524446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (DEBUG) Log.d(TAG, "Pbap state " + mState + " -> " + state + ", result = "
7534446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    + result);
754cab07635ea60924a4e9dc13f87a4408988ad4c57Jaikumar Ganesh            int prevState = mState;
75537b69bd05e4b7a7d0e43575a6c22734b2d8c3f69Jackson Fan            mState = state;
756cab07635ea60924a4e9dc13f87a4408988ad4c57Jaikumar Ganesh            Intent intent = new Intent(BluetoothPbap.PBAP_STATE_CHANGED_ACTION);
757cab07635ea60924a4e9dc13f87a4408988ad4c57Jaikumar Ganesh            intent.putExtra(BluetoothPbap.PBAP_PREVIOUS_STATE, prevState);
75837b69bd05e4b7a7d0e43575a6c22734b2d8c3f69Jackson Fan            intent.putExtra(BluetoothPbap.PBAP_STATE, mState);
759f2c447b81c6c03cb1c8a3e64a10381e23934834aNick Pelly            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
76037b69bd05e4b7a7d0e43575a6c22734b2d8c3f69Jackson Fan            sendBroadcast(intent, BLUETOOTH_PERM);
761b5cc776c9353a203cdde97e62b25f05d9633d14cfredc            AdapterService s = AdapterService.getAdapterService();
762b5cc776c9353a203cdde97e62b25f05d9633d14cfredc            if (s != null) {
763b5cc776c9353a203cdde97e62b25f05d9633d14cfredc                s.onProfileConnectionStateChanged(mRemoteDevice, BluetoothProfile.PBAP,
764b5cc776c9353a203cdde97e62b25f05d9633d14cfredc                        mState, prevState);
765b5cc776c9353a203cdde97e62b25f05d9633d14cfredc            }
76637b69bd05e4b7a7d0e43575a6c22734b2d8c3f69Jackson Fan        }
76737b69bd05e4b7a7d0e43575a6c22734b2d8c3f69Jackson Fan    }
7682c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
7694446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private void createPbapNotification(String action) {
7704446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
7710bd5f7b5c36a60687ffe895368fd8df6df38acabJaikumar Ganesh        NotificationManager nm = (NotificationManager)
7720bd5f7b5c36a60687ffe895368fd8df6df38acabJaikumar Ganesh            getSystemService(Context.NOTIFICATION_SERVICE);
7734446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
7744446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        // Create an intent triggered by clicking on the status icon.
7754446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        Intent clickIntent = new Intent();
7760bd5f7b5c36a60687ffe895368fd8df6df38acabJaikumar Ganesh        clickIntent.setClass(this, BluetoothPbapActivity.class);
7774446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        clickIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7784446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        clickIntent.setAction(action);
7794446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
7804446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        // Create an intent triggered by clicking on the
7814446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        // "Clear All Notifications" button
7824446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        Intent deleteIntent = new Intent();
7830bd5f7b5c36a60687ffe895368fd8df6df38acabJaikumar Ganesh        deleteIntent.setClass(this, BluetoothPbapReceiver.class);
7844446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
7854446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        Notification notification = null;
7864446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        String name = getRemoteDeviceName();
7870bd5f7b5c36a60687ffe895368fd8df6df38acabJaikumar Ganesh
7887eab97d6be9228b1c210bbb171c3e5e88e02f3d8Matthew Xie        if (action.equals(AUTH_CHALL_ACTION)) {
7894446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            deleteIntent.setAction(AUTH_CANCELLED_ACTION);
7900bd5f7b5c36a60687ffe895368fd8df6df38acabJaikumar Ganesh            notification = new Notification(android.R.drawable.stat_sys_data_bluetooth,
7910bd5f7b5c36a60687ffe895368fd8df6df38acabJaikumar Ganesh                getString(R.string.auth_notif_ticker), System.currentTimeMillis());
7920ce48bf302e010af811c903f8a986df567562ecfSelim Cinek            notification.color = getResources().getColor(
7930ce48bf302e010af811c903f8a986df567562ecfSelim Cinek                    com.android.internal.R.color.system_notification_accent_color);
7940bd5f7b5c36a60687ffe895368fd8df6df38acabJaikumar Ganesh            notification.setLatestEventInfo(this, getString(R.string.auth_notif_title),
7950bd5f7b5c36a60687ffe895368fd8df6df38acabJaikumar Ganesh                    getString(R.string.auth_notif_message, name), PendingIntent
7960bd5f7b5c36a60687ffe895368fd8df6df38acabJaikumar Ganesh                            .getActivity(this, 0, clickIntent, 0));
7974446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
7984446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            notification.flags |= Notification.FLAG_AUTO_CANCEL;
799c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            notification.flags |= Notification.FLAG_ONLY_ALERT_ONCE;
800c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            notification.defaults = Notification.DEFAULT_SOUND;
8010bd5f7b5c36a60687ffe895368fd8df6df38acabJaikumar Ganesh            notification.deleteIntent = PendingIntent.getBroadcast(this, 0, deleteIntent, 0);
8024446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            nm.notify(NOTIFICATION_ID_AUTH, notification);
8034446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
8044446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
8054446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
8064446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private void removePbapNotification(int id) {
8070bd5f7b5c36a60687ffe895368fd8df6df38acabJaikumar Ganesh        NotificationManager nm = (NotificationManager)
8080bd5f7b5c36a60687ffe895368fd8df6df38acabJaikumar Ganesh            getSystemService(Context.NOTIFICATION_SERVICE);
8094446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        nm.cancel(id);
8104446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
8114446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
8124446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    public static String getLocalPhoneNum() {
8134446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        return sLocalPhoneNum;
8144446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
8154446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
8164446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    public static String getLocalPhoneName() {
8174446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        return sLocalPhoneName;
8184446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
8194446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
8204446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    public static String getRemoteDeviceName() {
8214446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        return sRemoteDeviceName;
8224446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
8234446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
8242c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /**
8252c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * Handlers for incoming service calls
8262c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     */
8272c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private final IBluetoothPbap.Stub mBinder = new IBluetoothPbap.Stub() {
8282c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public int getState() {
8294446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (DEBUG) Log.d(TAG, "getState " + mState);
8304446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
83137510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            if (!Utils.checkCaller()) {
83237510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu                Log.w(TAG,"getState(): not allowed for non-active user");
83337510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu                return BluetoothPbap.STATE_DISCONNECTED;
83437510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            }
83537510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu
8362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
8372c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return mState;
8382c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
8392c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
84041ef8d494511c040451f2f887cb31c3100746b61Nick Pelly        public BluetoothDevice getClient() {
8414446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (DEBUG) Log.d(TAG, "getClient" + mRemoteDevice);
8424446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
84337510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            if (!Utils.checkCaller()) {
84437510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu                Log.w(TAG,"getClient(): not allowed for non-active user");
84537510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu                return null;
84637510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            }
84737510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu
8482c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
8492c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            if (mState == BluetoothPbap.STATE_DISCONNECTED) {
8502c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                return null;
8512c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
85241ef8d494511c040451f2f887cb31c3100746b61Nick Pelly            return mRemoteDevice;
8532c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
8542c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
85541ef8d494511c040451f2f887cb31c3100746b61Nick Pelly        public boolean isConnected(BluetoothDevice device) {
85637510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            if (!Utils.checkCaller()) {
85737510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu                Log.w(TAG,"isConnected(): not allowed for non-active user");
85837510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu                return false;
85937510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            }
86037510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu
8612c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
86241ef8d494511c040451f2f887cb31c3100746b61Nick Pelly            return mState == BluetoothPbap.STATE_CONNECTED && mRemoteDevice.equals(device);
8632c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
8642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
86541ef8d494511c040451f2f887cb31c3100746b61Nick Pelly        public boolean connect(BluetoothDevice device) {
86637510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            if (!Utils.checkCaller()) {
86737510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu                Log.w(TAG,"connect(): not allowed for non-active user");
86837510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu                return false;
86937510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            }
87037510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu
871d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
872d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                    "Need BLUETOOTH_ADMIN permission");
8732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return false;
8742c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
8752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
87641ef8d494511c040451f2f887cb31c3100746b61Nick Pelly        public void disconnect() {
8774446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (DEBUG) Log.d(TAG, "disconnect");
8784446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
87937510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            if (!Utils.checkCaller()) {
88037510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu                Log.w(TAG,"disconnect(): not allowed for non-active user");
88137510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu                return;
88237510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            }
88337510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu
884d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
885d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                    "Need BLUETOOTH_ADMIN permission");
8862c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            synchronized (BluetoothPbapService.this) {
8872c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                switch (mState) {
8882c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    case BluetoothPbap.STATE_CONNECTED:
8892c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        if (mServerSession != null) {
8902c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                            mServerSession.close();
8912c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                            mServerSession = null;
8922c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        }
8937b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu
8947b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu                        closeConnectionSocket();
8957b91a410d595b879548e540889f8b30a0d6476c4Zhihai Xu
8962c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        setState(BluetoothPbap.STATE_DISCONNECTED, BluetoothPbap.RESULT_CANCELED);
8972c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        break;
8984446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    default:
8994446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                        break;
9002c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                }
9012c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
9022c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
9032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    };
9042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan}
905