summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2016-03-30 11:51:31 -0700
committerSteve Kondik <steve@cyngn.com>2016-03-30 11:51:31 -0700
commit8c5b9feba472e4532b6d151a402c8ad3ebd947a7 (patch)
tree709589743ad8fd9e3dcfa2b0dbb5f8ba981ac16e
parentd7199f6c73b0c927f694967163f33257d6e5199f (diff)
parente6fae29795ff64060044d89bb6213f13042008ff (diff)
downloadandroid_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.java9
-rw-r--r--src/com/android/bluetooth/hfp/HeadsetStateMachine.java10
-rw-r--r--src/com/android/bluetooth/map/BluetoothMapContent.java2
-rw-r--r--src/com/android/bluetooth/map/BluetoothMapContentEmail.java2
-rw-r--r--src/com/android/bluetooth/map/BluetoothMapContentObserver.java3
-rw-r--r--src/com/android/bluetooth/map/BluetoothMapMasInstance.java16
-rwxr-xr-x[-rw-r--r--]src/com/android/bluetooth/map/BluetoothMapService.java105
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppL2capListener.java10
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppService.java82
-rw-r--r--src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java59
-rw-r--r--src/com/android/bluetooth/sap/SapServer.java37
-rw-r--r--src/com/android/bluetooth/sap/SapService.java99
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);
}