summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJessica Wagantall <jwagantall@cyngn.com>2016-05-16 11:28:05 -0700
committerJessica Wagantall <jwagantall@cyngn.com>2016-05-16 11:38:55 -0700
commited52dff0f25c14b8478d2b96be962f6f25b29f0c (patch)
tree626532699aa6e40a3c6c8264298899a7261bc095
parent39cd78c8f9508b4874b09aa47a0796fb2728333f (diff)
parent38516fd6ef6d2849ea0369413377e4e8a5632c2b (diff)
downloadandroid_packages_apps_Bluetooth-ed52dff0f25c14b8478d2b96be962f6f25b29f0c.tar.gz
android_packages_apps_Bluetooth-ed52dff0f25c14b8478d2b96be962f6f25b29f0c.tar.bz2
android_packages_apps_Bluetooth-ed52dff0f25c14b8478d2b96be962f6f25b29f0c.zip
Merge remote-tracking branch 'github/cm-13.0' into HEAD
OPO-618 Change-Id: I11479a6ae1f1b9e0fa1561e8992a3da929dfc8f6
-rw-r--r--jni/com_android_bluetooth_a2dp.cpp81
-rw-r--r--jni/com_android_bluetooth_btservice_AdapterService.cpp26
-rw-r--r--jni/com_android_bluetooth_hdp.cpp5
-rw-r--r--src/com/android/bluetooth/Utils.java4
-rw-r--r--src/com/android/bluetooth/avrcp/Avrcp.java2
-rw-r--r--src/com/android/bluetooth/btservice/AdapterService.java58
-rw-r--r--src/com/android/bluetooth/map/BluetoothMapAppObserver.java19
-rw-r--r--src/com/android/bluetooth/map/BluetoothMapContentObserver.java8
-rw-r--r--src/com/android/bluetooth/map/BluetoothMapMasInstance.java2
-rwxr-xr-xsrc/com/android/bluetooth/map/BluetoothMapService.java105
-rw-r--r--src/com/android/bluetooth/map/BluetoothMapUtils.java7
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java4
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppManager.java35
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java18
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java31
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppReceiver.java8
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppService.java27
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppShareInfo.java10
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppTransfer.java63
-rw-r--r--src/com/android/bluetooth/pbap/BluetoothPbapService.java4
-rw-r--r--src/com/android/bluetooth/sap/SapMessage.java5
-rw-r--r--src/com/android/bluetooth/sap/SapRilReceiver.java2
-rw-r--r--src/com/android/bluetooth/sap/SapServer.java5
-rw-r--r--src/com/android/bluetooth/sap/SapService.java95
24 files changed, 403 insertions, 221 deletions
diff --git a/jni/com_android_bluetooth_a2dp.cpp b/jni/com_android_bluetooth_a2dp.cpp
index df8fe9837..565cd99a9 100644
--- a/jni/com_android_bluetooth_a2dp.cpp
+++ b/jni/com_android_bluetooth_a2dp.cpp
@@ -27,6 +27,7 @@
#include "android_runtime/AndroidRuntime.h"
#include <string.h>
+#include <pthread.h>
namespace android {
static jmethodID method_onConnectionStateChanged;
@@ -39,6 +40,8 @@ static const btav_interface_t *sBluetoothA2dpInterface = NULL;
static jobject mCallbacksObj = NULL;
static JNIEnv *sCallbackEnv = NULL;
+static pthread_mutex_t mMutex = PTHREAD_MUTEX_INITIALIZER;
+
static bool checkCallbackThread() {
// Always fetch the latest callbackEnv from AdapterService.
// Caching this could cause this sCallbackEnv to go out-of-sync
@@ -58,10 +61,6 @@ static void bta2dp_connection_state_callback(btav_connection_state_t state, bt_b
ALOGI("%s", __FUNCTION__);
- if (mCallbacksObj == NULL) {
- ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
- return;
- }
if (!checkCallbackThread()) { \
ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
return; \
@@ -75,8 +74,16 @@ static void bta2dp_connection_state_callback(btav_connection_state_t state, bt_b
}
sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
- sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, (jint) state,
- addr);
+
+ pthread_mutex_lock(&mMutex);
+ if (mCallbacksObj != NULL) {
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged,
+ (jint) state, addr);
+ } else {
+ ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
+ }
+ pthread_mutex_unlock(&mMutex);
+
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
sCallbackEnv->DeleteLocalRef(addr);
}
@@ -86,10 +93,6 @@ static void bta2dp_audio_state_callback(btav_audio_state_t state, bt_bdaddr_t* b
ALOGI("%s", __FUNCTION__);
- if (mCallbacksObj == NULL) {
- ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
- return;
- }
if (!checkCallbackThread()) { \
ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
return; \
@@ -102,8 +105,16 @@ static void bta2dp_audio_state_callback(btav_audio_state_t state, bt_bdaddr_t* b
}
sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
- sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint) state,
- addr);
+
+ pthread_mutex_lock(&mMutex);
+ if (mCallbacksObj != NULL) {
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged,
+ (jint) state, addr);
+ } else {
+ ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
+ }
+ pthread_mutex_unlock(&mMutex);
+
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
sCallbackEnv->DeleteLocalRef(addr);
}
@@ -113,10 +124,6 @@ static void bta2dp_connection_priority_callback(bt_bdaddr_t* bd_addr) {
ALOGI("%s", __FUNCTION__);
- if (mCallbacksObj == NULL) {
- ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
- return;
- }
if (!checkCallbackThread()) { \
ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
return; \
@@ -129,7 +136,16 @@ static void bta2dp_connection_priority_callback(bt_bdaddr_t* bd_addr) {
}
sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
- sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCheckConnectionPriority, addr);
+
+ pthread_mutex_lock(&mMutex);
+ if (mCallbacksObj != NULL) {
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCheckConnectionPriority,
+ addr);
+ } else {
+ ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
+ }
+ pthread_mutex_unlock(&mMutex);
+
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
sCallbackEnv->DeleteLocalRef(addr);
}
@@ -138,16 +154,20 @@ static void bta2dp_multicast_enabled_callback(int state) {
ALOGI("%s", __FUNCTION__);
- if (mCallbacksObj == NULL) {
- ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
- return;
- }
if (!checkCallbackThread()) { \
ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
return; \
}
- sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMulticastStateChanged, state);
+ pthread_mutex_lock(&mMutex);
+ if (mCallbacksObj != NULL) {
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMulticastStateChanged,
+ state);
+ } else {
+ ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
+ }
+ pthread_mutex_unlock(&mMutex);
+
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
}
@@ -218,29 +238,32 @@ static void initNative(JNIEnv *env, jobject object, jint maxA2dpConnections,
sBluetoothA2dpInterface = NULL;
}
- if (mCallbacksObj != NULL) {
- ALOGW("Cleaning up A2DP callback object");
- env->DeleteGlobalRef(mCallbacksObj);
- mCallbacksObj = NULL;
- }
-
if ( (sBluetoothA2dpInterface = (btav_interface_t *)
btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID)) == NULL) {
ALOGE("Failed to get Bluetooth A2DP Interface");
return;
}
+ pthread_mutex_lock(&mMutex);
+ if (mCallbacksObj != NULL) {
+ ALOGW("Cleaning up A2DP callback object");
+ env->DeleteGlobalRef(mCallbacksObj);
+ mCallbacksObj = NULL;
+ }
mCallbacksObj = env->NewGlobalRef(object);
+ pthread_mutex_unlock(&mMutex);
if ( (status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks,
maxA2dpConnections, multiCastState)) != BT_STATUS_SUCCESS) {
ALOGE("Failed to initialize Bluetooth A2DP, status: %d", status);
sBluetoothA2dpInterface = NULL;
+ pthread_mutex_lock(&mMutex);
if (mCallbacksObj != NULL) {
ALOGW("Clean up A2DP callback object");
env->DeleteGlobalRef(mCallbacksObj);
mCallbacksObj = NULL;
}
+ pthread_mutex_unlock(&mMutex);
return;
}
@@ -260,10 +283,12 @@ static void cleanupNative(JNIEnv *env, jobject object) {
sBluetoothA2dpInterface = NULL;
}
+ pthread_mutex_lock(&mMutex);
if (mCallbacksObj != NULL) {
env->DeleteGlobalRef(mCallbacksObj);
mCallbacksObj = NULL;
}
+ pthread_mutex_unlock(&mMutex);
}
static jboolean connectA2dpNative(JNIEnv *env, jobject object, jbyteArray address) {
diff --git a/jni/com_android_bluetooth_btservice_AdapterService.cpp b/jni/com_android_bluetooth_btservice_AdapterService.cpp
index 2544eb8d4..f18856c1a 100644
--- a/jni/com_android_bluetooth_btservice_AdapterService.cpp
+++ b/jni/com_android_bluetooth_btservice_AdapterService.cpp
@@ -1256,6 +1256,27 @@ static jboolean factoryResetNative(JNIEnv *env, jobject obj) {
return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}
+static void interopDatabaseClearNative(JNIEnv *env, jobject obj) {
+ ALOGV("%s()", __FUNCTION__);
+ if (!sBluetoothInterface) return;
+ sBluetoothInterface->interop_database_clear();
+}
+
+static void interopDatabaseAddNative(JNIEnv *env, jobject obj, int feature,
+ jbyteArray address, int length) {
+ ALOGV("%s()", __FUNCTION__);
+ if (!sBluetoothInterface) return;
+
+ jbyte *addr = env->GetByteArrayElements(address, NULL);
+ if (addr == NULL) {
+ jniThrowIOException(env, EINVAL);
+ return;
+ }
+
+ sBluetoothInterface->interop_database_add(feature, (bt_bdaddr_t *)addr, length);
+ env->ReleaseByteArrayElements(address, addr, 0);
+}
+
static JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"classInitNative", "()V", (void *) classInitNative},
@@ -1287,8 +1308,9 @@ static JNINativeMethod sMethods[] = {
{"dumpNative", "(Ljava/io/FileDescriptor;)V", (void*) dumpNative},
{"factoryResetNative", "()Z", (void*)factoryResetNative},
{"getSocketOptNative", "(III[B)I", (void*) getSocketOptNative},
- {"setSocketOptNative", "(III[BI)I", (void*) setSocketOptNative}
-
+ {"setSocketOptNative", "(III[BI)I", (void*) setSocketOptNative},
+ {"interopDatabaseClearNative", "()V", (void*) interopDatabaseClearNative},
+ {"interopDatabaseAddNative", "(I[BI)V", (void*) interopDatabaseAddNative}
};
int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)
diff --git a/jni/com_android_bluetooth_hdp.cpp b/jni/com_android_bluetooth_hdp.cpp
index 81c8312c1..8556e6a89 100644
--- a/jni/com_android_bluetooth_hdp.cpp
+++ b/jni/com_android_bluetooth_hdp.cpp
@@ -195,7 +195,10 @@ static jint registerHealthAppNative(JNIEnv *env, jobject object, jint data_type,
bthl_reg_param_t reg_param;
int app_id;
- if (!sBluetoothHdpInterface) return NULL;
+ if (!sBluetoothHdpInterface) {
+ ALOGE("Failed register health app. No Bluetooth Health Interface available");
+ return -1;
+ }
mdep_cfg.mdep_role = (bthl_mdep_role_t) role;
mdep_cfg.data_type = data_type;
diff --git a/src/com/android/bluetooth/Utils.java b/src/com/android/bluetooth/Utils.java
index e87a6d9e3..6a467f9c3 100644
--- a/src/com/android/bluetooth/Utils.java
+++ b/src/com/android/bluetooth/Utils.java
@@ -204,19 +204,15 @@ final public class Utils {
int callingUser = UserHandle.getCallingUserId();
int callingUid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
- Log.d(TAG,"callingUid =" + callingUid);
try {
// With calling identity cleared the current user is the foreground user.
int foregroundUser = ActivityManager.getCurrentUser();
ok = (foregroundUser == callingUser);
- Log.e(TAG, "foregroundUser =" + foregroundUser);
- Log.e(TAG, "callingUser =" + callingUser);
if (!ok) {
// Always allow SystemUI/System access.
int systemUiUid = ActivityThread.getPackageManager().getPackageUid(
"com.android.systemui", UserHandle.USER_OWNER);
- Log.d(TAG," systemUiUid :" + systemUiUid);
ok = (systemUiUid == callingUid) || (Process.SYSTEM_UID == callingUid);
}
} catch (Exception ex) {
diff --git a/src/com/android/bluetooth/avrcp/Avrcp.java b/src/com/android/bluetooth/avrcp/Avrcp.java
index 2195559c0..dfdb42c27 100644
--- a/src/com/android/bluetooth/avrcp/Avrcp.java
+++ b/src/com/android/bluetooth/avrcp/Avrcp.java
@@ -4266,7 +4266,7 @@ public final class Avrcp {
}
}
}
- return !absVolumeSupported.contains((byte)0);
+ return !(absVolumeSupported.contains((byte)0) || absVolumeSupported.isEmpty());
}
/**
diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java
index fba0c8933..ba597c3e4 100644
--- a/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/src/com/android/bluetooth/btservice/AdapterService.java
@@ -395,6 +395,8 @@ public class AdapterService extends Service {
mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STOPPED));
} else if (isTurningOn) {
+ updateInteropDatabase();
+
//Process start pending
//Check if all services are started if so, update state
synchronized (mProfileServicesState) {
@@ -421,6 +423,59 @@ public class AdapterService extends Service {
}
}
+ private void updateInteropDatabase() {
+ interopDatabaseClearNative();
+
+ String interop_string = Settings.Global.getString(getContentResolver(),
+ Settings.Global.BLUETOOTH_INTEROPERABILITY_LIST);
+ if (interop_string == null) return;
+ Log.d(TAG, "updateInteropDatabase: [" + interop_string + "]");
+
+ String[] entries = interop_string.split(";");
+ for (String entry : entries) {
+ String[] tokens = entry.split(",");
+ if (tokens.length != 2) continue;
+
+ // Get feature
+ int feature = 0;
+ try {
+ feature = Integer.parseInt(tokens[1]);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "updateInteropDatabase: Invalid feature '" + tokens[1] + "'");
+ continue;
+ }
+
+ // Get address bytes and length
+ int length = (tokens[0].length() + 1) / 3;
+ if (length < 1 || length > 6) {
+ Log.e(TAG, "updateInteropDatabase: Malformed address string '" + tokens[0] + "'");
+ continue;
+ }
+
+ byte[] addr = new byte[6];
+ int offset = 0;
+ for (int i = 0; i < tokens[0].length(); ) {
+ if (tokens[0].charAt(i) == ':') {
+ i += 1;
+ } else {
+ try {
+ addr[offset++] = (byte) Integer.parseInt(tokens[0].substring(i, i + 2), 16);
+ } catch (NumberFormatException e) {
+ offset = 0;
+ break;
+ }
+ i += 2;
+ }
+ }
+
+ // Check if address was parsed ok, otherwise, move on...
+ if (offset == 0) continue;
+
+ // Add entry
+ interopDatabaseAddNative(feature, addr, length);
+ }
+ }
+
@Override
public void onCreate() {
super.onCreate();
@@ -2528,6 +2583,9 @@ public class AdapterService extends Service {
private native void alarmFiredNative();
private native void dumpNative(FileDescriptor fd);
+ private native void interopDatabaseClearNative();
+ private native void interopDatabaseAddNative(int feature, byte[] address, int length);
+
protected void finalize() {
cleanup();
if (TRACE_REF) {
diff --git a/src/com/android/bluetooth/map/BluetoothMapAppObserver.java b/src/com/android/bluetooth/map/BluetoothMapAppObserver.java
index ee0075669..7721b7e9e 100644
--- a/src/com/android/bluetooth/map/BluetoothMapAppObserver.java
+++ b/src/com/android/bluetooth/map/BluetoothMapAppObserver.java
@@ -55,6 +55,7 @@ public class BluetoothMapAppObserver{
private PackageManager mPackageManager = null;
BluetoothMapAccountEmailLoader mLoader;
BluetoothMapService mMapService = null;
+ private boolean mRegisteredReceiver = false;
public BluetoothMapAppObserver(final Context context, BluetoothMapService mapService) {
mContext = context;
@@ -283,12 +284,26 @@ public class BluetoothMapAppObserver{
}
}
};
- mContext.registerReceiver(mReceiver,intentFilter);
+ if (!mRegisteredReceiver) {
+ try {
+ mContext.registerReceiver(mReceiver,intentFilter);
+ mRegisteredReceiver = true;
+ } catch (Exception e) {
+ Log.e(TAG,"Unable to register MapAppObserver receiver",e);
+ }
+ }
}
private void removeReceiver(){
if(D)Log.d(TAG,"removeReceiver()\n");
- mContext.unregisterReceiver(mReceiver);
+ if (mRegisteredReceiver) {
+ try {
+ mRegisteredReceiver = false;
+ mContext.unregisterReceiver(mReceiver);
+ } catch (Exception e) {
+ Log.e(TAG,"Unable to unregister mapAppObserver receiver",e);
+ }
+ }
}
/**
diff --git a/src/com/android/bluetooth/map/BluetoothMapContentObserver.java b/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
index 92899c23a..e8bde44af 100644
--- a/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
+++ b/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
@@ -3402,7 +3402,9 @@ public class BluetoothMapContentObserver {
};
public void init() {
- mSmsBroadcastReceiver.register();
+ if (mSmsBroadcastReceiver != null ) {
+ mSmsBroadcastReceiver.register();
+ }
registerPhoneServiceStateListener();
mInitialized = true;
}
@@ -3410,7 +3412,9 @@ public class BluetoothMapContentObserver {
public void deinit() {
mInitialized = false;
unregisterObserver();
- mSmsBroadcastReceiver.unregister();
+ if (mSmsBroadcastReceiver != null ) {
+ mSmsBroadcastReceiver.unregister();
+ }
unRegisterPhoneServiceStateListener();
failPendingMessages();
removeDeletedMessages();
diff --git a/src/com/android/bluetooth/map/BluetoothMapMasInstance.java b/src/com/android/bluetooth/map/BluetoothMapMasInstance.java
index 4cc371883..0fa12c607 100644
--- a/src/com/android/bluetooth/map/BluetoothMapMasInstance.java
+++ b/src/com/android/bluetooth/map/BluetoothMapMasInstance.java
@@ -421,6 +421,8 @@ public class BluetoothMapMasInstance implements IObexConnectionHandler {
closeConnectionSocket();
+ if(V) Log.v(TAG, "Block acceptThreads: TRUE");
+ // Block to clean acceptThreads and avoid garbage collection
closeServerSockets(true);
}
diff --git a/src/com/android/bluetooth/map/BluetoothMapService.java b/src/com/android/bluetooth/map/BluetoothMapService.java
index 743c1b924..003687658 100755
--- a/src/com/android/bluetooth/map/BluetoothMapService.java
+++ b/src/com/android/bluetooth/map/BluetoothMapService.java
@@ -150,6 +150,7 @@ public class BluetoothMapService extends ProfileService {
private boolean mSdpSearchInitiated = false;
SdpMnsRecord mMnsRecord = null;
private MapServiceMessageHandler mSessionStatusHandler;
+ private boolean mStartError = true;
// 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";
@@ -167,23 +168,19 @@ public class BluetoothMapService extends ProfileService {
}
- private synchronized void closeService(CountDownLatch latch) {
+ private synchronized void closeService() {
if (DEBUG) Log.d(TAG, "MAP Service closeService in");
if (mBluetoothMnsObexClient != null) {
mBluetoothMnsObexClient.shutdown();
mBluetoothMnsObexClient = null;
}
-
- for(int i=0, c=mMasInstances.size(); i < c; i++) {
- mMasInstances.valueAt(i).shutdown();
- }
- mMasInstances.clear();
-
- if (mSessionStatusHandler != null) {
- mSessionStatusHandler.removeCallbacksAndMessages(null);
+ if (mMasInstances.size() > 0) {
+ for(int i=0, c=mMasInstances.size(); i < c; i++) {
+ mMasInstances.valueAt(i).shutdown();
+ }
+ mMasInstances.clear();
}
-
mIsWaitingAuthorization = false;
mPermission = BluetoothDevice.ACCESS_UNKNOWN;
setState(BluetoothMap.STATE_DISCONNECTED);
@@ -193,12 +190,21 @@ public class BluetoothMapService extends ProfileService {
if (VERBOSE) Log.v(TAG, "CloseService(): Release Wake Lock");
mWakeLock = null;
}
+ /* Only one SHUTDOWN message expected to closeService.
+ * Hence, quit looper and Handler on first SHUTDOWN message*/
+ if (mSessionStatusHandler != null) {
+ //Perform cleanup in Handler running on worker Thread
+ mSessionStatusHandler.removeCallbacksAndMessages(null);
+ Looper looper = mSessionStatusHandler.getLooper();
+ if (looper != null) {
+ looper.quit();
+ if(VERBOSE) Log.i(TAG, "Quit looper");
+ }
+ mSessionStatusHandler = null;
+ if(VERBOSE) Log.i(TAG, "Remove Handler");
+ }
mRemoteDevice = null;
-
if (DEBUG) Log.d(TAG, "MAP Service closeService out");
- if(latch != null) {
- latch.countDown();
- }
}
/**
@@ -379,8 +385,7 @@ public class BluetoothMapService extends ProfileService {
case SHUTDOWN:
/* Ensure to call close from this handler to avoid starting new stuff
because of pending messages */
- CountDownLatch latch = (CountDownLatch) msg.obj;
- closeService(latch);
+ closeService();
break;
case MSG_ACQUIRE_WAKE_LOCK:
if (VERBOSE) Log.v(TAG, "Acquire Wake Lock request message");
@@ -465,6 +470,10 @@ public class BluetoothMapService extends ProfileService {
return mState;
}
+ protected boolean isMapStarted() {
+ return !mStartError;
+ }
+
public static BluetoothDevice getRemoteDevice() {
return mRemoteDevice;
}
@@ -504,7 +513,7 @@ public class BluetoothMapService extends ProfileService {
public boolean disconnectMap(BluetoothDevice device) {
boolean result = false;
if (DEBUG) Log.d(TAG, "disconnectMap");
- if (getRemoteDevice().equals(device)) {
+ if (getRemoteDevice()!= null && getRemoteDevice().equals(device)) {
switch (mState) {
case BluetoothMap.STATE_CONNECTED:
/* Disconnect all connections and restart all MAS instances */
@@ -585,13 +594,13 @@ public class BluetoothMapService extends ProfileService {
if(!VERBOSE)
VERBOSE = Log.isLoggable(LOG_TAG, Log.VERBOSE);
- if (!Utils.checkCaller()) {
- Log.w(TAG, "start received for non-active user, ignoring");
+ //Start MapProfile if not already done.
+ if (isMapStarted()) {
+ Log.w(TAG, "start received for already started, ignoring");
return false;
}
if (VERBOSE) Log.v(TAG, "verbose logging is enabled");
-
HandlerThread thread = new HandlerThread("BluetoothMapHandler");
thread.start();
Looper looper = thread.getLooper();
@@ -631,7 +640,8 @@ public class BluetoothMapService extends ProfileService {
// start RFCOMM listener
sendStartListenerMessage(-1);
- return true;
+ mStartError = false;
+ return !mStartError;
}
/**
@@ -797,24 +807,18 @@ public class BluetoothMapService extends ProfileService {
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 {
- latch.await();
- } catch (InterruptedException e) {
- Log.e(TAG, "Interrupt received while waiting for shutdown to complete", e);
+ //Stop MapProfile if already started.
+ //TODO: Check if the profile state can be retreived from ProfileService or AdapterService.
+ if (!isMapStarted()) {
+ if (DEBUG) Log.d(TAG, "Service Not Available to STOP, ignoring");
+ return true;
+ } else {
+ if (VERBOSE) Log.d(TAG, "Service Stoping()");
}
if (mSessionStatusHandler != null) {
- mSessionStatusHandler.removeCallbacksAndMessages(null);
- Looper looper = mSessionStatusHandler.getLooper();
- if (looper != null) {
- looper.quit();
- }
- mSessionStatusHandler = null;
+ sendShutdownMessage();
}
+ mStartError = true;
setState(BluetoothMap.STATE_DISCONNECTED, BluetoothMap.RESULT_CANCELED);
if (DEBUG) Log.d(TAG, "stop() out");
return true;
@@ -823,8 +827,9 @@ public class BluetoothMapService extends ProfileService {
public boolean cleanup() {
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(null); // Stop() should be called to handle cleanup - hence this is not needed
+ //Cleanup already handled in Stop().
+ //Move this extra check to Handler.
+ sendShutdownMessage();
return true;
}
@@ -918,13 +923,16 @@ public class BluetoothMapService extends ProfileService {
* @param masId the MasID to start. Use -1 to start all listeners.
*/
public void sendStartListenerMessage(int masId) {
- if(mSessionStatusHandler != null) {
+ if(mSessionStatusHandler != null && ! mSessionStatusHandler.hasMessages(START_LISTENER)) {
Message msg = mSessionStatusHandler.obtainMessage(START_LISTENER, masId, 0);
/* We add a small delay here to ensure the call returns true before this message is
* handled. It seems wrong to add a delay, but the alternative is to build a lock
* system to handle synchronization, which isn't nice either... */
mSessionStatusHandler.sendMessageDelayed(msg, 20);
- } // Can only be null during shutdown
+ } else if(mSessionStatusHandler != null ) {
+ if(DEBUG)
+ Log.w(TAG, "mSessionStatusHandler START_LISTENER message already in Queue");
+ }
}
private void sendConnectMessage(int masId) {
@@ -950,7 +958,8 @@ public class BluetoothMapService extends ProfileService {
} // Can only be null during shutdown
}
- private void sendShutdownMessage(CountDownLatch latch) {
+ private void sendShutdownMessage() {
+ if (VERBOSE) Log.d(TAG, "sendShutdownMessage() In");
/* Any pending messages are no longer valid.
To speed up things, simply delete them. */
if (mRemoveTimeoutMsg) {
@@ -960,23 +969,23 @@ public class BluetoothMapService extends ProfileService {
mIsWaitingAuthorization = false;
cancelUserTimeoutAlarm();
}
- if (mSessionStatusHandler != null) {
+ if (mSessionStatusHandler != null && !mSessionStatusHandler.hasMessages(SHUTDOWN)) {
mSessionStatusHandler.removeCallbacksAndMessages(null);
// Request release of all resources
- Message msg = mSessionStatusHandler.obtainMessage(SHUTDOWN,latch);
+ Message msg = mSessionStatusHandler.obtainMessage(SHUTDOWN);
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");
}
+ } else if(mSessionStatusHandler != null) {
+ if(DEBUG)
+ Log.w(TAG, "mSessionStatusHandler shutdown message already in Queue");
}
+ if (VERBOSE) Log.d(TAG, "sendShutdownMessage() Out");
}
private MapBroadcastReceiver mMapReceiver = new MapBroadcastReceiver();
@@ -992,7 +1001,7 @@ public class BluetoothMapService extends ProfileService {
BluetoothAdapter.ERROR);
if (state == BluetoothAdapter.STATE_TURNING_OFF) {
if (DEBUG) Log.d(TAG, "STATE_TURNING_OFF");
- sendShutdownMessage(null);
+ sendShutdownMessage();
} else if (state == BluetoothAdapter.STATE_ON) {
if (DEBUG) Log.d(TAG, "STATE_ON");
// start ServerSocket listener threads
diff --git a/src/com/android/bluetooth/map/BluetoothMapUtils.java b/src/com/android/bluetooth/map/BluetoothMapUtils.java
index 1537807a0..7ca55301a 100644
--- a/src/com/android/bluetooth/map/BluetoothMapUtils.java
+++ b/src/com/android/bluetooth/map/BluetoothMapUtils.java
@@ -394,15 +394,16 @@ public class BluetoothMapUtils {
static public byte[] truncateUtf8StringToBytearray(String utf8String, int maxLength)
throws UnsupportedEncodingException {
- byte[] utf8Bytes = null;
+ byte[] utf8Bytes = new byte[utf8String.length() + 1];
try {
- utf8Bytes = utf8String.getBytes("UTF-8");
+ System.arraycopy(utf8String.getBytes("UTF-8"), 0,
+ utf8Bytes, 0, utf8String.length());
} catch (UnsupportedEncodingException e) {
Log.e(TAG,"truncateUtf8StringToBytearray: getBytes exception ", e);
throw e;
}
- if (utf8Bytes.length > (maxLength - 1)) {
+ if (utf8Bytes.length > maxLength) {
/* if 'continuation' byte is in place 200,
* then strip previous bytes until utf-8 start byte is found */
if ( (utf8Bytes[maxLength - 1] & 0xC0) == 0x80 ) {
diff --git a/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java b/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java
index e1f24c253..aa2af081d 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java
@@ -34,9 +34,11 @@ public class BluetoothOppHandoverReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
+ if(D) Log.d(TAG, "Action :" + action);
+
if (action.equals(Constants.ACTION_HANDOVER_SEND) ||
action.equals(Constants.ACTION_HANDOVER_SEND_MULTIPLE)) {
- if (V) Log.v(TAG, "Transfer initiated from HANDOVER");
+
BluetoothDevice device =
(BluetoothDevice)intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device == null) {
diff --git a/src/com/android/bluetooth/opp/BluetoothOppManager.java b/src/com/android/bluetooth/opp/BluetoothOppManager.java
index 7d259e15f..8805818e5 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppManager.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppManager.java
@@ -119,8 +119,6 @@ public class BluetoothOppManager {
// The time for which the whitelist entries remain valid.
private static final int WHITELIST_DURATION_MS = 15000;
- public boolean isOPPServiceUp = false;
-
/**
* Get singleton instance.
*/
@@ -429,28 +427,17 @@ public class BluetoothOppManager {
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- while (true) {
- if (mRemoteDevice == null) {
- Log.e(TAG, "Target bt device is null!");
- return;
- }
-
- if (V) Log.v(TAG, "OPPServiceUP = " + isOPPServiceUp);
- if (isOPPServiceUp) {
- if (mIsMultiple) {
- insertMultipleShare();
- } else {
- insertSingleShare();
- }
-
- synchronized (BluetoothOppManager.this) {
- mInsertShareThreadNum--;
- }
- return;
- } else if (!isEnabled()) {
- Log.v(TAG, "BT is OFF");
- return;
- }
+ if (mRemoteDevice == null) {
+ Log.e(TAG, "Target bt device is null!");
+ return;
+ }
+ if (mIsMultiple) {
+ insertMultipleShare();
+ } else {
+ insertSingleShare();
+ }
+ synchronized (BluetoothOppManager.this) {
+ mInsertShareThreadNum--;
}
}
diff --git a/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java b/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
index d3b0c28de..7248a4d72 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
@@ -128,11 +128,13 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession {
private static final int sSleepTime = 1000;
private Uri contentUri;
private Context mContext1;
+ private volatile boolean interrupted = false;
public ContentResolverUpdateThread(Context context, Uri cntUri) {
super("BtOpp ContentResolverUpdateThread");
mContext1 = context;
contentUri = cntUri;
+ interrupted = false;
}
@@ -144,19 +146,33 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
if (V) Log.v(TAG, "Is ContentResolverUpdateThread Interrupted :" + isInterrupted());
/* Check if the Operation is interrupted before entering into loop */
- while (!isInterrupted()) {
+ while (!interrupted) {
updateValues = new ContentValues();
updateValues.put(BluetoothShare.CURRENT_BYTES, position);
mContext1.getContentResolver().update(contentUri, updateValues,
null, null);
+
+ /* Check if the Operation is interrupted before entering sleep */
+ if (interrupted) {
+ if (V) Log.v(TAG, "ContentResolverUpdateThread was interrupted before sleep !, exiting");
+ return;
+ }
+
try {
Thread.sleep(sSleepTime);
} catch (InterruptedException e1) {
if (V) Log.v(TAG, "ContentResolverUpdateThread was interrupted (1), exiting");
+ interrupted = true;
return;
}
}
}
+
+ @Override
+ public void interrupt() {
+ interrupted = true;
+ super.interrupt();
+ }
}
private class ClientThread extends Thread {
diff --git a/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java b/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java
index 39355eb40..37dd8b199 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java
@@ -112,7 +112,7 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
boolean mTransferInProgress = false;
- private int position;
+ private long position;
public BluetoothOppObexServerSession(Context context, ObexTransport transport) {
mContext = context;
@@ -183,6 +183,7 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
super("BtOpp Server ContentResolverUpdateThread");
mContext1 = context;
contentUri = cntUri;
+ interrupted = false;
}
@Override
@@ -192,14 +193,15 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
ContentValues updateValues;
if (V) Log.v(TAG, "Is ContentResolverUpdateThread Interrupted :" + isInterrupted());
/* Check if the Operation is interrupted before entering into loop */
- while ( !isInterrupted() ) {
- updateValues = new ContentValues();
- updateValues.put(BluetoothShare.CURRENT_BYTES, position);
- mContext1.getContentResolver().update(contentUri, updateValues,
- null, null);
- /* Check if the Operation is interrupted before entering sleep */
- if (isInterrupted()) {
- if (V) Log.v(TAG, "ContentResolverUpdateThread was interrupted before sleep !,"+
+ while (!interrupted) {
+
+ updateValues = new ContentValues();
+ updateValues.put(BluetoothShare.CURRENT_BYTES, position);
+ mContext1.getContentResolver().update(contentUri, updateValues,
+ null, null);
+ /* Check if the Operation is interrupted before entering sleep */
+ if (interrupted) {
+ if (V) Log.v(TAG, "ContentResolverUpdateThread was interrupted before sleep !,"+
" exiting");
return ;
}
@@ -209,9 +211,16 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
} catch (InterruptedException e1) {
if (V) Log.v(TAG, "Server ContentResolverUpdateThread was interrupted (1),"+
" exiting");
+ interrupted = true;
return ;
- }
- }
+ }
+ }
+ }
+
+ @Override
+ public void interrupt() {
+ interrupted = true;
+ super.interrupt();
}
}
/*
diff --git a/src/com/android/bluetooth/opp/BluetoothOppReceiver.java b/src/com/android/bluetooth/opp/BluetoothOppReceiver.java
index 1479646eb..b4626c0be 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppReceiver.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppReceiver.java
@@ -48,7 +48,6 @@ import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;
-import com.android.bluetooth.Utils;
/**
* Receives and handles: system broadcasts; Intents from other applications;
@@ -62,13 +61,8 @@ public class BluetoothOppReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
+ if (D) Log.d(TAG, "Action :" + action);
- /* Ignore if Broadcast action is not transfer complete and Invalid user */
- if (!Utils.checkCaller() && !action.equals(BluetoothShare.TRANSFER_COMPLETED_ACTION)) {
- Log.w(TAG, action + " received for non-active user, ignoring!!");
- return;
- }
- if (V) Log.v(TAG, action + " Intent received for active user");
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
if (BluetoothAdapter.STATE_ON == intent.getIntExtra(
diff --git a/src/com/android/bluetooth/opp/BluetoothOppService.java b/src/com/android/bluetooth/opp/BluetoothOppService.java
index 27519cc5b..c70d0fe17 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppService.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppService.java
@@ -148,8 +148,6 @@ public class BluetoothOppService extends Service {
*/
private BluetoothOppObexServerSession mServerSession;
- BluetoothOppManager mOppManager = null;
-
@Override
public IBinder onBind(Intent arg0) {
throw new UnsupportedOperationException("Cannot bind to Bluetooth OPP Service");
@@ -158,7 +156,7 @@ public class BluetoothOppService extends Service {
@Override
public void onCreate() {
super.onCreate();
- if (V) Log.v(TAG, "onCreate");
+ if (D) Log.d(TAG, "onCreate");
mAdapter = BluetoothAdapter.getDefaultAdapter();
mShares = Lists.newArrayList();
mBatchs = Lists.newArrayList();
@@ -170,11 +168,12 @@ public class BluetoothOppService extends Service {
mNotifier.updateNotification();
final ContentResolver contentResolver = getContentResolver();
- synchronized (BluetoothOppService.this) {
- trimDatabase(contentResolver);
- }
+ new Thread("trimDatabase") {
+ public void run() {
+ trimDatabase(contentResolver);
+ }
+ }.start();
- mOppManager = BluetoothOppManager.getInstance(this);
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(mBluetoothReceiver, filter);
@@ -184,7 +183,6 @@ public class BluetoothOppService extends Service {
} else {
startListener();
}
- mOppManager.isOPPServiceUp = true;
}
if (V) BluetoothOppPreference.getInstance(this).dump();
updateFromProvider();
@@ -396,7 +394,6 @@ public class BluetoothOppService extends Service {
public void onDestroy() {
if (V) Log.v(TAG, "onDestroy");
super.onDestroy();
- mOppManager.isOPPServiceUp = false;
getContentResolver().unregisterContentObserver(mObserver);
unregisterReceiver(mBluetoothReceiver);
if(mSocketListener != null) {
@@ -658,9 +655,9 @@ public class BluetoothOppService extends Service {
cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.VISIBILITY)),
cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION)),
cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.STATUS)),
- cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES)),
- cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES)),
- cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP)),
+ cursor.getLong(cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES)),
+ cursor.getLong(cursor.getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES)),
+ cursor.getLong(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP)),
cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) != Constants.MEDIA_SCANNED_NOT_SCANNED);
if (V) {
@@ -808,10 +805,10 @@ public class BluetoothOppService extends Service {
}
info.mStatus = newStatus;
- info.mTotalBytes = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES));
- info.mCurrentBytes = cursor.getInt(cursor
+ info.mTotalBytes = cursor.getLong(cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES));
+ info.mCurrentBytes = cursor.getLong(cursor
.getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES));
- info.mTimestamp = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP));
+ info.mTimestamp = cursor.getLong(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP));
info.mMediaScanned = (cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) != Constants.MEDIA_SCANNED_NOT_SCANNED);
if (confirmUpdated) {
diff --git a/src/com/android/bluetooth/opp/BluetoothOppShareInfo.java b/src/com/android/bluetooth/opp/BluetoothOppShareInfo.java
index 32f6b3cb3..cb35f6da0 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppShareInfo.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppShareInfo.java
@@ -60,17 +60,18 @@ public class BluetoothOppShareInfo {
public int mStatus;
- public int mTotalBytes;
+ public long mTotalBytes;
- public int mCurrentBytes;
+ public long mCurrentBytes;
public long mTimestamp;
public boolean mMediaScanned;
public BluetoothOppShareInfo(int id, Uri uri, String hint, String filename, String mimetype,
- int direction, String destination, int visibility, int confirm, int status,
- int totalBytes, int currentBytes, int timestamp, boolean mediaScanned) {
+ int direction, String destination, int visibility, int confirm, int status,
+ long totalBytes, long currentBytes, long timestamp, boolean mediaScanned) {
+
mId = id;
mUri = uri;
mHint = hint;
@@ -96,6 +97,7 @@ public class BluetoothOppShareInfo {
if (mStatus == BluetoothShare.STATUS_PENDING && mUri != null) {
return true;
}
+
} else if (mDirection == BluetoothShare.DIRECTION_INBOUND) {
if (mStatus == BluetoothShare.STATUS_PENDING) {
//&& mConfirm != BluetoothShare.USER_CONFIRMATION_PENDING) {
diff --git a/src/com/android/bluetooth/opp/BluetoothOppTransfer.java b/src/com/android/bluetooth/opp/BluetoothOppTransfer.java
index 3943ea164..c4960d4f1 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppTransfer.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppTransfer.java
@@ -535,6 +535,7 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
if (mBluetoothReceiver != null){
mContext.unregisterReceiver(mBluetoothReceiver);
mBluetoothReceiver = null;
+ if (V) Log.v(TAG, "Un Registered mBluetoothReceiver");
}
} catch (Exception e) {
Log.e(TAG, "Exception:unregisterReceiver");
@@ -566,10 +567,17 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
mConnectThread = new SocketConnectThread("localhost", Constants.TCP_DEBUG_PORT, 0);
mConnectThread.start();
} else {
- OolConnManager.setSdpInitiatedAddress(mBatch.mDestination);
- mBatch.mDestination.sdpSearch(BluetoothUuid.ObexObjectPush);
- mConnectThread = new SocketConnectThread(mBatch.mDestination,false);
- mConnectThread.start();
+ OolConnManager.setSdpInitiatedAddress(mBatch.mDestination);
+ if (!mBatch.mDestination.sdpSearch(BluetoothUuid.ObexObjectPush)) {
+ /* SDP failed, start rfcomm connect directly */
+ mConnectThread = new SocketConnectThread(mBatch.mDestination, false, false);
+ /* update bd address as sdp could not be started */
+ OolConnManager.setSdpInitiatedAddress(null);
+ } else {
+ /* SDP sucessfully started, start l2cap connect after sdp completes */
+ mConnectThread = new SocketConnectThread(mBatch.mDestination, false, true);
+ }
+ mConnectThread.start();
}
}
@@ -592,6 +600,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
private boolean mRetry = false;
+ private boolean mSdpInitiated = false;
+
/* create a TCP socket */
public SocketConnectThread(String host, int port, int dummy) {
super("Socket Connect Thread");
@@ -599,9 +609,10 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
this.channel = port;
this.device = null;
isConnected = false;
+ mSdpInitiated = false;
}
- /* create a Rfcomm Socket */
+ /* create a Rfcomm/L2CAP Socket */
public SocketConnectThread(BluetoothDevice device, int channel, boolean
retry) {
super("Socket Connect Thread");
@@ -610,17 +621,30 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
this.channel = channel;
isConnected = false;
mRetry = retry;
+ mSdpInitiated = false;
}
- /* create a Rfcomm Socket */
- public SocketConnectThread(BluetoothDevice device, boolean
- retry) {
+ /* create a Rfcomm/L2CAP Socket */
+ public SocketConnectThread(BluetoothDevice device, boolean retry) {
+ super("Socket Connect Thread");
+ this.device = device;
+ this.host = null;
+ this.channel = -1;
+ isConnected = false;
+ mRetry = retry;
+ mSdpInitiated = false;
+ }
+
+ /* create a Rfcomm/L2CAP Socket */
+ public SocketConnectThread(BluetoothDevice device, boolean retry,
+ boolean sdpInitiated) {
super("Socket Connect Thread");
this.device = device;
this.host = null;
this.channel = -1;
isConnected = false;
mRetry = retry;
+ mSdpInitiated = sdpInitiated;
}
public void interrupt() {
@@ -744,11 +768,32 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
return ;
}
+ Log.d(TAG, "sdp initiated = " + mSdpInitiated);
+
+ // check if sdp initiated successfully for l2cap or not. If not connect
+ // directly to rfcomm
+ if (!mSdpInitiated) {
+ /* sdp failed for some reason, connect on rfcomm */
+ Log.d(TAG, "sdp not initiated, connecting on rfcomm");
+ connectRfcommSocket();
+ return;
+ }
+
+ /* Reset the flag */
+ mSdpInitiated = false;
+
/* Use BluetoothSocket to connect */
l2cChannel = 0;
try {
l2cChannel = OolConnManager.getL2cPSM(device);
- btSocket = device.createInsecureL2capSocket(l2cChannel);
+ if (l2cChannel > 0) {
+ Log.d(TAG, "Connecting to l2cap psm = " + l2cChannel);
+ btSocket = device.createInsecureL2capSocket(l2cChannel);
+ } else {
+ Log.d(TAG, "L2cap psm not found, connecting on rfcomm");
+ connectRfcommSocket();
+ return;
+ }
} catch (IOException e1) {
Log.e(TAG, "L2cap socket create error",e1);
connectRfcommSocket();
diff --git a/src/com/android/bluetooth/pbap/BluetoothPbapService.java b/src/com/android/bluetooth/pbap/BluetoothPbapService.java
index dcfc5c209..6cfd71339 100644
--- a/src/com/android/bluetooth/pbap/BluetoothPbapService.java
+++ b/src/com/android/bluetooth/pbap/BluetoothPbapService.java
@@ -200,10 +200,6 @@ public class BluetoothPbapService extends Service {
mInterrupted = false;
mAdapter = BluetoothAdapter.getDefaultAdapter();
- if (!Utils.checkCaller()) {
- Log.w(TAG, "onCreate received for non-active user, ignoring");
- return;
- }
if (!mHasStarted) {
mHasStarted = true;
diff --git a/src/com/android/bluetooth/sap/SapMessage.java b/src/com/android/bluetooth/sap/SapMessage.java
index 451d9280c..251c67e1a 100644
--- a/src/com/android/bluetooth/sap/SapMessage.java
+++ b/src/com/android/bluetooth/sap/SapMessage.java
@@ -26,8 +26,8 @@ import android.util.Log;
public class SapMessage {
public static final String TAG = "SapMessage";
- public static final boolean DEBUG = Log.isLoggable(SapService.LOG_TAG, Log.DEBUG);
- public static final boolean VERBOSE = Log.isLoggable(SapService.LOG_TAG, Log.VERBOSE);
+ public static final boolean DEBUG = true;
+ public static final boolean VERBOSE = SapService.VERBOSE;
public static final boolean TEST = false;
/* Message IDs - SAP specification */
@@ -721,6 +721,7 @@ public class SapMessage {
msg.setType(SapApi.REQUEST);
msg.setError(SapApi.RIL_E_UNUSED);
+ if(DEBUG) Log.d(TAG, "Writing request, message type:" + mMsgType);
switch(mMsgType) {
case ID_CONNECT_REQ:
{
diff --git a/src/com/android/bluetooth/sap/SapRilReceiver.java b/src/com/android/bluetooth/sap/SapRilReceiver.java
index 6cfd6db84..542519344 100644
--- a/src/com/android/bluetooth/sap/SapRilReceiver.java
+++ b/src/com/android/bluetooth/sap/SapRilReceiver.java
@@ -18,7 +18,7 @@ import android.util.Log;
public class SapRilReceiver implements Runnable {
private static final String TAG = "SapRilReceiver";
- public static final boolean DEBUG = Log.isLoggable(SapService.LOG_TAG, Log.DEBUG);
+ public static final boolean DEBUG = true;
public static final boolean VERBOSE = Log.isLoggable(SapService.LOG_TAG, Log.VERBOSE);
private static final String SOCKET_NAME_RIL_BT = "sap_uim_socket1";
diff --git a/src/com/android/bluetooth/sap/SapServer.java b/src/com/android/bluetooth/sap/SapServer.java
index d8c24722f..c30e63bfc 100644
--- a/src/com/android/bluetooth/sap/SapServer.java
+++ b/src/com/android/bluetooth/sap/SapServer.java
@@ -50,8 +50,8 @@ import com.google.protobuf.micro.CodedOutputStreamMicro;
public class SapServer extends Thread implements Callback {
private static final String TAG = "SapServer";
private static final String TAG_HANDLER = "SapServerHandler";
- public static final boolean DEBUG = Log.isLoggable(SapService.LOG_TAG, Log.DEBUG);
- public static final boolean VERBOSE = Log.isLoggable(SapService.LOG_TAG, Log.VERBOSE);
+ public static final boolean DEBUG = true;
+ public static final boolean VERBOSE = SapService.VERBOSE;
private enum SAP_STATE {
DISCONNECTED, CONNECTING, CONNECTING_CALL_ONGOING, CONNECTED,
@@ -198,6 +198,7 @@ public class SapServer extends Thread implements Callback {
} else {
SapMessage msg = new SapMessage(SapMessage.ID_DISCONNECT_REQ);
/* Force disconnect of RFCOMM - but first we need to clean up. */
+ if(DEBUG) Log.d(TAG, "Cleaning up before force disconnecting rfcomm");
clearPendingRilResponses(msg);
/* We simply need to forward to RIL, but not change state to busy - hence send and set
diff --git a/src/com/android/bluetooth/sap/SapService.java b/src/com/android/bluetooth/sap/SapService.java
index 9199d7fd1..a02afc648 100644
--- a/src/com/android/bluetooth/sap/SapService.java
+++ b/src/com/android/bluetooth/sap/SapService.java
@@ -4,7 +4,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
-import java.util.concurrent.CountDownLatch;
import android.annotation.TargetApi;
import android.app.AlarmManager;
@@ -50,7 +49,7 @@ public class SapService extends ProfileService {
private static final int SDP_SAP_VERSION = 0x0102;
private static final String TAG = "SapService";
public static final String LOG_TAG = "BluetoothSap";
- public static boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
+ public static boolean DEBUG = true;
public static boolean VERBOSE = Log.isLoggable(LOG_TAG, Log.VERBOSE);
/* Message ID's */
@@ -79,7 +78,7 @@ public class SapService extends ProfileService {
/* Intent indicating timeout for user confirmation. */
public static final String USER_CONFIRM_TIMEOUT_ACTION =
"com.android.bluetooth.sap.USER_CONFIRM_TIMEOUT";
- private static final int USER_CONFIRM_TIMEOUT_VALUE = 25000;
+ private static final int USER_CONFIRM_TIMEOUT_VALUE = 30000;
private PowerManager.WakeLock mWakeLock = null;
private BluetoothAdapter mAdapter;
@@ -129,17 +128,20 @@ public class SapService extends ProfileService {
}
private void startRfcommSocketListener() {
- if (VERBOSE) Log.v(TAG, "Sap Service startRfcommSocketListener");
+ if (DEBUG) Log.d(TAG, "Sap Service startRfcommSocketListener");
if (mAcceptThread == null) {
+ Log.d(TAG, "Sap Service startRfcommSocketListener");
mAcceptThread = new SocketAcceptThread();
mAcceptThread.setName("SapAcceptThread");
mAcceptThread.start();
+ } else {
+ Log.d(TAG, "Sap Service Already ON: startRfcommSocketListener");
}
}
private final boolean initSocket() {
- if (VERBOSE) Log.v(TAG, "Sap Service initSocket");
+ if (DEBUG) Log.d(TAG, "Sap Service initSocket");
boolean initSocketOK = false;
final int CREATE_RETRY_TIME = 10;
@@ -201,7 +203,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");
+ if (DEBUG) Log.d(TAG, "Closing server socket");
mServerSocket.close();
mServerSocket = null;
} catch (IOException ex) {
@@ -213,7 +215,7 @@ public class SapService extends ProfileService {
private final synchronized void closeConnectionSocket() {
if (mConnSocket != null) {
try {
- if (VERBOSE) Log.v(TAG, "Closing conenction socket");
+ if (DEBUG) Log.d(TAG, "Closing conenction socket");
mConnSocket.close();
mConnSocket = null;
} catch (IOException e) {
@@ -222,8 +224,8 @@ public class SapService extends ProfileService {
}
}
- synchronized private final void closeService(CountDownLatch latch) {
- if (VERBOSE) Log.v(TAG, "SAP Service closeService in");
+ synchronized private final void closeService() {
+ if (DEBUG) Log.d(TAG, "SAP Service closeService in");
// exit initSocket early
mInterrupted = true;
@@ -243,9 +245,20 @@ public class SapService extends ProfileService {
}
releaseWakeLockResources();
- if(latch != null) {
- latch.countDown();
+ /* Only one SHUTDOWN message expected to closeService.
+ * Hence, quit looper and Handler on first SHUTDOWN message*/
+ if (mSessionStatusHandler != null) {
+ //Perform cleanup in Handler running on worker Thread
+ mSessionStatusHandler.removeCallbacksAndMessages(null);
+ Looper looper = mSessionStatusHandler.getLooper();
+ if (looper != null) {
+ looper.quit();
+ if(VERBOSE) Log.i(TAG, "Quit looper");
+ }
+ mSessionStatusHandler = null;
+ if(VERBOSE) Log.i(TAG, "Remove Handler");
}
+
if (VERBOSE) Log.v(TAG, "SAP Service closeService out");
}
@@ -278,7 +291,7 @@ public class SapService extends ProfileService {
}
private synchronized void startSapServerSession() throws IOException {
- if (VERBOSE) Log.v(TAG, "Sap Service startSapServerSession");
+ if (DEBUG) Log.d(TAG, "Sap Service startSapServerSession");
// acquire the wakeLock before start SAP transaction thread
if (mWakeLock == null) {
@@ -309,7 +322,7 @@ public class SapService extends ProfileService {
/* When we reach this point, the SapServer is closed down, and the client is
* supposed to close the RFCOMM connection. */
- if (VERBOSE) Log.v(TAG, "SAP Service stopSapServerSession");
+ if (DEBUG) Log.d(TAG, "SAP Service stopSapServerSession");
mAcceptThread = null;
closeConnectionSocket();
@@ -318,7 +331,8 @@ public class SapService extends ProfileService {
setState(BluetoothSap.STATE_DISCONNECTED);
awaitSapServerSessionStop();
-
+ // Extra check to startListener if already not available
+ // This will not actually restart listener on every connect/disconnect.
// Last SAP transaction is finished, we start to listen for incoming
// rfcomm connection again
if (mAdapter.isEnabled()) {
@@ -471,7 +485,8 @@ public class SapService extends ProfileService {
if (VERBOSE) Log.v(TAG, "Release Wake Lock request message");
if (mWakeLock != null) {
mWakeLock.release();
- if (DEBUG) Log.d(TAG, " Released Wake Lock by message");
+ mWakeLock = null;
+ Log.w(TAG, "Release Wake Lock");
}
break;
case MSG_CHANGE_STATE:
@@ -479,10 +494,7 @@ public class SapService extends ProfileService {
setState(msg.arg1);
break;
case SHUTDOWN:
- /* Ensure to call close from this handler to avoid starting new stuff
- because of pending messages */
- CountDownLatch latch = (CountDownLatch)msg.obj;
- closeService(latch);
+ closeService();
break;
default:
break;
@@ -648,7 +660,7 @@ public class SapService extends ProfileService {
@Override
protected boolean stop() {
- if (VERBOSE) Log.v(TAG, "Stoping SAPService");
+ if (DEBUG) Log.d(TAG, "Stoping SAPService");
if (!mIsRegistered){
Log.i(TAG, "Avoid unregister when receiver it is not registered");
@@ -661,34 +673,19 @@ public class SapService extends ProfileService {
Log.w(TAG,"Unable to unregister sap receiver",e);
}
setState(BluetoothSap.STATE_DISCONNECTED, BluetoothSap.RESULT_CANCELED, true);
- 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 {
- 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;
- }
+
+ if (mSessionStatusHandler != null)
+ sendShutdownMessage();
+
if(DEBUG) Log.v(TAG, "stop() out");
return true;
}
public boolean cleanup() {
setState(BluetoothSap.STATE_DISCONNECTED, BluetoothSap.RESULT_CANCELED, true);
- closeService(null); // No latch needed as the call is blocking
- if(mSessionStatusHandler != null) {
- mSessionStatusHandler.removeCallbacksAndMessages(null);
- }
+ //Cleanup already handled in Stop().
+ //Move this extra check to Handler.
+ sendShutdownMessage();
return true;
}
@@ -725,7 +722,7 @@ public class SapService extends ProfileService {
sendBroadcast(intent, BLUETOOTH_PERM);
}
- private void sendShutdownMessage(CountDownLatch latch) {
+ private void sendShutdownMessage() {
/* Any pending messages are no longer valid.
To speed up things, simply delete them. */
if (mRemoveTimeoutMsg) {
@@ -745,20 +742,20 @@ public class SapService extends ProfileService {
if (mSessionStatusHandler != null) {
mSessionStatusHandler.removeCallbacksAndMessages(null);
// Request release of all resources
- Message msg = mSessionStatusHandler.obtainMessage(SHUTDOWN,latch);
+ Message msg = mSessionStatusHandler.obtainMessage(SHUTDOWN);
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 (mSessionStatusHandler != null) {
+ if(DEBUG) Log.w(TAG, "mSessionStatusHandler shutdown message already in Queue");
}
+
+ if (VERBOSE) Log.d(TAG, "sendShutdownMessage() Out");
}
private void sendConnectTimeoutMessage() {
@@ -782,7 +779,7 @@ public class SapService extends ProfileService {
BluetoothAdapter.ERROR);
if (state == BluetoothAdapter.STATE_TURNING_OFF) {
if (DEBUG) Log.d(TAG, "STATE_TURNING_OFF");
- sendShutdownMessage(null);
+ sendShutdownMessage();
} else if (state == BluetoothAdapter.STATE_ON) {
if (DEBUG) Log.d(TAG, "STATE_ON");
// start RFCOMM listener