diff options
author | Steve Kondik <steve@cyngn.com> | 2016-03-30 11:51:31 -0700 |
---|---|---|
committer | Steve Kondik <steve@cyngn.com> | 2016-03-30 11:51:31 -0700 |
commit | 8c5b9feba472e4532b6d151a402c8ad3ebd947a7 (patch) | |
tree | 709589743ad8fd9e3dcfa2b0dbb5f8ba981ac16e | |
parent | d7199f6c73b0c927f694967163f33257d6e5199f (diff) | |
parent | e6fae29795ff64060044d89bb6213f13042008ff (diff) | |
download | android_packages_apps_Bluetooth-8c5b9feba472e4532b6d151a402c8ad3ebd947a7.tar.gz android_packages_apps_Bluetooth-8c5b9feba472e4532b6d151a402c8ad3ebd947a7.tar.bz2 android_packages_apps_Bluetooth-8c5b9feba472e4532b6d151a402c8ad3ebd947a7.zip |
Merge branch 'LA.BF.1.1.3_rb1.11' of git://codeaurora.org/platform/packages/apps/Bluetooth into cm-13.0
-rw-r--r-- | src/com/android/bluetooth/OolConnManager.java | 9 | ||||
-rw-r--r-- | src/com/android/bluetooth/hfp/HeadsetStateMachine.java | 10 | ||||
-rw-r--r-- | src/com/android/bluetooth/map/BluetoothMapContent.java | 2 | ||||
-rw-r--r-- | src/com/android/bluetooth/map/BluetoothMapContentEmail.java | 2 | ||||
-rw-r--r-- | src/com/android/bluetooth/map/BluetoothMapContentObserver.java | 3 | ||||
-rw-r--r-- | src/com/android/bluetooth/map/BluetoothMapMasInstance.java | 16 | ||||
-rwxr-xr-x[-rw-r--r--] | src/com/android/bluetooth/map/BluetoothMapService.java | 105 | ||||
-rw-r--r-- | src/com/android/bluetooth/opp/BluetoothOppL2capListener.java | 10 | ||||
-rw-r--r-- | src/com/android/bluetooth/opp/BluetoothOppService.java | 82 | ||||
-rw-r--r-- | src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java | 59 | ||||
-rw-r--r-- | src/com/android/bluetooth/sap/SapServer.java | 37 | ||||
-rw-r--r-- | src/com/android/bluetooth/sap/SapService.java | 99 |
12 files changed, 287 insertions, 147 deletions
diff --git a/src/com/android/bluetooth/OolConnManager.java b/src/com/android/bluetooth/OolConnManager.java index 458d39d93..3609c53b3 100644 --- a/src/com/android/bluetooth/OolConnManager.java +++ b/src/com/android/bluetooth/OolConnManager.java @@ -54,7 +54,10 @@ public class OolConnManager { public static void setSdpInitiatedAddress(BluetoothDevice remBtDev) { - mAddress = remBtDev.getAddress(); + if (remBtDev != null) + mAddress = remBtDev.getAddress(); + else + mAddress = null; Log.d(TAG,"setSdpInitiatedAddress "+ mAddress); } @@ -63,9 +66,9 @@ public class OolConnManager { int waitCount = 0; int channelNo = -1; - while(!sdpDone && waitCount < 20) { + while(!sdpDone && waitCount < 100) { try { - Thread.sleep(500); + Thread.sleep(100); } catch (InterruptedException e) { Log.e(TAG, "Interrupted", e); } diff --git a/src/com/android/bluetooth/hfp/HeadsetStateMachine.java b/src/com/android/bluetooth/hfp/HeadsetStateMachine.java index d7bf4a85d..bacdaf82d 100644 --- a/src/com/android/bluetooth/hfp/HeadsetStateMachine.java +++ b/src/com/android/bluetooth/hfp/HeadsetStateMachine.java @@ -832,11 +832,6 @@ final class HeadsetStateMachine extends StateMachine { private class Connected extends State { @Override public void enter() { - // Remove pending connection attempts that were deferred during the pending - // state. This is to prevent auto connect attempts from disconnecting - // devices that previously successfully connected. - // TODO: This needs to check for multiple HFP connections, once supported... - removeDeferredMessages(CONNECT); Log.d(TAG, "Enter Connected: " + getCurrentMessage().what + ", size: " + mConnectedDevicesList.size()); // start phone state listener here so that the CIND response as part of SLC can be @@ -3129,11 +3124,6 @@ final class HeadsetStateMachine extends StateMachine { } atResponseCodeNative(HeadsetHalConstants.AT_RESPONSE_OK, 0, getByteAddress(device)); - removeMessages(DIALING_OUT_TIMEOUT); - } else if (callState.mCallState == - HeadsetHalConstants.CALL_STATE_ACTIVE || callState.mCallState - == HeadsetHalConstants.CALL_STATE_IDLE) { - mDialingOut = false; } /* Set ActiveScoDevice to null when call ends */ diff --git a/src/com/android/bluetooth/map/BluetoothMapContent.java b/src/com/android/bluetooth/map/BluetoothMapContent.java index 62c90a9bc..2d27c6b87 100644 --- a/src/com/android/bluetooth/map/BluetoothMapContent.java +++ b/src/com/android/bluetooth/map/BluetoothMapContent.java @@ -1242,6 +1242,8 @@ public class BluetoothMapContent { } if (subject != null && subject.length() > subLength) { subject = subject.substring(0, subLength); + } else if (subject == null ) { + subject = ""; } if (V) Log.d(TAG, "setSubject: " + subject); e.setSubject(subject); diff --git a/src/com/android/bluetooth/map/BluetoothMapContentEmail.java b/src/com/android/bluetooth/map/BluetoothMapContentEmail.java index 32864f3cb..da0287e11 100644 --- a/src/com/android/bluetooth/map/BluetoothMapContentEmail.java +++ b/src/com/android/bluetooth/map/BluetoothMapContentEmail.java @@ -688,6 +688,8 @@ public class BluetoothMapContentEmail extends BluetoothMapContent { } if (subject != null && subject.length() > subLength) { subject = subject.substring(0, subLength); + } else if(subject == null ) { + subject = ""; } if (V) Log.d(TAG, "setSubject: " + subject); e.setSubject(subject); diff --git a/src/com/android/bluetooth/map/BluetoothMapContentObserver.java b/src/com/android/bluetooth/map/BluetoothMapContentObserver.java index 1a51d29ee..92899c23a 100644 --- a/src/com/android/bluetooth/map/BluetoothMapContentObserver.java +++ b/src/com/android/bluetooth/map/BluetoothMapContentObserver.java @@ -469,8 +469,7 @@ public class BluetoothMapContentObserver { return smsType; } - private final ContentObserver mObserver = new ContentObserver( - new Handler(Looper.getMainLooper())) { + private final ContentObserver mObserver = new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { onChange(selfChange, null); diff --git a/src/com/android/bluetooth/map/BluetoothMapMasInstance.java b/src/com/android/bluetooth/map/BluetoothMapMasInstance.java index 3ebcde96d..4cc371883 100644 --- a/src/com/android/bluetooth/map/BluetoothMapMasInstance.java +++ b/src/com/android/bluetooth/map/BluetoothMapMasInstance.java @@ -277,10 +277,13 @@ public class BluetoothMapMasInstance implements IObexConnectionHandler { Log.e(TAG, "Failed to start the listeners"); return; } - if(mSdpHandle >= 0) { - SdpManager.getDefaultManager().removeSdpRecord(mSdpHandle); + if (mAdapter != null && mSdpHandle >= 0 && + SdpManager.getDefaultManager() != null) { if(V) Log.d(TAG, "Removing SDP record for MAS instance: " + mMasInstanceId + " Object reference: " + this + "SDP handle: " + mSdpHandle); + boolean status = SdpManager.getDefaultManager().removeSdpRecord(mSdpHandle); + Log.d(TAG, "RemoveSDPrecord returns " + status); + mSdpHandle = -1; } mSdpHandle = createMasSdpRecord(mServerSockets.getRfcommChannel(), mServerSockets.getL2capPsm()); @@ -396,7 +399,7 @@ public class BluetoothMapMasInstance implements IObexConnectionHandler { return (mConnSocket != null); } - public void shutdown() { + public synchronized void shutdown() { if (D) Log.d(TAG, "MAP Service shutdown"); if (mServerSession != null) { @@ -407,10 +410,13 @@ public class BluetoothMapMasInstance implements IObexConnectionHandler { mObserver.deinit(); mObserver = null; } - if (mSdpHandle >= 0) { - SdpManager.getDefaultManager().removeSdpRecord(mSdpHandle); + if (mAdapter != null && mSdpHandle >= 0 && + SdpManager.getDefaultManager() != null) { if(V) Log.d(TAG, "Removing SDP record for MAS instance: " + mMasInstanceId + " Object reference: " + this + "SDP handle: " + mSdpHandle); + boolean status = SdpManager.getDefaultManager().removeSdpRecord(mSdpHandle); + Log.d(TAG, "RemoveSDPrecord returns " + status); + mSdpHandle = -1; } closeConnectionSocket(); diff --git a/src/com/android/bluetooth/map/BluetoothMapService.java b/src/com/android/bluetooth/map/BluetoothMapService.java index 8cf69f601..743c1b924 100644..100755 --- a/src/com/android/bluetooth/map/BluetoothMapService.java +++ b/src/com/android/bluetooth/map/BluetoothMapService.java @@ -30,6 +30,8 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.IntentFilter.MalformedMimeTypeException; import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; import android.os.Message; import android.os.ParcelUuid; import android.os.PowerManager; @@ -50,6 +52,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Set; +import java.util.concurrent.CountDownLatch; public class BluetoothMapService extends ProfileService { private static final String TAG = "BluetoothMapService"; @@ -65,7 +68,6 @@ public class BluetoothMapService extends ProfileService { public static final boolean DEBUG = true; //FIXME set to false; public static boolean VERBOSE = Log.isLoggable(LOG_TAG, Log.VERBOSE); - /** * Intent indicating timeout for user confirmation, which is sent to * BluetoothMapActivity @@ -142,10 +144,12 @@ public class BluetoothMapService extends ProfileService { private boolean mIsWaitingAuthorization = false; private boolean mRemoveTimeoutMsg = false; + private boolean mRegisteredMapReceiver = false; private int mPermission = BluetoothDevice.ACCESS_UNKNOWN; private boolean mAccountChanged = false; private boolean mSdpSearchInitiated = false; SdpMnsRecord mMnsRecord = null; + private MapServiceMessageHandler mSessionStatusHandler; // package and class name to which we send intent to check phone book access permission private static final String ACCESS_AUTHORITY_PACKAGE = "com.android.settings"; @@ -163,7 +167,7 @@ public class BluetoothMapService extends ProfileService { } - private final void closeService() { + private synchronized void closeService(CountDownLatch latch) { if (DEBUG) Log.d(TAG, "MAP Service closeService in"); if (mBluetoothMnsObexClient != null) { @@ -191,7 +195,10 @@ public class BluetoothMapService extends ProfileService { } mRemoteDevice = null; - if (VERBOSE) Log.v(TAG, "MAP Service closeService out"); + if (DEBUG) Log.d(TAG, "MAP Service closeService out"); + if(latch != null) { + latch.countDown(); + } } /** @@ -226,7 +233,7 @@ public class BluetoothMapService extends ProfileService { "StartingObexMapTransaction"); mWakeLock.setReferenceCounted(false); mWakeLock.acquire(); - if (VERBOSE) Log.v(TAG, "startObexSessions(): Acquire Wake Lock"); + if (DEBUG) Log.d(TAG, "startObexSessions(): Acquire Wake Lock"); } if(mBluetoothMnsObexClient == null) { @@ -259,7 +266,7 @@ public class BluetoothMapService extends ProfileService { mSessionStatusHandler.sendMessageDelayed(mSessionStatusHandler .obtainMessage(MSG_RELEASE_WAKE_LOCK), RELEASE_WAKE_LOCK_DELAY); - if (VERBOSE) Log.v(TAG, "startObexServerSessions() success!"); + if (DEBUG) Log.d(TAG, "startObexServerSessions() success!"); } public Handler getHandler() { @@ -317,10 +324,13 @@ public class BluetoothMapService extends ProfileService { } } - private final Handler mSessionStatusHandler = new Handler() { + private final class MapServiceMessageHandler extends Handler { + private MapServiceMessageHandler(Looper looper) { + super(looper); + } @Override public void handleMessage(Message msg) { - if (DEBUG) Log.v(TAG, "Handler(): got msg=" + msg.what); + if (DEBUG) Log.d(TAG, "Handler(): got msg=" + msg.what); switch (msg.what) { case UPDATE_MAS_INSTANCES: @@ -369,7 +379,8 @@ public class BluetoothMapService extends ProfileService { case SHUTDOWN: /* Ensure to call close from this handler to avoid starting new stuff because of pending messages */ - closeService(); + CountDownLatch latch = (CountDownLatch) msg.obj; + closeService(latch); break; case MSG_ACQUIRE_WAKE_LOCK: if (VERBOSE) Log.v(TAG, "Acquire Wake Lock request message"); @@ -580,6 +591,12 @@ public class BluetoothMapService extends ProfileService { } if (VERBOSE) Log.v(TAG, "verbose logging is enabled"); + + HandlerThread thread = new HandlerThread("BluetoothMapHandler"); + thread.start(); + Looper looper = thread.getLooper(); + mSessionStatusHandler = new MapServiceMessageHandler(looper); + IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); @@ -596,12 +613,14 @@ public class BluetoothMapService extends ProfileService { } catch (MalformedMimeTypeException e) { Log.e(TAG, "Wrong mime type!!!", e); } - - try { - registerReceiver(mMapReceiver, filter); - registerReceiver(mMapReceiver, filterMessageSent); - } catch (Exception e) { - Log.w(TAG,"Unable to register map receiver",e); + if (!mRegisteredMapReceiver) { + try { + registerReceiver(mMapReceiver, filter); + registerReceiver(mMapReceiver, filterMessageSent); + mRegisteredMapReceiver = true; + } catch (Exception e) { + Log.e(TAG,"Unable to register map receiver",e); + } } mAdapter = BluetoothAdapter.getDefaultAdapter(); mAppObserver = new BluetoothMapAppObserver(this, this); @@ -769,15 +788,35 @@ public class BluetoothMapService extends ProfileService { @Override protected boolean stop() { if (DEBUG) Log.d(TAG, "stop()"); + if (mRegisteredMapReceiver) { + try { + mRegisteredMapReceiver = false; + unregisterReceiver(mMapReceiver); + mAppObserver.shutdown(); + } catch (Exception e) { + Log.e(TAG,"Unable to unregister map receiver",e); + } + } + CountDownLatch latch = new CountDownLatch(1); + sendShutdownMessage(latch); + // We need to wait for shutdown to complete to avoid being garbage collected before + // shutdown completes. + if(DEBUG) Log.i(TAG, "Waiting for shutdown to complete"); try { - unregisterReceiver(mMapReceiver); - mAppObserver.shutdown(); - } catch (Exception e) { - Log.w(TAG,"Unable to unregister map receiver",e); + latch.await(); + } catch (InterruptedException e) { + Log.e(TAG, "Interrupt received while waiting for shutdown to complete", e); + } + if (mSessionStatusHandler != null) { + mSessionStatusHandler.removeCallbacksAndMessages(null); + Looper looper = mSessionStatusHandler.getLooper(); + if (looper != null) { + looper.quit(); + } + mSessionStatusHandler = null; } - setState(BluetoothMap.STATE_DISCONNECTED, BluetoothMap.RESULT_CANCELED); - sendShutdownMessage(); + if (DEBUG) Log.d(TAG, "stop() out"); return true; } @@ -785,7 +824,7 @@ public class BluetoothMapService extends ProfileService { if (DEBUG) Log.d(TAG, "cleanup()"); setState(BluetoothMap.STATE_DISCONNECTED, BluetoothMap.RESULT_CANCELED); // TODO: Change to use message? - do we need to wait for completion? - closeService(); + closeService(null); // Stop() should be called to handle cleanup - hence this is not needed return true; } @@ -911,7 +950,7 @@ public class BluetoothMapService extends ProfileService { } // Can only be null during shutdown } - private void sendShutdownMessage() { + private void sendShutdownMessage(CountDownLatch latch) { /* Any pending messages are no longer valid. To speed up things, simply delete them. */ if (mRemoveTimeoutMsg) { @@ -921,9 +960,23 @@ public class BluetoothMapService extends ProfileService { mIsWaitingAuthorization = false; cancelUserTimeoutAlarm(); } - mSessionStatusHandler.removeCallbacksAndMessages(null); - // Request release of all resources - mSessionStatusHandler.obtainMessage(SHUTDOWN).sendToTarget(); + if (mSessionStatusHandler != null) { + mSessionStatusHandler.removeCallbacksAndMessages(null); + // Request release of all resources + Message msg = mSessionStatusHandler.obtainMessage(SHUTDOWN,latch); + if( mSessionStatusHandler.sendMessage(msg) == false) { + /* most likely caused by shutdown being called from multiple sources - e.g.BT off + * signaled through intent and a service shutdown simultaneously. + * Intended behavior not documented, hence we need to be able to handle all cases. */ + Log.e(TAG, "mSessionStatusHandler.sendMessage() failed trigger latch locally"); + if(latch != null) { + latch.countDown(); + } + } else { + if(DEBUG) + Log.e(TAG, "mSessionStatusHandler.sendMessage() dispatched shutdown message"); + } + } } private MapBroadcastReceiver mMapReceiver = new MapBroadcastReceiver(); @@ -939,7 +992,7 @@ public class BluetoothMapService extends ProfileService { BluetoothAdapter.ERROR); if (state == BluetoothAdapter.STATE_TURNING_OFF) { if (DEBUG) Log.d(TAG, "STATE_TURNING_OFF"); - sendShutdownMessage(); + sendShutdownMessage(null); } else if (state == BluetoothAdapter.STATE_ON) { if (DEBUG) Log.d(TAG, "STATE_ON"); // start ServerSocket listener threads diff --git a/src/com/android/bluetooth/opp/BluetoothOppL2capListener.java b/src/com/android/bluetooth/opp/BluetoothOppL2capListener.java index 855851272..0bc7acaa7 100644 --- a/src/com/android/bluetooth/opp/BluetoothOppL2capListener.java +++ b/src/com/android/bluetooth/opp/BluetoothOppL2capListener.java @@ -115,9 +115,6 @@ public class BluetoothOppL2capListener { while (!mInterrupted) { try { if (V) Log.v(TAG, "Accepting connection..."); - if (mBtServerSocket == null) { - - } BluetoothServerSocket sSocket = mBtServerSocket; if (sSocket ==null) { mInterrupted = true; @@ -192,9 +189,12 @@ public class BluetoothOppL2capListener { } } - public int getL2capChannel() { - Log.d(TAG,"L2C channel is " +mBtServerSocket.getChannel()); + public int getL2capPsm() { + if (mBtServerSocket != null) { + Log.d(TAG, "L2CAP psm is " + mBtServerSocket.getChannel()); return mBtServerSocket.getChannel(); + } + return -1; } public BluetoothServerSocket openL2capSocket(){ diff --git a/src/com/android/bluetooth/opp/BluetoothOppService.java b/src/com/android/bluetooth/opp/BluetoothOppService.java index b69a1f47e..27519cc5b 100644 --- a/src/com/android/bluetooth/opp/BluetoothOppService.java +++ b/src/com/android/bluetooth/opp/BluetoothOppService.java @@ -139,8 +139,6 @@ public class BluetoothOppService extends Service { private int mIncomingRetries = 0; private ObexTransport mPendingConnection = null; - private BluetoothServerSocket mBtRfcServerSocket = null; - private BluetoothServerSocket mBtL2cServerSocket = null; private int mOppSdpHandle = -1; /* @@ -162,8 +160,6 @@ public class BluetoothOppService extends Service { super.onCreate(); if (V) Log.v(TAG, "onCreate"); mAdapter = BluetoothAdapter.getDefaultAdapter(); - mSocketListener = new BluetoothOppRfcommListener(mAdapter); - mL2cSocketListener = new BluetoothOppL2capListener(mAdapter); mShares = Lists.newArrayList(); mBatchs = Lists.newArrayList(); mObserver = new BluetoothShareContentObserver(); @@ -237,11 +233,21 @@ public class BluetoothOppService extends Service { public void handleMessage(Message msg) { switch (msg.what) { case STOP_LISTENER: + if (mAdapter != null && mOppSdpHandle >= 0 && + SdpManager.getDefaultManager() != null) { + if (D) Log.d(TAG, "Removing SDP record"); + boolean status = SdpManager.getDefaultManager(). + removeSdpRecord(mOppSdpHandle); + Log.d(TAG, "RemoveSDPrecord returns " + status); + mOppSdpHandle = -1; + } if(mSocketListener != null){ mSocketListener.stop(); + mSocketListener = null; } if(mL2cSocketListener != null){ mL2cSocketListener.stop(); + mL2cSocketListener = null; } mListenStarted = false; //Stop Active INBOUND Transfer @@ -356,31 +362,34 @@ public class BluetoothOppService extends Service { private void startSocketListener() { - if (V) Log.v(TAG, "start Socket Listeners"); - if (mSocketListener != null ) { - mBtRfcServerSocket = mSocketListener.openRfcommSocket(); - } - - if (mL2cSocketListener != null) { - mBtL2cServerSocket = mL2cSocketListener.openL2capSocket(); - } + Log.d(TAG, "start Socket Listeners"); - if (mBtRfcServerSocket != null && mBtL2cServerSocket != null) { - mOppSdpHandle = SdpManager.getDefaultManager().createOppOpsRecord("OBEX Object Push", - mBtRfcServerSocket.getChannel(), mBtL2cServerSocket.getChannel(), - 0x0102, SdpManager.OPP_FORMAT_ALL); - } else { - Log.e(TAG, "ERROR:serversocket object is NULL"); + if(mSocketListener != null){ + Log.d(TAG, "rfcomm listener active, stopping it"); + mSocketListener.stop(); + mSocketListener = null; } - - if (mSocketListener != null) { - mSocketListener.start(mHandler); + if(mL2cSocketListener != null){ + Log.d(TAG, "l2cap listener active, stopping it"); + mL2cSocketListener.stop(); + mL2cSocketListener = null; } - - if (mL2cSocketListener != null) { - mL2cSocketListener.start(mHandler); + mSocketListener = new BluetoothOppRfcommListener(mAdapter); + mL2cSocketListener = new BluetoothOppL2capListener(mAdapter); + if (mSocketListener != null && mL2cSocketListener != null) { + + if ( ( mSocketListener.openRfcommSocket() != null) && + ( mL2cSocketListener.openL2capSocket() != null) && + SdpManager.getDefaultManager() != null) { + mOppSdpHandle = SdpManager.getDefaultManager() + .createOppOpsRecord("OBEX Object Push", mSocketListener.getRfcommChannel(), + mL2cSocketListener.getL2capPsm(), 0x0102, SdpManager.OPP_FORMAT_ALL); + mSocketListener.start(mHandler); + mL2cSocketListener.start(mHandler); + } else { + Log.e(TAG, "ERROR:serversocket object is NULL"); + } } - } @Override @@ -390,8 +399,14 @@ public class BluetoothOppService extends Service { mOppManager.isOPPServiceUp = false; getContentResolver().unregisterContentObserver(mObserver); unregisterReceiver(mBluetoothReceiver); - mSocketListener.stop(); - mL2cSocketListener.stop(); + if(mSocketListener != null) { + mSocketListener.stop(); + mSocketListener = null; + } + if(mL2cSocketListener != null) { + mL2cSocketListener.stop(); + mL2cSocketListener = null; + } if(mBatchs != null) { mBatchs.clear(); @@ -420,12 +435,11 @@ public class BluetoothOppService extends Service { if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { switch (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) { case BluetoothAdapter.STATE_ON: - if (V) Log.v(TAG, - "Receiver BLUETOOTH_STATE_CHANGED_ACTION, BLUETOOTH_STATE_ON"); + Log.d(TAG, "Receiver BLUETOOTH_STATE_CHANGED_ACTION, STATE_ON"); startSocketListener(); break; case BluetoothAdapter.STATE_TURNING_OFF: - if (V) Log.v(TAG, "Receiver DISABLED_ACTION "); + Log.d(TAG, "Receiver BLUETOOTH_STATE_CHANGED_ACTION, STATE_TURNING_OFF"); //FIX: Don't block main thread /* mSocketListener.stop(); @@ -449,6 +463,7 @@ public class BluetoothOppService extends Service { mPendingUpdate = true; if ((mUpdateThread == null) && (mAdapter != null) && mAdapter.isEnabled()) { + mPowerManager = (PowerManager)getSystemService(POWER_SERVICE); if (V) Log.v(TAG, "Starting a new thread"); mUpdateThread = new UpdateThread(); mUpdateThread.start(); @@ -484,6 +499,13 @@ public class BluetoothOppService extends Service { if (V) Log.v(TAG, "***returning from updatethread***"); return; } + try { + if (!mPowerManager.isInteractive()) + Thread.sleep(1000); + } catch (InterruptedException e) { + Log.e(TAG, "Interrupted", e); + } + mPendingUpdate = false; } Cursor cursor; diff --git a/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java b/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java index f195ce54d..3d665f169 100644 --- a/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java +++ b/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java @@ -340,22 +340,28 @@ public class BluetoothPbapVcardManager { final Uri myUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext); Cursor contactCursor = null; try { - contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, CLAUSE_ONLY_VISIBLE, - null, Phone.CONTACT_ID); + if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_INDEXED) { + if (V) Log.v(TAG, "getPhonebookNameList, order by index"); + contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, + CLAUSE_ONLY_VISIBLE, null, Phone.CONTACT_ID); + } else if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) { + /*we are getting the contacts from the database in the alphabetical sorted order + itself rather than appying sorting afterwards since that sort the owner + contact too which was added in the beginning and can mess up the behavior + */ + if (V) Log.v(TAG, "getPhonebookNameList, order by alpha"); + contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, + CLAUSE_ONLY_VISIBLE, null, Contacts.DISPLAY_NAME); + } if (contactCursor != null) { appendDistinctNameIdList(nameList, mContext.getString(android.R.string.unknownName), contactCursor); - if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_INDEXED) { - if (V) Log.v(TAG, "getPhonebookNameList, order by index"); - // Do not need to do anything, as we sort it by index already - } else if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) { - if (V) Log.v(TAG, "getPhonebookNameList, order by alpha"); - Collections.sort(nameList); - } } + } catch (CursorWindowAllocationException e) { + Log.e(TAG, "CursorWindowAllocationException while getting phonebook name list"); } catch (Exception e) { - Log.e(TAG, "Exception while getting Phonebook name list", e); + Log.e(TAG, "Exception while getting phonebook name list", e); } finally { if (contactCursor != null) { contactCursor.close(); @@ -635,17 +641,32 @@ public class BluetoothPbapVcardManager { Cursor contactIdCursor = new MatrixCursor(new String[] { Phone.CONTACT_ID }); - try { - contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, - CLAUSE_ONLY_VISIBLE, null, Phone.CONTACT_ID); - contactIdCursor = ContactCursorFilter.filterByOffset(contactCursor, offset); + if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_INDEXED) { + try { + contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, + CLAUSE_ONLY_VISIBLE, null, Phone.CONTACT_ID); + contactIdCursor = ContactCursorFilter.filterByOffset(contactCursor, offset); + } catch (CursorWindowAllocationException e) { + Log.e(TAG, + "CursorWindowAllocationException while composing phonebook one vcard"); + } finally { + if (contactCursor != null) { + contactCursor.close(); + } + } + } else if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) { + try { + contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, + CLAUSE_ONLY_VISIBLE, null, Phone.DISPLAY_NAME); + contactIdCursor = ContactCursorFilter.filterByOffset(contactCursor, offset); - } catch (CursorWindowAllocationException e) { - Log.e(TAG, + } catch (CursorWindowAllocationException e) { + Log.e(TAG, "CursorWindowAllocationException while composing phonebook one vcard"); - } finally { - if (contactCursor != null) { - contactCursor.close(); + } finally { + if (contactCursor != null) { + contactCursor.close(); + } } } return composeContactsAndSendVCards(op, contactIdCursor, vcardType21, ownerVCard, diff --git a/src/com/android/bluetooth/sap/SapServer.java b/src/com/android/bluetooth/sap/SapServer.java index 56dc4f44d..d8c24722f 100644 --- a/src/com/android/bluetooth/sap/SapServer.java +++ b/src/com/android/bluetooth/sap/SapServer.java @@ -30,6 +30,7 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.telephony.TelephonyManager; import android.util.Log; +import android.bluetooth.BluetoothSap; //import com.android.internal.telephony.RIL; import com.google.protobuf.micro.CodedOutputStreamMicro; @@ -311,7 +312,6 @@ public class SapServer extends Thread implements Callback { mRilBtReceiver = new SapRilReceiver(mSapHandler, mSapServiceHandler); mRilBtReceiverThread = new Thread(mRilBtReceiver, "RilBtReceiver"); - setNotification(SapMessage.DISC_GRACEFULL,0); boolean done = false; while (!done) { if(VERBOSE) Log.v(TAG, "Waiting for incomming RFCOMM message..."); @@ -347,16 +347,23 @@ public class SapServer extends Thread implements Callback { * close socket-streams and initiate cleanup */ if(DEBUG) Log.d(TAG, "DISCONNECT_REQ"); - clearPendingRilResponses(msg); - - changeState(SAP_STATE.DISCONNECTING); - - sendRilThreadMessage(msg); - /* We simply need to forward to RIL, but not change state to busy - * - hence send and set message to null. */ - msg = null; // don't send twice - /*cancel the timer for the hard-disconnect intent*/ - stopDisconnectTimer(); + if (mState == SAP_STATE.CONNECTING_CALL_ONGOING) { + Log.d(TAG, "disconnect received when call was ongoing, " + + "send disconnect response"); + changeState(SAP_STATE.DISCONNECTING); + SapMessage reply = new SapMessage(SapMessage.ID_DISCONNECT_RESP); + sendClientMessage(reply); + msg = null; // No message needs to be sent to RIL + } else { + clearPendingRilResponses(msg); + changeState(SAP_STATE.DISCONNECTING); + sendRilThreadMessage(msg); + /* We simply need to forward to RIL, but not change state to busy + * - hence send and set message to null. */ + msg = null; // don't send twice + /*cancel the timer for the hard-disconnect intent*/ + stopDisconnectTimer(); + } break; case SapMessage.ID_POWER_SIM_OFF_REQ: // Fall through case SapMessage.ID_RESET_SIM_REQ: @@ -785,6 +792,14 @@ public class SapServer extends Thread implements Callback { mState == SAP_STATE.DISCONNECTING) { sapMsg = null; } + if (mSapServiceHandler != null && mState == SAP_STATE.CONNECTED) { + Message msg = Message.obtain(mSapServiceHandler); + msg.what = SapService.MSG_CHANGE_STATE; + msg.arg1 = BluetoothSap.STATE_CONNECTED; + msg.sendToTarget(); + setNotification(SapMessage.DISC_GRACEFULL, 0); + if (DEBUG) Log.d(TAG, "MSG_CHANGE_STATE sent out."); + } break; default: // Nothing special, just send the message diff --git a/src/com/android/bluetooth/sap/SapService.java b/src/com/android/bluetooth/sap/SapService.java index b3cc74d5c..9199d7fd1 100644 --- a/src/com/android/bluetooth/sap/SapService.java +++ b/src/com/android/bluetooth/sap/SapService.java @@ -65,6 +65,7 @@ public class SapService extends ProfileService { public static final int MSG_ACQUIRE_WAKE_LOCK = 5005; public static final int MSG_RELEASE_WAKE_LOCK = 5006; + public static final int MSG_CHANGE_STATE = 5007; /* Each time a transaction between the SIM and the BT Client is detected a wakelock is taken. * After an idle period of RELEASE_WAKE_LOCK_DELAY ms the wakelock is released. * @@ -95,6 +96,7 @@ public class SapService extends ProfileService { private boolean mRemoveTimeoutMsg = false; private boolean mIsWaitingAuthorization = false; + private boolean mIsRegistered = false; private SapServiceMessageHandler mSessionStatusHandler = null; @@ -151,9 +153,12 @@ public class SapService extends ProfileService { // for multiple connections. mServerSocket = mAdapter.listenUsingRfcommOn( BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, true, true); - if (mSdpHandle >= 0) { - SdpManager.getDefaultManager().removeSdpRecord(mSdpHandle); + if (mAdapter != null && mSdpHandle >= 0 && + SdpManager.getDefaultManager() != null) { if (DEBUG) Log.d(TAG, "Removing SDP record"); + boolean status = SdpManager.getDefaultManager().removeSdpRecord(mSdpHandle); + Log.d(TAG, "RemoveSDPrecord returns " + status); + mSdpHandle = -1; } mSdpHandle = SdpManager.getDefaultManager().createSapsRecord(SDP_SAP_SERVICE_NAME, mServerSocket.getChannel(), SDP_SAP_VERSION); @@ -181,11 +186,6 @@ public class SapService extends ProfileService { break; } } - if (mInterrupted) { - initSocketOK = false; - // close server socket to avoid resource leakage - closeServerSocket(); - } if (initSocketOK) { if (VERBOSE) Log.v(TAG, "Succeed to create listening socket "); @@ -201,6 +201,7 @@ public class SapService extends ProfileService { if (mServerSocket != null) { try { // this will cause mServerSocket.accept() return early with IOException + if (VERBOSE) Log.v(TAG, "Closing server socket"); mServerSocket.close(); mServerSocket = null; } catch (IOException ex) { @@ -212,6 +213,7 @@ public class SapService extends ProfileService { private final synchronized void closeConnectionSocket() { if (mConnSocket != null) { try { + if (VERBOSE) Log.v(TAG, "Closing conenction socket"); mConnSocket.close(); mConnSocket = null; } catch (IOException e) { @@ -235,7 +237,7 @@ public class SapService extends ProfileService { mAcceptThread.shutdown(); mAcceptThread.join(); } catch (InterruptedException ex) { - Log.w(TAG, "mAcceptThread close error", ex); + Log.e(TAG, "mAcceptThread close error", ex); } mAcceptThread = null; } @@ -248,7 +250,7 @@ public class SapService extends ProfileService { } synchronized private void releaseWakeLockResources() { - if (mWakeLock != null) { + if ((mWakeLock != null) && (mSessionStatusHandler != null)) { mSessionStatusHandler.removeMessages(MSG_ACQUIRE_WAKE_LOCK); mSessionStatusHandler.removeMessages(MSG_RELEASE_WAKE_LOCK); mWakeLock.release(); @@ -261,6 +263,7 @@ public class SapService extends ProfileService { // E.g. we cannot have multiple receivers registered nor have multiple servers attached // to the RIL socket. if(mSapServer != null) { + if (DEBUG) Log.d(TAG, "Awaiting SapServerSessionStop"); boolean retry = true; while(retry == true) { retry = false; @@ -286,8 +289,6 @@ public class SapService extends ProfileService { mWakeLock.acquire(); } - setState(BluetoothSap.STATE_CONNECTED); - /* Start the SAP I/O thread and associate with message handler */ mSapServer = new SapServer(mSessionStatusHandler, this, mConnSocket.getInputStream(), mConnSocket.getOutputStream()); mSapServer.start(); @@ -351,14 +352,14 @@ public class SapService extends ProfileService { if (VERBOSE) Log.v(TAG, "Accepting socket connection..."); serverSocket = mServerSocket; if (serverSocket == null) { - Log.w(TAG, "mServerSocket is null"); + Log.e(TAG, "mServerSocket is null"); break; } mConnSocket = mServerSocket.accept(); - if (VERBOSE) Log.v(TAG, "Accepted socket connection..."); + if (DEBUG) Log.d(TAG, "Accepted socket connection..."); synchronized (SapService.this) { if (mConnSocket == null) { - Log.w(TAG, "mConnSocket is null"); + Log.e(TAG, "mConnSocket is null"); break; } mRemoteDevice = mConnSocket.getRemoteDevice(); @@ -375,7 +376,7 @@ public class SapService extends ProfileService { } int permission = mRemoteDevice.getSimAccessPermission(); - if (VERBOSE) Log.v(TAG, "getSimAccessPermission() = " + permission); + if (DEBUG) Log.d(TAG, "getSimAccessPermission() = " + permission); if (permission == BluetoothDevice.ACCESS_ALLOWED) { try { @@ -408,7 +409,7 @@ public class SapService extends ProfileService { stopped = true; // job done ,close this thread; } catch (IOException ex) { stopped=true; - if (VERBOSE) Log.v(TAG, "Accept exception: ", ex); + if (DEBUG) Log.d(TAG, "Accept exception: ", ex); } } } @@ -473,6 +474,10 @@ public class SapService extends ProfileService { if (DEBUG) Log.d(TAG, " Released Wake Lock by message"); } break; + case MSG_CHANGE_STATE: + if (VERBOSE) Log.v(TAG, "change state message: newState = " + msg.arg1); + setState(msg.arg1); + break; case SHUTDOWN: /* Ensure to call close from this handler to avoid starting new stuff because of pending messages */ @@ -625,6 +630,7 @@ public class SapService extends ProfileService { try { registerReceiver(mSapReceiver, filter); + mIsRegistered = true; } catch (Exception e) { Log.w(TAG,"Unable to register sap receiver",e); } @@ -643,7 +649,13 @@ public class SapService extends ProfileService { @Override protected boolean stop() { if (VERBOSE) Log.v(TAG, "Stoping SAPService"); + + if (!mIsRegistered){ + Log.i(TAG, "Avoid unregister when receiver it is not registered"); + return true; + } try { + mIsRegistered = false; unregisterReceiver(mSapReceiver); } catch (Exception e) { Log.w(TAG,"Unable to unregister sap receiver",e); @@ -723,19 +735,29 @@ public class SapService extends ProfileService { mIsWaitingAuthorization = false; cancelUserTimeoutAlarm(); } - mSessionStatusHandler.removeCallbacksAndMessages(null); - // Request release of all resources - Message msg = mSessionStatusHandler.obtainMessage(SHUTDOWN,latch); - if( mSessionStatusHandler.sendMessage(msg) == false) { - /* most likely caused by shutdown being called from multiple sources - e.g.BT off - * signaled through intent and a service shutdown simultaneously. - * Intended behavior not documented, hence we need to be able to handle all cases. */ - Log.e(TAG, "mSessionStatusHandler.sendMessage() failed trigger latch locally"); - if(latch != null) { - latch.countDown(); + if (mAdapter != null && mSdpHandle >= 0 && + SdpManager.getDefaultManager() != null) { + if (DEBUG) Log.d(TAG, "Removing SDP record"); + boolean status = SdpManager.getDefaultManager().removeSdpRecord(mSdpHandle); + Log.d(TAG, "RemoveSDPrecord returns " + status); + mSdpHandle = -1; + } + if (mSessionStatusHandler != null) { + mSessionStatusHandler.removeCallbacksAndMessages(null); + // Request release of all resources + Message msg = mSessionStatusHandler.obtainMessage(SHUTDOWN,latch); + if( mSessionStatusHandler.sendMessage(msg) == false) { + /* most likely caused by shutdown being called from multiple sources - e.g.BT off + * signaled through intent and a service shutdown simultaneously. + * Intended behavior not documented, hence we need to be able to handle all cases. + */ + Log.e(TAG, "mSessionStatusHandler.sendMessage() failed trigger latch locally"); + if(latch != null) { + latch.countDown(); + } + } else { + if(DEBUG) Log.e(TAG, "mSessionStatusHandler.sendMessage() dispatched shutdown msg"); } - } else { - if(DEBUG) Log.e(TAG, "mSessionStatusHandler.sendMessage() dispatched shutdown message"); } } @@ -764,7 +786,8 @@ public class SapService extends ProfileService { } else if (state == BluetoothAdapter.STATE_ON) { if (DEBUG) Log.d(TAG, "STATE_ON"); // start RFCOMM listener - mSessionStatusHandler.sendMessage(mSessionStatusHandler + if (mSessionStatusHandler != null) + mSessionStatusHandler.sendMessage(mSessionStatusHandler .obtainMessage(START_LISTENER)); } } else if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY)) { @@ -806,7 +829,8 @@ public class SapService extends ProfileService { } } // Ensure proper cleanup, and prepare for new connect. - mSessionStatusHandler.sendEmptyMessage(MSG_SERVERSESSION_CLOSE); + if (mSessionStatusHandler != null) + mSessionStatusHandler.sendEmptyMessage(MSG_SERVERSESSION_CLOSE); } } else if (action.equals(USER_CONFIRM_TIMEOUT_ACTION)){ if (DEBUG) Log.d(TAG, "USER_CONFIRM_TIMEOUT ACTION Received."); @@ -823,13 +847,16 @@ public class SapService extends ProfileService { if (DEBUG) Log.d(TAG,"ACL disconnected for " + device); - if (mRemoteDevice.equals(device) && mRemoveTimeoutMsg) { - // Send any pending timeout now, as ACL got disconnected. - cancelUserTimeoutAlarm(); - mSessionStatusHandler.removeMessages(USER_TIMEOUT); - sendCancelUserConfirmationIntent(mRemoteDevice); + if (mRemoteDevice.equals(device)) { + if (mRemoveTimeoutMsg) { + // Send any pending timeout now, as ACL got disconnected. + cancelUserTimeoutAlarm(); + mSessionStatusHandler.removeMessages(USER_TIMEOUT); + sendCancelUserConfirmationIntent(mRemoteDevice); + mRemoveTimeoutMsg = false; + } mIsWaitingAuthorization = false; - mRemoveTimeoutMsg = false; + setState(BluetoothSap.STATE_DISCONNECTED); // Ensure proper cleanup, and prepare for new connect. mSessionStatusHandler.sendEmptyMessage(MSG_SERVERSESSION_CLOSE); } |