summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2014-12-18 16:40:16 -0800
committerSteve Kondik <steve@cyngn.com>2014-12-18 16:40:16 -0800
commit73b826f84b9a6337b3d36b2b1aed0ebff997421c (patch)
tree651cc6ebd91cc4e6f084a67cb9b12638a561e5a4
parent7897776ccedf883cd137ca8ccab6d180ba243e0f (diff)
parent2b582a6914f8e13a261b5a66567517ac62074f74 (diff)
downloadandroid_packages_apps_Bluetooth-73b826f84b9a6337b3d36b2b1aed0ebff997421c.tar.gz
android_packages_apps_Bluetooth-73b826f84b9a6337b3d36b2b1aed0ebff997421c.tar.bz2
android_packages_apps_Bluetooth-73b826f84b9a6337b3d36b2b1aed0ebff997421c.zip
Merge branch 'LA.BF.1.1_rb1.16' of git://codeaurora.org/platform/packages/apps/Bluetooth into cm-12.0
-rw-r--r--jni/com_android_bluetooth_avrcp.cpp22
-rw-r--r--src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java2
-rw-r--r--src/com/android/bluetooth/avrcp/Avrcp.java365
-rwxr-xr-xsrc/com/android/bluetooth/btservice/AdapterService.java2
-rw-r--r--src/com/android/bluetooth/btservice/AdapterState.java2
-rw-r--r--src/com/android/bluetooth/btservice/BondStateMachine.java10
-rw-r--r--src/com/android/bluetooth/btservice/RemoteDevices.java2
-rw-r--r--src/com/android/bluetooth/gatt/AdvertiseManager.java26
-rw-r--r--src/com/android/bluetooth/gatt/GattService.java70
-rw-r--r--src/com/android/bluetooth/gatt/ScanManager.java67
-rw-r--r--src/com/android/bluetooth/hdp/HealthService.java36
-rw-r--r--src/com/android/bluetooth/hfp/HeadsetStateMachine.java96
-rw-r--r--src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java26
-rw-r--r--src/com/android/bluetooth/map/BluetoothMapContentObserver.java8
-rwxr-xr-xsrc/com/android/bluetooth/map/BluetoothMapbMessageMmsEmail.java6
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppNotification.java98
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java27
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java30
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppProvider.java10
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java2
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java2
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppService.java81
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppTransfer.java26
-rw-r--r--src/com/android/bluetooth/opp/BluetoothShare.java12
24 files changed, 689 insertions, 339 deletions
diff --git a/jni/com_android_bluetooth_avrcp.cpp b/jni/com_android_bluetooth_avrcp.cpp
index eaed3bd5d..a8ff2c986 100644
--- a/jni/com_android_bluetooth_avrcp.cpp
+++ b/jni/com_android_bluetooth_avrcp.cpp
@@ -304,8 +304,8 @@ static void btavrcp_volume_change_callback(uint8_t volume, uint8_t ctype) {
static void btavrcp_get_folder_items_callback(btrc_browse_folderitem_t scope ,
btrc_getfolderitem_t *param) {
- jint start = param->start_item;
- jint end = param->end_item;
+ jlong start = param->start_item;
+ jlong end = param->end_item;
jint size = param->size;
jint num_attr = param->attr_count;
jintArray attrs;
@@ -516,7 +516,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
env->GetMethodID(clazz, "setAddressedPlayer", "(I)V");
//getFolderItems: attributes to pass: Scope, Start, End, Attr Cnt
method_getFolderItems =
- env->GetMethodID(clazz, "getFolderItems", "(BIIII[I)V");
+ env->GetMethodID(clazz, "getFolderItems", "(BJJII[I)V");
method_setBrowsedPlayer =
env->GetMethodID(clazz, "setBrowsedPlayer", "(I)V");
method_changePath =
@@ -1081,7 +1081,7 @@ static jboolean registerNotificationRspNowPlayingContentChangedNative(JNIEnv *en
}
static jboolean getFolderItemsRspNative(JNIEnv *env, jobject object, jbyte statusCode,
- jint numItems, jintArray itemType, jlongArray uid, jintArray type,
+ jlong numItems, jintArray itemType, jlongArray uid, jintArray type,
jbyteArray playable, jobjectArray displayName, jbyteArray numAtt,
jobjectArray attValues, jintArray attIds) {
bt_status_t status = BT_STATUS_SUCCESS;
@@ -1158,6 +1158,10 @@ static jboolean getFolderItemsRspNative(JNIEnv *env, jobject object, jbyte statu
param.p_item_list[count].u.folder.playable = playableElements[count];
text = (jstring) env->GetObjectArrayElement(displayName, count);
+ if (text == NULL) {
+ ALOGE("getFolderItemsRspNative: App string is NULL, bail out");
+ break;
+ }
utfStringLength = env->GetStringUTFLength(text);
if (!utfStringLength) {
ALOGE("getFolderItemsRspNative: GetStringUTFLength return NULL");
@@ -1186,6 +1190,10 @@ static jboolean getFolderItemsRspNative(JNIEnv *env, jobject object, jbyte statu
param.p_item_list[count].u.media.type = (uint8_t)typeElements[count];
ALOGI("getFolderItemsRspNative: type: %d", param.p_item_list[count].u.folder.type);
text = (jstring) env->GetObjectArrayElement(displayName, count);
+ if (text == NULL) {
+ ALOGE("getFolderItemsRspNative: App string is NULL, bail out");
+ break;
+ }
utfStringLength = env->GetStringUTFLength(text);
if (!utfStringLength) {
ALOGE("getFolderItemsRspNative: GetStringUTFLength return NULL");
@@ -1213,6 +1221,10 @@ static jboolean getFolderItemsRspNative(JNIEnv *env, jobject object, jbyte statu
for (int i = 0; i < numAttElements[count]; i++) {
text = (jstring) env->GetObjectArrayElement(attValues, (7 * count) + i);
+ if (text == NULL) {
+ ALOGE("getFolderItemsRspNative: Attribute string is NULL, continue to next");
+ continue;
+ }
utfStringLength = env->GetStringUTFLength(text);
if (!utfStringLength) {
ALOGE("getFolderItemsRspNative: GetStringUTFLength return NULL");
@@ -1594,7 +1606,7 @@ static JNINativeMethod sMethods[] = {
{"changePathRspNative", "(IJ)Z", (void *) changePathRspNative},
{"playItemRspNative", "(I)Z", (void *) playItemRspNative},
{"getItemAttrRspNative", "(B[I[Ljava/lang/String;)Z", (void *) getItemAttrRspNative},
- {"getFolderItemsRspNative", "(BI[I[J[I[B[Ljava/lang/String;[B[Ljava/lang/String;[I)Z",
+ {"getFolderItemsRspNative", "(BJ[I[J[I[B[Ljava/lang/String;[B[Ljava/lang/String;[I)Z",
(void *) getFolderItemsRspNative},
};
diff --git a/src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java b/src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java
index 2f1f3d9cc..13c4ade46 100644
--- a/src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java
+++ b/src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java
@@ -619,7 +619,7 @@ final class A2dpSinkStateMachine extends StateMachine {
mPlayingDevice = null;
broadcastAudioState(device, BluetoothA2dpSink.STATE_NOT_PLAYING,
BluetoothA2dpSink.STATE_PLAYING);
- if ((mAudioFocusAcquired == AUDIO_FOCUS_LOSS_TRANSIENT) ||
+ if ((mAudioFocusAcquired == AUDIO_FOCUS_LOSS_TRANSIENT) &&
(state == AUDIO_STATE_REMOTE_SUSPEND)) {
log(" Dont't Loose audiofocus in case of suspend ");
break;
diff --git a/src/com/android/bluetooth/avrcp/Avrcp.java b/src/com/android/bluetooth/avrcp/Avrcp.java
index 095f0ed6c..3b7a4bfc6 100644
--- a/src/com/android/bluetooth/avrcp/Avrcp.java
+++ b/src/com/android/bluetooth/avrcp/Avrcp.java
@@ -310,6 +310,7 @@ public final class Avrcp {
private final String UPDATE_ATTRIB_TEXT = "UpdateAttributesText";
private final String UPDATE_VALUE_TEXT = "UpdateValuesText";
private ArrayList <Integer> mPendingCmds;
+ private ArrayList <Integer> mPendingSetAttributes;
static {
classInitNative();
@@ -359,6 +360,7 @@ public final class Avrcp {
Looper looper = thread.getLooper();
mHandler = new AvrcpMessageHandler(looper);
mPendingCmds = new ArrayList<Integer>();
+ mPendingSetAttributes = new ArrayList<Integer>();
mCurrentPath = PATH_INVALID;
mCurrentPathUid = null;
mMediaUri = Uri.EMPTY;
@@ -402,14 +404,19 @@ public final class Avrcp {
GET_INVALID);
byte [] data;
String [] text;
+ boolean isSetAttrValRsp = false;
synchronized (mPendingCmds) {
Integer val = new Integer(getResponse);
if (mPendingCmds.contains(val)) {
+ if (getResponse == SET_ATTRIBUTE_VALUES) {
+ isSetAttrValRsp = true;
+ if (DEBUG) Log.v(TAG,"Response received for SET_ATTRIBUTE_VALUES");
+ }
mHandler.removeMessages(MESSAGE_PLAYERSETTINGS_TIMEOUT);
mPendingCmds.remove(val);
}
}
- if (DEBUG) Log.v(TAG,"getResponse" + getResponse);
+ if (DEBUG) Log.v(TAG,"getResponse " + getResponse);
switch (getResponse) {
case GET_ATTRIBUTE_IDS:
data = intent.getByteArrayExtra(EXTRA_ATTIBUTE_ID_ARRAY);
@@ -420,35 +427,34 @@ public final class Avrcp {
case GET_VALUE_IDS:
data = intent.getByteArrayExtra(EXTRA_VALUE_ID_ARRAY);
numAttr = (byte) data.length;
- if (DEBUG) Log.v(TAG,"GET_VALUE_IDS" + numAttr);
+ if (DEBUG) Log.v(TAG,"GET_VALUE_IDS " + numAttr);
getPlayerAppValueRspNative(numAttr, data);
break;
case GET_ATTRIBUTE_VALUES:
data = intent.getByteArrayExtra(EXTRA_ATTRIB_VALUE_PAIRS);
updateLocalPlayerSettings(data);
numAttr = (byte) data.length;
- if (DEBUG) Log.v(TAG,"GET_ATTRIBUTE_VALUES" + numAttr);
+ if (DEBUG) Log.v(TAG,"GET_ATTRIBUTE_VALUES " + numAttr);
SendCurrentPlayerValueRspNative(numAttr, data);
break;
case SET_ATTRIBUTE_VALUES:
data = intent.getByteArrayExtra(EXTRA_ATTRIB_VALUE_PAIRS);
updateLocalPlayerSettings(data);
- Log.v(TAG,"SET_ATTRIBUTE_VALUES: " + data[0] + ", " + data[1]);
- if (data[0] == ATTRIBUTE_EQUALIZER ||
- data[0] == ATTRIBUTE_REPEATMODE ||
- data[0] == ATTRIBUTE_SHUFFLEMODE) {
- if (mPlayerStatusChangeNT == NOTIFICATION_TYPE_INTERIM) {
- Log.v(TAG,"Send Player appl attribute changed response");
- mPlayerStatusChangeNT = NOTIFICATION_TYPE_CHANGED;
- sendPlayerAppChangedRsp(mPlayerStatusChangeNT);
+ Log.v(TAG,"SET_ATTRIBUTE_VALUES: ");
+ if (isSetAttrValRsp){
+ isSetAttrValRsp = false;
+ Log.v(TAG,"Respond to SET_ATTRIBUTE_VALUES request");
+ if (checkPlayerAttributeResponse(data)) {
+ SendSetPlayerAppRspNative(OPERATION_SUCCESSFUL);
} else {
- Log.v(TAG,"Respond to SET_ATTRIBUTE_VALUES request");
- if (data[1] == ATTRIBUTE_NOTSUPPORTED) {
- SendSetPlayerAppRspNative(INTERNAL_ERROR);
- } else {
- SendSetPlayerAppRspNative(OPERATION_SUCCESSFUL);
- }
+ SendSetPlayerAppRspNative(INTERNAL_ERROR);
}
+ } else if (mPlayerStatusChangeNT == NOTIFICATION_TYPE_INTERIM) {
+ Log.v(TAG,"Send Player appl attribute changed response");
+ mPlayerStatusChangeNT = NOTIFICATION_TYPE_CHANGED;
+ sendPlayerAppChangedRsp(mPlayerStatusChangeNT);
+ } else {
+ Log.v(TAG,"Drop Set Attr Val update from media player");
}
break;
case GET_ATTRIBUTE_TEXT:
@@ -1259,8 +1265,8 @@ public final class Avrcp {
void updateNowPlayingEntriesReceived(long[] playList) {
int status = OPERATION_SUCCESSFUL;
int numItems = 0;
- int reqItems = (mCachedRequest.mEnd - mCachedRequest.mStart) + 1;
- int availableItems = 0;
+ long reqItems = (mCachedRequest.mEnd - mCachedRequest.mStart) + 1;
+ long availableItems = 0;
Cursor cursor = null;
int[] itemType = new int[MAX_BROWSE_ITEM_TO_SEND];
long[] uid = new long[MAX_BROWSE_ITEM_TO_SEND];
@@ -1288,7 +1294,7 @@ public final class Avrcp {
return;
}
- if ((mCachedRequest.mStart < 0) || (mCachedRequest.mEnd< 0) ||
+ if ((mCachedRequest.mStart < 0) || (mCachedRequest.mEnd < 0) ||
(mCachedRequest.mStart > mCachedRequest.mEnd)) {
Log.i(TAG, "wrong start / end index");
getFolderItemsRspNative((byte)RANGE_OUT_OF_BOUNDS, numItems, itemType, uid, type,
@@ -1297,18 +1303,23 @@ public final class Avrcp {
}
availableItems = availableItems - mCachedRequest.mStart;
+ Log.i(TAG, "start Index: " + mCachedRequest.mStart);
+ Log.i(TAG, "end Index: " + mCachedRequest.mEnd);
+ Log.i(TAG, "availableItems: " + availableItems);
if (availableItems > MAX_BROWSE_ITEM_TO_SEND)
availableItems = MAX_BROWSE_ITEM_TO_SEND;
if (reqItems > availableItems)
reqItems = availableItems;
+ Log.i(TAG, "reqItems: " + reqItems);
for (index = 0; index < reqItems; index++) {
try {
cursor = mContext.getContentResolver().query(
mMediaUri, mCursorCols,
MediaStore.Audio.Media.IS_MUSIC + "=1 AND _id=" +
- playList[index], null, null);
+ playList[index + (int)mCachedRequest.mStart], null, null);
if (cursor != null) {
+ int validAttrib = 0;
cursor.moveToFirst();
itemType[index] = TYPE_MEDIA_ELEMENT_ITEM;
uid[index] = cursor.getLong(cursor.getColumnIndexOrThrow("_id"));
@@ -1316,20 +1327,25 @@ public final class Avrcp {
playable[index] = 0;
displayName[index] = cursor.getString(cursor.getColumnIndexOrThrow(
MediaStore.Audio.Media.TITLE));
- numAtt[index] = mCachedRequest.mAttrCnt;
for (int attIndex = 0; attIndex < mCachedRequest.mAttrCnt; attIndex++) {
int attr = mCachedRequest.mAttrList.get(attIndex).intValue();
- attValues[(7 * index) + attIndex] = getAttributeStringFromCursor(
- cursor, attr);
- attIds[(7 * index) + attIndex] = attr;
+ if ((attr <= MEDIA_ATTR_MAX) && (attr >= MEDIA_ATTR_MIN)) {
+ attValues[(7 * index) + attIndex] =
+ getAttributeStringFromCursor(cursor, attr);
+ attIds[(7 * index) + attIndex] = attr;
+ validAttrib ++;
+ }
}
- cursor.close();
+ numAtt[index] = (byte)validAttrib;
}
} catch(Exception e) {
- Log.i(TAG, "Exception e"+ e);
- cursor.close();
+ Log.i(TAG, "Exception "+ e);
getFolderItemsRspNative((byte)INTERNAL_ERROR, numItems, itemType,
uid, type, playable, displayName, numAtt, attValues, attIds);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
}
numItems = index;
@@ -1338,11 +1354,11 @@ public final class Avrcp {
}
class CachedRequest {
- int mStart;
- int mEnd;
+ long mStart;
+ long mEnd;
byte mAttrCnt;
ArrayList<Integer> mAttrList;
- public CachedRequest(int start, int end, byte attrCnt, int[] attrs) {
+ public CachedRequest(long start, long end, byte attrCnt, int[] attrs) {
mStart = start;
mEnd = end;
mAttrCnt = attrCnt;
@@ -1355,12 +1371,12 @@ public final class Avrcp {
class FolderListEntries {
byte mScope;
- int mStart;
- int mEnd;
+ long mStart;
+ long mEnd;
int mAttrCnt;
int mNumAttr;
ArrayList<Integer> mAttrList;
- public FolderListEntries(byte scope, int start, int end, int attrCnt, int numAttr,
+ public FolderListEntries(byte scope, long start, long end, int attrCnt, int numAttr,
int[] attrs) {
mScope = scope;
mStart = start;
@@ -1418,11 +1434,16 @@ public final class Avrcp {
final MediaPlayerInfo di = rccIterator.next();
if (di.GetPlayerFocus()) {
if (DEBUG) Log.v(TAG, "resetting current MetaData");
- mMetadata = di.GetMetadata();
+ mMetadata.artist = di.GetMetadata().artist;
+ mMetadata.trackTitle = di.GetMetadata().trackTitle;
+ mMetadata.albumTitle = di.GetMetadata().albumTitle;
+ mMetadata.genre = di.GetMetadata().genre;
+ mMetadata.tracknum = di.GetMetadata().tracknum;
break;
}
}
}
+
String oldMetadata = mMetadata.toString();
mMetadata.artist = data.getString(MediaMetadataRetriever.METADATA_KEY_ARTIST, null);
mMetadata.trackTitle = data.getString(MediaMetadataRetriever.METADATA_KEY_TITLE, null);
@@ -1431,7 +1452,8 @@ public final class Avrcp {
mTrackNumber = data.getLong(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS, -1L);
mMetadata.tracknum = data.getLong(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER, -1L);
- Log.v(TAG,"mMetadata.toString() = " + mMetadata.toString());
+ Log.v(TAG,"old Metadata = " + oldMetadata);
+ Log.v(TAG,"new MetaData " + mMetadata.toString());
if (mMediaPlayers.size() > 0) {
final Iterator<MediaPlayerInfo> rccIterator = mMediaPlayers.iterator();
@@ -1444,6 +1466,7 @@ public final class Avrcp {
}
}
}
+
if (!oldMetadata.equals(mMetadata.toString())) {
updateTrackNumber();
Log.v(TAG,"new mMetadata, mTrackNumber update to " + mTrackNumber);
@@ -1622,11 +1645,13 @@ public final class Avrcp {
status = NOT_A_DIRECTORY;
else
status = DOES_NOT_EXIST;
- cursor.close();
} catch (Exception e) {
Log.e(TAG, "Exception " + e);
- cursor.close();
changePathRspNative(INTERNAL_ERROR, numberOfItems);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
break;
default:
@@ -1661,12 +1686,14 @@ public final class Avrcp {
} else{
numberOfItems = cursor.getCount();
mCurrentPathUid = String.valueOf(folderUid);
- cursor.close();
}
} catch (Exception e) {
Log.e(TAG, "Exception " + e);
- cursor.close();
changePathRspNative(INTERNAL_ERROR, numberOfItems);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
} else { // Path @ Individual Album id
Cursor cursor = null;
@@ -1682,11 +1709,13 @@ public final class Avrcp {
status = NOT_A_DIRECTORY;
else
status = DOES_NOT_EXIST;
- cursor.close();
} catch (Exception e) {
Log.e(TAG, "Exception " + e);
- cursor.close();
changePathRspNative(INTERNAL_ERROR, numberOfItems);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
}
break;
@@ -1723,12 +1752,14 @@ public final class Avrcp {
numberOfItems = cursor.getCount();
mCurrentPathUid = String.valueOf(folderUid);
mCurrentPath = PATH_ARTISTS;
- cursor.close();
}
} catch (Exception e) {
Log.e(TAG, "Exception " + e);
- cursor.close();
changePathRspNative(INTERNAL_ERROR, numberOfItems);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
} else {
Cursor cursor = null;
@@ -1742,11 +1773,13 @@ public final class Avrcp {
status = NOT_A_DIRECTORY;
else
status = DOES_NOT_EXIST;
- cursor.close();
} catch (Exception e) {
Log.e(TAG, "Exception " + e);
- cursor.close();
changePathRspNative(INTERNAL_ERROR, numberOfItems);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
}
break;
@@ -1789,12 +1822,14 @@ public final class Avrcp {
numberOfItems = cursor.getCount();
mCurrentPathUid = String.valueOf(folderUid);
mCurrentPath = PATH_PLAYLISTS;
- cursor.close();
}
} catch (Exception e) {
Log.e(TAG, "Exception " + e);
- cursor.close();
changePathRspNative(INTERNAL_ERROR, numberOfItems);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
} else {
numberOfItems = 0;
@@ -1829,13 +1864,15 @@ public final class Avrcp {
return 0;
} else {
long count = cursor.getCount();
- cursor.close();
return count;
}
} catch (Exception e) {
Log.e(TAG, "Exception " + e);
- cursor.close();
return 0;
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
}
@@ -1853,7 +1890,6 @@ public final class Avrcp {
return 0;
} else if (path.equals(PATH_TITLES)) {
long count = cursor.getCount();
- cursor.close();
return count;
} else if (path.equals(PATH_ALBUMS) || path.equals(PATH_ARTISTS)){
long elemCount = 0;
@@ -1872,12 +1908,14 @@ public final class Avrcp {
count--;
}
Log.i(TAG, "element Count is "+ elemCount);
- cursor.close();
return elemCount;
}
} catch (Exception e) {
Log.e(TAG, "Exception " + e);
- cursor.close();
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
return 0;
}
@@ -1924,13 +1962,15 @@ public final class Avrcp {
playItemRspNative(DOES_NOT_EXIST);
} else {
Log.i(TAG, "Play uid:" + uid);
- cursor.close();
mRemoteController.setRemoteControlClientPlayItem(uid, scope);
}
} catch (Exception e) {
Log.e(TAG, "Exception " + e);
- cursor.close();
playItemRspNative(INTERNAL_ERROR);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
} else if (mCurrentPath.equals(PATH_ALBUMS)) {
if (mCurrentPathUid == null) {
@@ -1949,13 +1989,15 @@ public final class Avrcp {
playItemRspNative(DOES_NOT_EXIST);
} else {
Log.i(TAG, "Play uid:" + uid);
- cursor.close();
mRemoteController.setRemoteControlClientPlayItem(uid, scope);
}
} catch (Exception e) {
Log.e(TAG, "Exception " + e);
- cursor.close();
playItemRspNative(INTERNAL_ERROR);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
}
} else if (mCurrentPath.equals(PATH_ARTISTS)) {
@@ -1975,13 +2017,15 @@ public final class Avrcp {
playItemRspNative(DOES_NOT_EXIST);
} else {
Log.i(TAG, "Play uid:" + uid);
- cursor.close();
mRemoteController.setRemoteControlClientPlayItem(uid, scope);
}
} catch (Exception e) {
Log.e(TAG, "Exception " + e);
- cursor.close();
playItemRspNative(INTERNAL_ERROR);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
}
} else if (mCurrentPath.equals(PATH_PLAYLISTS)) {
@@ -2014,13 +2058,15 @@ public final class Avrcp {
playItemRspNative(DOES_NOT_EXIST);
} else {
Log.i(TAG, "Play uid:" + uid);
- cursor.close();
mRemoteController.setRemoteControlClientPlayItem(uid, scope);
}
} catch (Exception e) {
Log.e(TAG, "Exception " + e);
- cursor.close();
playItemRspNative(INTERNAL_ERROR);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
}
} else {
@@ -2083,16 +2129,23 @@ public final class Avrcp {
Log.i(TAG, "Invalid track UID");
getItemAttrRspNative((byte)0, attrs, textArray);
} else {
+ int validAttrib = 0;
cursor.moveToFirst();
for (int i = 0; i < numAttr; ++i) {
- textArray[i] = getAttributeStringFromCursor(cursor, attrs[i]);
+ if ((attrs[i] <= MEDIA_ATTR_MAX) && (attrs[i] >= MEDIA_ATTR_MIN)) {
+ textArray[i] = getAttributeStringFromCursor(cursor, attrs[i]);
+ validAttrib ++;
+ }
}
- getItemAttrRspNative(numAttr, attrs, textArray);
- cursor.close();
+ getItemAttrRspNative((byte)validAttrib, attrs, textArray);
}
} catch (Exception e) {
- Log.e(TAG, "Exception " + e); cursor.close();
+ Log.e(TAG, "Exception " + e);
getItemAttrRspNative((byte)0, attrs, textArray);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
} else {
Log.i(TAG, "Invalid scope");
@@ -2153,7 +2206,7 @@ public final class Avrcp {
}
}
- private void getFolderItems(byte scope, int start, int end, int attrCnt,
+ private void getFolderItems(byte scope, long start, long end, int attrCnt,
int numAttr, int[] attrs) {
if (DEBUG) Log.v(TAG, "getFolderItems");
if (DEBUG) Log.v(TAG, "scope: " + scope + " attrCnt: " + attrCnt);
@@ -2168,7 +2221,7 @@ public final class Avrcp {
mHandler.sendMessage(msg);
}
- private void processGetFolderItems(byte scope, int start, int end, int size,
+ private void processGetFolderItems(byte scope, long start, long end, int size,
int numAttr, int[] attrs) {
if (DEBUG) Log.v(TAG, "processGetFolderItems");
if (DEBUG) Log.v(TAG, "scope: " + scope + " size: " + size);
@@ -2183,7 +2236,7 @@ public final class Avrcp {
}
}
- private void processGetMediaPlayerItems(byte scope, int start, int end, int size,
+ private void processGetMediaPlayerItems(byte scope, long start, long end, int size,
int numAttr, int[] attrs) {
byte[] folderItems = new byte[size];
int[] folderItemLengths = new int[32];
@@ -2223,12 +2276,12 @@ public final class Avrcp {
return false;
}
- private void processGetFolderItemsInternal(byte scope, int start, int end, int size,
+ private void processGetFolderItemsInternal(byte scope, long start, long end, long size,
byte numAttr, int[] attrs) {
int status = OPERATION_SUCCESSFUL;
- int numItems = 0;
- int reqItems = (end - start) + 1;
+ long numItems = 0;
+ long reqItems = (end - start) + 1;
int[] itemType = new int[MAX_BROWSE_ITEM_TO_SEND];
long[] uid = new long[MAX_BROWSE_ITEM_TO_SEND];
int[] type = new int[MAX_BROWSE_ITEM_TO_SEND];
@@ -2269,7 +2322,7 @@ public final class Avrcp {
}
if (mCurrentPath.equals(PATH_ROOT)) {
- int availableItems = NUM_ROOT_ELEMENTS;
+ long availableItems = NUM_ROOT_ELEMENTS;
if (start >= availableItems) {
Log.i(TAG, "startIteam exceeds the available item index");
getFolderItemsRspNative((byte)RANGE_OUT_OF_BOUNDS, numItems, itemType, uid,
@@ -2288,8 +2341,8 @@ public final class Avrcp {
numItems = reqItems;
for (int count = 0; count < reqItems; count ++) {
- int index = start + count;
- switch (index) {
+ long index = start + count;
+ switch ((int)index) {
case ALBUMS_ITEM_INDEX:
itemType[count] = TYPE_FOLDER_ITEM;
uid[count] = UID_ALBUM;
@@ -2336,7 +2389,7 @@ public final class Avrcp {
getFolderItemsRspNative((byte)status, numItems, itemType, uid, type,
playable, displayName, numAtt, attValues, attIds);
} else if (mCurrentPath.equals(PATH_TITLES)) {
- int availableItems = 0;
+ long availableItems = 0;
Cursor cursor = null;
try {
cursor = mContext.getContentResolver().query(
@@ -2350,7 +2403,6 @@ public final class Avrcp {
getFolderItemsRspNative((byte)RANGE_OUT_OF_BOUNDS, numItems,
itemType, uid, type, playable, displayName, numAtt, attValues,
attIds);
- cursor.close();
return;
}
cursor.moveToFirst();
@@ -2382,23 +2434,30 @@ public final class Avrcp {
displayName[index] =
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.
Audio.Media.TITLE));
- numAtt[index] = numAttr;
+ int validAttrib = 0;
for (attIndex = 0; attIndex < numAttr; attIndex++) {
- attValues[(7 * index) + attIndex] = getAttributeStringFromCursor(
- cursor, attrs[attIndex]);
- attIds[(7 * index) + attIndex] = attrs[attIndex];
+ if ((attrs[attIndex] <= MEDIA_ATTR_MAX) &&
+ (attrs[attIndex] >= MEDIA_ATTR_MIN)) {
+ attValues[(7 * index) + attIndex] =
+ getAttributeStringFromCursor(cursor, attrs[attIndex]);
+ attIds[(7 * index) + attIndex] = attrs[attIndex];
+ validAttrib ++;
+ }
}
+ numAtt[index] = (byte)validAttrib;
cursor.moveToNext();
}
numItems = index;
getFolderItemsRspNative((byte)OPERATION_SUCCESSFUL, numItems, itemType, uid,
type, playable, displayName, numAtt, attValues, attIds);
- cursor.close();
} catch(Exception e) {
Log.i(TAG, "Exception e" + e);
- cursor.close();
getFolderItemsRspNative((byte)INTERNAL_ERROR, numItems, itemType, uid, type,
playable, displayName, numAtt, attValues, attIds);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
} else if (mCurrentPath.equals(PATH_ALBUMS)) {
if (mCurrentPathUid == null) {
@@ -2477,16 +2536,18 @@ public final class Avrcp {
itemType, uid, type, playable, displayName, numAtt, attValues,
attIds);
}
- cursor.close();
} catch(Exception e) {
Log.i(TAG, "Exception e" + e);
- cursor.close();
getFolderItemsRspNative((byte)INTERNAL_ERROR, numItems, itemType, uid, type,
playable, displayName, numAtt, attValues, attIds);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
} else {
long folderUid = Long.valueOf(mCurrentPathUid);
- int availableItems = 0;
+ long availableItems = 0;
Cursor cursor = null;
try {
cursor = mContext.getContentResolver().query(
@@ -2502,7 +2563,6 @@ public final class Avrcp {
getFolderItemsRspNative((byte)RANGE_OUT_OF_BOUNDS, numItems,
itemType, uid, type, playable, displayName, numAtt,
attValues, attIds);
- cursor.close();
return;
}
cursor.moveToFirst();
@@ -2535,24 +2595,31 @@ public final class Avrcp {
playable[index] = 0;
displayName[index] =
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.
- Audio.Media.TITLE));
- numAtt[index] = numAttr;
+ Audio.Media.TITLE));
+ int validAttrib = 0;
for (attIndex = 0; attIndex < numAttr; attIndex++) {
- attValues[(7 * index) + attIndex] = getAttributeStringFromCursor(
- cursor, attrs[attIndex]);
- attIds[(7 * index) + attIndex] = attrs[attIndex];
+ if ((attrs[attIndex] <= MEDIA_ATTR_MAX) &&
+ (attrs[attIndex] >= MEDIA_ATTR_MIN)) {
+ attValues[(7 * index) + attIndex] =
+ getAttributeStringFromCursor(cursor, attrs[attIndex]);
+ attIds[(7 * index) + attIndex] = attrs[attIndex];
+ validAttrib ++;
+ }
}
+ numAtt[index] = (byte)validAttrib;
cursor.moveToNext();
}
numItems = index;
getFolderItemsRspNative((byte)OPERATION_SUCCESSFUL, numItems, itemType, uid,
type, playable, displayName, numAtt, attValues, attIds);
- cursor.close();
} catch(Exception e) {
Log.i(TAG, "Exception e" + e);
- cursor.close();
getFolderItemsRspNative((byte)INTERNAL_ERROR, numItems, itemType, uid, type,
playable, displayName, numAtt, attValues, attIds);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
}
} else if (mCurrentPath.equals(PATH_ARTISTS)) {
@@ -2630,16 +2697,18 @@ public final class Avrcp {
getFolderItemsRspNative((byte)RANGE_OUT_OF_BOUNDS, numItems, itemType,
uid, type, playable, displayName, numAtt, attValues, attIds);
}
- cursor.close();
} catch(Exception e) {
Log.i(TAG, "Exception e" + e);
- cursor.close();
getFolderItemsRspNative((byte)INTERNAL_ERROR, numItems, itemType, uid, type,
playable, displayName, numAtt, attValues, attIds);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
} else {
long folderUid = Long.valueOf(mCurrentPathUid);
- int availableItems = 0;
+ long availableItems = 0;
Cursor cursor = null;
try {
cursor = mContext.getContentResolver().query(
@@ -2655,7 +2724,6 @@ public final class Avrcp {
getFolderItemsRspNative((byte)RANGE_OUT_OF_BOUNDS, numItems,
itemType, uid, type, playable, displayName, numAtt, attValues,
attIds);
- cursor.close();
return;
}
cursor.moveToFirst();
@@ -2688,23 +2756,30 @@ public final class Avrcp {
displayName[index] =
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.
Audio.Media.TITLE));
- numAtt[index] = numAttr;
+ int validAttrib = 0;
for (attIndex = 0; attIndex < numAttr; attIndex++) {
- attValues[(7 * index) + attIndex] = getAttributeStringFromCursor(
- cursor, attrs[attIndex]);
- attIds[(7 * index) + attIndex] = attrs[attIndex];
+ if ((attrs[attIndex] <= MEDIA_ATTR_MAX) &&
+ (attrs[attIndex] >= MEDIA_ATTR_MIN)) {
+ attValues[(7 * index) + attIndex] =
+ getAttributeStringFromCursor(cursor, attrs[attIndex]);
+ attIds[(7 * index) + attIndex] = attrs[attIndex];
+ validAttrib ++;
+ }
}
+ numAtt[index] = (byte)validAttrib;
cursor.moveToNext();
}
numItems = index;
getFolderItemsRspNative((byte)OPERATION_SUCCESSFUL, numItems, itemType,
uid, type, playable, displayName, numAtt, attValues, attIds);
- cursor.close();
} catch(Exception e) {
Log.i(TAG, "Exception e" + e);
- cursor.close();
getFolderItemsRspNative((byte)INTERNAL_ERROR, numItems, itemType, uid,
type, playable, displayName, numAtt, attValues, attIds);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
}
} else if (mCurrentPath.equals(PATH_PLAYLISTS)) {
@@ -2776,16 +2851,18 @@ public final class Avrcp {
itemType, uid, type, playable, displayName, numAtt,
attValues, attIds);
}
- cursor.close();
} catch(Exception e) {
Log.i(TAG, "Exception e" + e);
- cursor.close();
getFolderItemsRspNative((byte)INTERNAL_ERROR, numItems, itemType,
uid, type, playable, displayName, numAtt, attValues, attIds);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
} else {
long folderUid = Long.valueOf(mCurrentPathUid);
- int availableItems = 0;
+ long availableItems = 0;
Cursor cursor = null;
String[] playlistMemberCols = new String[] {
@@ -2816,7 +2893,6 @@ public final class Avrcp {
getFolderItemsRspNative((byte)RANGE_OUT_OF_BOUNDS, numItems,
itemType, uid, type, playable, displayName, numAtt,
attValues, attIds);
- cursor.close();
return;
}
cursor.moveToFirst();
@@ -2850,23 +2926,30 @@ public final class Avrcp {
displayName[index] =
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.
Audio.Media.TITLE));
- numAtt[index] = numAttr;
+ int validAttrib = 0;
for (attIndex = 0; attIndex < numAttr; attIndex++) {
- attValues[(7 * index) + attIndex] = getAttributeStringFromCursor(
- cursor, attrs[attIndex]);
- attIds[(7 * index) + attIndex] = attrs[attIndex];
+ if ((attrs[attIndex] <= MEDIA_ATTR_MAX) &&
+ (attrs[attIndex] >= MEDIA_ATTR_MIN)) {
+ attValues[(7 * index) + attIndex] =
+ getAttributeStringFromCursor(cursor, attrs[attIndex]);
+ attIds[(7 * index) + attIndex] = attrs[attIndex];
+ validAttrib ++;
+ }
}
+ numAtt[index] = (byte)validAttrib;
cursor.moveToNext();
}
numItems = index;
getFolderItemsRspNative((byte)OPERATION_SUCCESSFUL, numItems, itemType, uid,
type, playable, displayName, numAtt, attValues, attIds);
- cursor.close();
} catch(Exception e) {
Log.e(TAG, "Exception e" + e);
- cursor.close();
getFolderItemsRspNative((byte)INTERNAL_ERROR, numItems, itemType, uid, type,
playable, displayName, numAtt, attValues, attIds);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
}
} else {
@@ -3097,7 +3180,7 @@ public final class Avrcp {
}
private String getAttributeStringFromCursor(Cursor cursor, int attrId) {
- String attrStr = null;
+ String attrStr = "<unknown>";
switch (attrId) {
case MEDIA_ATTR_TITLE:
attrStr = cursor.getString(cursor.getColumnIndexOrThrow(
@@ -3285,8 +3368,10 @@ public final class Avrcp {
return (int) Math.ceil((double) volume*AVRCP_MAX_VOL/mAudioStreamMax);
}
-private void updateLocalPlayerSettings( byte[] data) {
+ private void updateLocalPlayerSettings( byte[] data) {
+ if (DEBUG) Log.v(TAG, "updateLocalPlayerSettings");
for (int i = 0; i < data.length; i += 2) {
+ if (DEBUG) Log.v(TAG, "ID: " + data[i] + " Value: " + data[i+1]);
switch (data[i]) {
case ATTRIBUTE_EQUALIZER:
settingValues.eq_value = data[i+1];
@@ -3304,6 +3389,45 @@ private void updateLocalPlayerSettings( byte[] data) {
}
}
+ private boolean checkPlayerAttributeResponse( byte[] data) {
+ boolean ret = false;
+ if (DEBUG) Log.v(TAG, "checkPlayerAttributeResponse");
+ for (int i = 0; i < data.length; i += 2) {
+ if (DEBUG) Log.v(TAG, "ID: " + data[i] + " Value: " + data[i+1]);
+ switch (data[i]) {
+ case ATTRIBUTE_EQUALIZER:
+ if (mPendingSetAttributes.contains(new Integer(ATTRIBUTE_EQUALIZER))) {
+ if(data[i+1] == ATTRIBUTE_NOTSUPPORTED) {
+ ret = false;
+ } else {
+ ret = true;
+ }
+ }
+ break;
+ case ATTRIBUTE_REPEATMODE:
+ if (mPendingSetAttributes.contains(new Integer(ATTRIBUTE_REPEATMODE))) {
+ if(data[i+1] == ATTRIBUTE_NOTSUPPORTED) {
+ ret = false;
+ } else {
+ ret = true;
+ }
+ }
+ break;
+ case ATTRIBUTE_SHUFFLEMODE:
+ if (mPendingSetAttributes.contains(new Integer(ATTRIBUTE_SHUFFLEMODE))) {
+ if(data[i+1] == ATTRIBUTE_NOTSUPPORTED) {
+ ret = false;
+ } else {
+ ret = true;
+ }
+ }
+ break;
+ }
+ }
+ mPendingSetAttributes.clear();
+ return ret;
+ }
+
//PDU ID 0x11
private void onListPlayerAttributeRequest() {
if (DEBUG) Log.v(TAG, "onListPlayerAttributeRequest");
@@ -3360,12 +3484,13 @@ private void updateLocalPlayerSettings( byte[] data) {
//PDU 0x14
private void setPlayerAppSetting( byte num , byte [] attr_id , byte [] attr_val )
{
- if (DEBUG) Log.v(TAG, "setPlayerAppSetting" + num );
+ if (DEBUG) Log.v(TAG, "setPlayerAppSetting " + num );
byte[] array = new byte[num*2];
for ( int i = 0; i < num; i++)
{
array[i] = attr_id[i] ;
array[i+1] = attr_val[i];
+ mPendingSetAttributes.add(new Integer(attr_id[i]));
}
Intent intent = new Intent(PLAYERSETTINGS_REQUEST);
intent.putExtra(COMMAND, CMDSET);
@@ -3375,7 +3500,7 @@ private void updateLocalPlayerSettings( byte[] data) {
msg.what = MESSAGE_PLAYERSETTINGS_TIMEOUT;
msg.arg1 = SET_ATTRIBUTE_VALUES;
mPendingCmds.add(new Integer(msg.arg1));
- mHandler.sendMessageDelayed(msg, 130);
+ mHandler.sendMessageDelayed(msg, 500);
}
//PDU 0x15
@@ -3438,6 +3563,7 @@ private void updateLocalPlayerSettings( byte[] data) {
final static short PLAYSTATUS_ERROR = 255;
// match up with btrc_media_attr_t enum of bt_rc.h
+ final static int MEDIA_ATTR_MIN = 1;
final static int MEDIA_ATTR_TITLE = 1;
final static int MEDIA_ATTR_ARTIST = 2;
final static int MEDIA_ATTR_ALBUM = 3;
@@ -3445,6 +3571,7 @@ private void updateLocalPlayerSettings( byte[] data) {
final static int MEDIA_ATTR_NUM_TRACKS = 5;
final static int MEDIA_ATTR_GENRE = 6;
final static int MEDIA_ATTR_PLAYING_TIME = 7;
+ final static int MEDIA_ATTR_MAX = 7;
// match up with btrc_event_id_t enum of bt_rc.h
final static int EVT_PLAY_STATUS_CHANGED = 1;
@@ -3784,7 +3911,7 @@ private void updateLocalPlayerSettings( byte[] data) {
private native boolean setAdressedPlayerRspNative(byte statusCode);
private native boolean getMediaPlayerListRspNative(byte statusCode, int uidCounter,
int itemCount, byte[] folderItems, int[] folderItemLengths);
- private native boolean getFolderItemsRspNative(byte statusCode, int numItems,
+ private native boolean getFolderItemsRspNative(byte statusCode, long numItems,
int[] itemType, long[] uid, int[] type, byte[] playable, String[] displayName,
byte[] numAtt, String[] attValues, int[] attIds);
private native boolean getListPlayerappAttrRspNative(byte attr, byte[] attrIds);
@@ -3894,6 +4021,8 @@ private void updateLocalPlayerSettings( byte[] data) {
mMetadata.albumTitle = metaData.albumTitle;
mMetadata.artist = metaData.artist;
mMetadata.trackTitle = metaData.trackTitle;
+ mMetadata.genre = metaData.genre;
+ mMetadata.tracknum = metaData.tracknum;
}
public byte GetPlayState() {
return mPlayState;
diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java
index 8a303fc0e..524d16a74 100755
--- a/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/src/com/android/bluetooth/btservice/AdapterService.java
@@ -1595,9 +1595,9 @@ public class AdapterService extends Service {
void setProfileAutoConnectionPriority (BluetoothDevice device, int profileId){
if (profileId == BluetoothProfile.HEADSET) {
HeadsetService hsService = HeadsetService.getHeadsetService();
- List<BluetoothDevice> deviceList = hsService.getConnectedDevices();
if ((hsService != null) &&
(BluetoothProfile.PRIORITY_AUTO_CONNECT != hsService.getPriority(device))){
+ List<BluetoothDevice> deviceList = hsService.getConnectedDevices();
adjustOtherHeadsetPriorities(hsService, deviceList);
hsService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT);
}
diff --git a/src/com/android/bluetooth/btservice/AdapterState.java b/src/com/android/bluetooth/btservice/AdapterState.java
index c0d3f3999..419300ac3 100644
--- a/src/com/android/bluetooth/btservice/AdapterState.java
+++ b/src/com/android/bluetooth/btservice/AdapterState.java
@@ -341,6 +341,8 @@ final class AdapterState extends StateMachine {
mPendingCommandState.setTurningOff(false);
transitionTo(mOffState);
notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
+ errorLog("STOP_TIMEOUT:Killing the process to force a restart as part cleanup");
+ android.os.Process.killProcess(android.os.Process.myPid());
break;
case DISABLE_TIMEOUT:
if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = DISABLE_TIMEOUT, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
diff --git a/src/com/android/bluetooth/btservice/BondStateMachine.java b/src/com/android/bluetooth/btservice/BondStateMachine.java
index 3b82b18b2..68590e7b6 100644
--- a/src/com/android/bluetooth/btservice/BondStateMachine.java
+++ b/src/com/android/bluetooth/btservice/BondStateMachine.java
@@ -229,11 +229,21 @@ final class BondStateMachine extends StateMachine {
case SSP_REQUEST:
int passkey = msg.arg1;
int variant = msg.arg2;
+ if(devProp == null)
+ {
+ Log.e(TAG,"Received msg from an unknown device");
+ return false;
+ }
sendDisplayPinIntent(devProp.getAddress(), passkey, variant);
break;
case PIN_REQUEST:
BluetoothClass btClass = dev.getBluetoothClass();
int btDeviceClass = btClass.getDeviceClass();
+ if(devProp == null)
+ {
+ Log.e(TAG,"Received msg from an unknown device");
+ return false;
+ }
if (btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD ||
btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING) {
// Its a keyboard. Follow the HID spec recommendation of creating the
diff --git a/src/com/android/bluetooth/btservice/RemoteDevices.java b/src/com/android/bluetooth/btservice/RemoteDevices.java
index b6c94890e..7ec817054 100644
--- a/src/com/android/bluetooth/btservice/RemoteDevices.java
+++ b/src/com/android/bluetooth/btservice/RemoteDevices.java
@@ -351,7 +351,7 @@ final class RemoteDevices {
device = getDeviceProperties(bdDevice);
}
- for (int j = 0; j < types.length; j++) {
+ for (int j = 0; j < types.length && device != null; j++) {
type = types[j];
val = values[j];
if(val.length <= 0)
diff --git a/src/com/android/bluetooth/gatt/AdvertiseManager.java b/src/com/android/bluetooth/gatt/AdvertiseManager.java
index a2c859316..22b20dd6b 100644
--- a/src/com/android/bluetooth/gatt/AdvertiseManager.java
+++ b/src/com/android/bluetooth/gatt/AdvertiseManager.java
@@ -87,6 +87,16 @@ class AdvertiseManager {
void cleanup() {
logd("advertise clients cleared");
mAdvertiseClients.clear();
+
+ if (mHandler != null) {
+ // Shut down the thread
+ mHandler.removeCallbacksAndMessages(null);
+ Looper looper = mHandler.getLooper();
+ if (looper != null) {
+ looper.quit();
+ }
+ mHandler = null;
+ }
}
/**
@@ -219,12 +229,16 @@ class AdvertiseManager {
// Returns maximum advertise instances supported by controller.
private int maxAdvertiseInstances() {
- AdapterService adapter = AdapterService.getAdapterService();
- int numOfAdvtInstances = adapter.getNumOfAdvertisementInstancesSupported();
- // Note numOfAdvtInstances includes the standard advertising instance.
- // TODO: remove - 1 once the stack is able to include standard instance for multiple
- // advertising.
- return numOfAdvtInstances - 1;
+ AdapterService adapter;
+ int numOfAdvtInstances = 0;
+ if (null != (adapter = AdapterService.getAdapterService())){
+ numOfAdvtInstances = adapter.getNumOfAdvertisementInstancesSupported();
+ // Note numOfAdvtInstances includes the standard advertising instance.
+ // TODO: remove - 1 once the stack is able to include standard instance for multiple
+ // advertising.
+ return numOfAdvtInstances - 1;
+ }
+ return numOfAdvtInstances;
}
}
diff --git a/src/com/android/bluetooth/gatt/GattService.java b/src/com/android/bluetooth/gatt/GattService.java
index 4dbf0fed8..654df69b9 100644
--- a/src/com/android/bluetooth/gatt/GattService.java
+++ b/src/com/android/bluetooth/gatt/GattService.java
@@ -1721,10 +1721,14 @@ public class GattService extends ProfileService {
case HandleMap.TYPE_CHARACTERISTIC:
{
HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle);
+ if (null != serviceEntry) {
app.callback.onCharacteristicReadRequest(address, transId, offset, isLong,
serviceEntry.serviceType, serviceEntry.instance,
new ParcelUuid(serviceEntry.uuid), entry.instance,
new ParcelUuid(entry.uuid));
+ }else {
+ Log.d(TAG, "null == serviceEntry");
+ }
break;
}
@@ -1732,11 +1736,15 @@ public class GattService extends ProfileService {
{
HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle);
HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle);
- app.callback.onDescriptorReadRequest(address, transId, offset, isLong,
+ if (null != serviceEntry && null != charEntry) {
+ app.callback.onDescriptorReadRequest(address, transId, offset, isLong,
serviceEntry.serviceType, serviceEntry.instance,
new ParcelUuid(serviceEntry.uuid), charEntry.instance,
new ParcelUuid(charEntry.uuid),
new ParcelUuid(entry.uuid));
+ } else {
+ Log.d(TAG, "null == serviceEntry || null == charEntry");
+ }
break;
}
@@ -1771,11 +1779,15 @@ public class GattService extends ProfileService {
case HandleMap.TYPE_CHARACTERISTIC:
{
HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle);
+ if (null != serviceEntry) {
app.callback.onCharacteristicWriteRequest(address, transId,
offset, length, isPrep, needRsp,
serviceEntry.serviceType, serviceEntry.instance,
new ParcelUuid(serviceEntry.uuid), entry.instance,
new ParcelUuid(entry.uuid), data);
+ }else {
+ Log.d(TAG, "null == serviceEntry");
+ }
break;
}
@@ -1783,12 +1795,16 @@ public class GattService extends ProfileService {
{
HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle);
HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle);
+ if (null != serviceEntry && null != charEntry) {
app.callback.onDescriptorWriteRequest(address, transId,
offset, length, isPrep, needRsp,
serviceEntry.serviceType, serviceEntry.instance,
new ParcelUuid(serviceEntry.uuid), charEntry.instance,
new ParcelUuid(charEntry.uuid),
new ParcelUuid(entry.uuid), data);
+ } else {
+ Log.d(TAG, "null == serviceEntry || null == charEntry");
+ }
break;
}
@@ -1893,8 +1909,12 @@ public class GattService extends ProfileService {
if (DBG) Log.d(TAG, "beginServiceDeclaration() - uuid=" + srvcUuid +
" serverIf=" + serverIf);
ServiceDeclaration serviceDeclaration = addToActiveDeclaration(serverIf);
- serviceDeclaration.addService(srvcUuid, srvcType, srvcInstanceId, minHandles,
+ if (null != serviceDeclaration ) {
+ serviceDeclaration.addService(srvcUuid, srvcType, srvcInstanceId, minHandles,
advertisePreferred);
+ } else {
+ if (DBG) Log.d(TAG, "beginServiceDeclaration: Got null from addToActiveDeclaration()");
+ }
}
void addIncludedService(int serverIf, int srvcType, int srvcInstanceId,
@@ -1902,7 +1922,12 @@ public class GattService extends ProfileService {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (DBG) Log.d(TAG, "addIncludedService() - uuid=" + srvcUuid);
- getActiveDeclaration(serverIf).addIncludedService(srvcUuid, srvcType, srvcInstanceId);
+ ServiceDeclaration serviceDeclaration = getActiveDeclaration(serverIf);
+ if (null != serviceDeclaration) {
+ serviceDeclaration.addIncludedService(srvcUuid, srvcType, srvcInstanceId);
+ } else {
+ Log.d(TAG,"getActiveDeclaration(serverIf) is null");
+ }
}
void addCharacteristic(int serverIf, UUID charUuid, int properties,
@@ -1910,14 +1935,24 @@ public class GattService extends ProfileService {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (DBG) Log.d(TAG, "addCharacteristic() - uuid=" + charUuid);
- getActiveDeclaration(serverIf).addCharacteristic(charUuid, properties, permissions);
+ ServiceDeclaration serviceDeclaration = getActiveDeclaration(serverIf);
+ if (null != serviceDeclaration) {
+ serviceDeclaration.addCharacteristic(charUuid, properties, permissions);
+ } else {
+ Log.d(TAG,"getActiveDeclaration(serverIf) is null");
+ }
}
void addDescriptor(int serverIf, UUID descUuid, int permissions) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (DBG) Log.d(TAG, "addDescriptor() - uuid=" + descUuid);
- getActiveDeclaration(serverIf).addDescriptor(descUuid, permissions);
+ ServiceDeclaration serviceDeclaration = getActiveDeclaration(serverIf);
+ if (null != serviceDeclaration) {
+ serviceDeclaration.addDescriptor(descUuid, permissions);
+ } else {
+ Log.d(TAG,"getActiveDeclaration(serverIf) is null");
+ }
}
void endServiceDeclaration(int serverIf) {
@@ -1965,9 +2000,11 @@ public class GattService extends ProfileService {
HandleMap.Entry entry = mHandleMap.getByRequestId(requestId);
if (entry != null) handle = entry.handle;
- int connId = mServerMap.connIdByAddress(serverIf, address);
- gattServerSendResponseNative(serverIf, connId, requestId, (byte)status,
+ Integer connId;
+ if(null != (connId = mServerMap.connIdByAddress(serverIf, address))) {
+ gattServerSendResponseNative(serverIf, connId, requestId, (byte)status,
handle, offset, value, (byte)0);
+ }
mHandleMap.deleteRequest(requestId);
}
@@ -1985,9 +2022,8 @@ public class GattService extends ProfileService {
int charHandle = mHandleMap.getCharacteristicHandle(srvcHandle, charUuid, charInstanceId);
if (charHandle == 0) return;
- int connId = mServerMap.connIdByAddress(serverIf, address);
- if (connId == 0) return;
-
+ Integer connId = mServerMap.connIdByAddress(serverIf, address);
+ if (connId == null) return;
if (confirm) {
gattServerSendIndicationNative(serverIf, charHandle, connId, value);
} else {
@@ -2060,12 +2096,14 @@ public class GattService extends ProfileService {
private void continueServiceDeclaration(int serverIf, int status, int srvcHandle) throws RemoteException {
if (mServiceDeclarations.size() == 0) return;
if (DBG) Log.d(TAG, "continueServiceDeclaration() - srvcHandle=" + srvcHandle);
-
+ ServiceDeclaration serviceDeclaration;
boolean finished = false;
ServiceDeclaration.Entry entry = null;
- if (status == 0)
- entry = getPendingDeclaration().getNext();
+ if (status == 0) {
+ if (null != (serviceDeclaration = getPendingDeclaration()))
+ entry = serviceDeclaration.getNext();
+ }
if (entry != null) {
if (DBG) Log.d(TAG, "continueServiceDeclaration() - next entry type="
@@ -2075,11 +2113,13 @@ public class GattService extends ProfileService {
if (entry.advertisePreferred) {
mAdvertisingServiceUuids.add(entry.uuid);
}
- gattServerAddServiceNative(serverIf, entry.serviceType,
+ if (null != (serviceDeclaration = getPendingDeclaration())) {
+ gattServerAddServiceNative(serverIf, entry.serviceType,
entry.instance,
entry.uuid.getLeastSignificantBits(),
entry.uuid.getMostSignificantBits(),
- getPendingDeclaration().getNumHandles());
+ serviceDeclaration.getNumHandles());
+ }
break;
case ServiceDeclaration.TYPE_CHARACTERISTIC:
diff --git a/src/com/android/bluetooth/gatt/ScanManager.java b/src/com/android/bluetooth/gatt/ScanManager.java
index 27e492f30..705d49e72 100644
--- a/src/com/android/bluetooth/gatt/ScanManager.java
+++ b/src/com/android/bluetooth/gatt/ScanManager.java
@@ -101,6 +101,16 @@ public class ScanManager {
mRegularScanClients.clear();
mBatchClients.clear();
mScanNative.cleanup();
+
+ if (mHandler != null) {
+ // Shut down the thread
+ mHandler.removeCallbacksAndMessages(null);
+ Looper looper = mHandler.getLooper();
+ if (looper != null) {
+ looper.quit();
+ }
+ mHandler = null;
+ }
}
/**
@@ -351,14 +361,15 @@ public class ScanManager {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "awakened up at time " + SystemClock.elapsedRealtime());
- String action = intent.getAction();
-
- if (action.equals(ACTION_REFRESH_BATCHED_SCAN)) {
- if (mBatchClients.isEmpty()) {
- return;
+ String action;
+ if (null != (action = intent.getAction())) {
+ if (action.equals(ACTION_REFRESH_BATCHED_SCAN)) {
+ if (mBatchClients.isEmpty()) {
+ return;
+ }
+ // Note this actually flushes all pending batch data.
+ flushBatchScanResults(mBatchClients.iterator().next());
}
- // Note this actually flushes all pending batch data.
- flushBatchScanResults(mBatchClients.iterator().next());
}
}
};
@@ -649,20 +660,24 @@ public class ScanManager {
waitForCallback();
} else {
Deque<Integer> clientFilterIndices = new ArrayDeque<Integer>();
+ int featureSelection;
+ int filterIndex;
for (ScanFilter filter : client.filters) {
ScanFilterQueue queue = new ScanFilterQueue();
- queue.addScanFilter(filter);
- int featureSelection = queue.getFeatureSelection();
- int filterIndex = mFilterIndexStack.pop();
- while (!queue.isEmpty()) {
+ if (null != queue) {
+ queue.addScanFilter(filter);
+ featureSelection = queue.getFeatureSelection();
+ filterIndex = mFilterIndexStack.pop();
+ while (!queue.isEmpty()) {
+ resetCountDownLatch();
+ addFilterToController(clientIf, queue.pop(), filterIndex);
+ waitForCallback();
+ }
resetCountDownLatch();
- addFilterToController(clientIf, queue.pop(), filterIndex);
+ configureFilterParamter(clientIf, client, featureSelection, filterIndex);
waitForCallback();
+ clientFilterIndices.add(filterIndex);
}
- resetCountDownLatch();
- configureFilterParamter(clientIf, client, featureSelection, filterIndex);
- waitForCallback();
- clientFilterIndices.add(filterIndex);
}
mClientFilterIndexMap.put(clientIf, clientFilterIndices);
}
@@ -748,7 +763,7 @@ public class ScanManager {
if (client.filters == null || client.filters.isEmpty()) {
return true;
}
- return client.filters.size() < mClientFilterIndexMap.size();
+ return false;
}
private void addFilterToController(int clientIf, ScanFilterQueue.Entry entry,
@@ -797,14 +812,16 @@ public class ScanManager {
}
private void initFilterIndexStack() {
- int maxFiltersSupported =
- AdapterService.getAdapterService().getNumOfOffloadedScanFilterSupported();
- // Start from index 3 as:
- // index 0 is reserved for ALL_PASS filter in Settings app.
- // index 1 is reserved for ALL_PASS filter for regular scan apps.
- // index 2 is reserved for ALL_PASS filter for batch scan apps.
- for (int i = 3; i < maxFiltersSupported; ++i) {
- mFilterIndexStack.add(i);
+ AdapterService adapterService;
+ if (null != (adapterService = AdapterService.getAdapterService())) {
+ int maxFiltersSupported = adapterService.getNumOfOffloadedScanFilterSupported();
+ // Start from index 3 as:
+ // index 0 is reserved for ALL_PASS filter in Settings app.
+ // index 1 is reserved for ALL_PASS filter for regular scan apps.
+ // index 2 is reserved for ALL_PASS filter for batch scan apps.
+ for (int i = 3; i < maxFiltersSupported; ++i) {
+ mFilterIndexStack.add(i);
+ }
}
}
diff --git a/src/com/android/bluetooth/hdp/HealthService.java b/src/com/android/bluetooth/hdp/HealthService.java
index 21846c677..01e3f4121 100644
--- a/src/com/android/bluetooth/hdp/HealthService.java
+++ b/src/com/android/bluetooth/hdp/HealthService.java
@@ -189,7 +189,12 @@ public class HealthService extends ProfileService {
{
BluetoothHealthAppConfiguration appConfig =
(BluetoothHealthAppConfiguration) msg.obj;
- int appId = (mApps.get(appConfig)).mAppId;
+ AppInfo appInfo = mApps.get(appConfig);
+ if (appInfo == null) {
+ Log.e(TAG, "No AppInfo found for AppConfig: " + appConfig);
+ break;
+ }
+ int appId = appInfo.mAppId;
if (!unregisterHealthAppNative(appId)) {
Log.e(TAG, "Failed to unregister application: id: " + appId);
callStatusCallback(appConfig,
@@ -201,7 +206,12 @@ public class HealthService extends ProfileService {
{
HealthChannel chan = (HealthChannel) msg.obj;
byte[] devAddr = Utils.getByteAddress(chan.mDevice);
- int appId = (mApps.get(chan.mConfig)).mAppId;
+ AppInfo appInfo = mApps.get(chan.mConfig);
+ if (appInfo == null) {
+ Log.e(TAG, "No AppInfo found for AppConfig: " + chan.mConfig);
+ break;
+ }
+ int appId = appInfo.mAppId;
chan.mChannelId = connectChannelNative(devAddr, appId);
if (chan.mChannelId == -1) {
callHealthChannelCallback(chan.mConfig, chan.mDevice,
@@ -241,6 +251,10 @@ public class HealthService extends ProfileService {
regStatus == BluetoothHealth.APP_CONFIG_UNREGISTRATION_SUCCESS) {
//unlink to death once app is unregistered
AppInfo appInfo = mApps.get(appConfig);
+ if (appInfo == null){
+ Log.e(TAG, "No AppInfo found for AppConfig " + appConfig);
+ break;
+ }
appInfo.cleanup();
mApps.remove(appConfig);
}
@@ -254,7 +268,7 @@ public class HealthService extends ProfileService {
findAppConfigByAppId(channelStateEvent.mAppId);
int newState;
newState = convertHalChannelState(channelStateEvent.mState);
- if (newState == BluetoothHealth.STATE_CHANNEL_DISCONNECTED &&
+ if (newState == BluetoothHealth.STATE_CHANNEL_DISCONNECTED ||
appConfig == null) {
Log.e(TAG,"Disconnected for non existing app");
break;
@@ -512,9 +526,15 @@ public class HealthService extends ProfileService {
private void callStatusCallback(BluetoothHealthAppConfiguration config, int status) {
if (VDBG) log ("Health Device Application: " + config + " State Change: status:" + status);
- IBluetoothHealthCallback callback = (mApps.get(config)).mCallback;
+ AppInfo appInfo = mApps.get(config);
+ if (appInfo == null) {
+ Log.e(TAG, " No AppInfo found for AppConfig " + config);
+ return;
+ }
+ IBluetoothHealthCallback callback = appInfo.mCallback;
if (callback == null) {
Log.e(TAG, "Callback object null");
+ return;
}
try {
@@ -604,8 +624,12 @@ public class HealthService extends ProfileService {
Log.e(TAG, "Exception while duping: " + e);
}
}
-
- IBluetoothHealthCallback callback = (mApps.get(config)).mCallback;
+ AppInfo appInfo = mApps.get(config);
+ if (appInfo == null) {
+ Log.e(TAG, "No AppInfo found for AppConfig " + config);
+ return;
+ }
+ IBluetoothHealthCallback callback = appInfo.mCallback;
if (callback == null) {
Log.e(TAG, "No callback found for config: " + config);
return;
diff --git a/src/com/android/bluetooth/hfp/HeadsetStateMachine.java b/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
index edd352018..0bec29172 100644
--- a/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
+++ b/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
@@ -1218,6 +1218,12 @@ final class HeadsetStateMachine extends StateMachine {
switch (state) {
case HeadsetHalConstants.AUDIO_STATE_CONNECTED:
+ if (!isScoAcceptable()) {
+ Log.e(TAG,"Audio Connected without any listener");
+ disconnectAudioNative(getByteAddress(device));
+ break;
+ }
+
// TODO(BT) should I save the state for next broadcast as the prevState?
mAudioState = BluetoothHeadset.STATE_AUDIO_CONNECTED;
setAudioParameters(device); /*Set proper Audio Paramters.*/
@@ -1458,7 +1464,9 @@ final class HeadsetStateMachine extends StateMachine {
processLocalVrEvent(HeadsetHalConstants.VR_STATE_STOPPED);
break;
case INTENT_SCO_VOLUME_CHANGED:
- processIntentScoVolume((Intent) message.obj, mActiveScoDevice);
+ if (mActiveScoDevice != null) {
+ processIntentScoVolume((Intent) message.obj, mActiveScoDevice);
+ }
break;
case CALL_STATE_CHANGED:
processCallState((HeadsetCallState) message.obj, ((message.arg1 == 1)?true:false));
@@ -1839,6 +1847,11 @@ final class HeadsetStateMachine extends StateMachine {
processLocalVrEvent(HeadsetHalConstants.VR_STATE_STOPPED);
}
break;
+ case INTENT_SCO_VOLUME_CHANGED:
+ if (mActiveScoDevice != null) {
+ processIntentScoVolume((Intent) message.obj, mActiveScoDevice);
+ }
+ break;
case INTENT_BATTERY_CHANGED:
processIntentBatteryChanged((Intent) message.obj);
break;
@@ -2184,6 +2197,11 @@ final class HeadsetStateMachine extends StateMachine {
switch (state) {
case HeadsetHalConstants.AUDIO_STATE_CONNECTED:
+ if (!isScoAcceptable()) {
+ Log.e(TAG,"Audio Connected without any listener");
+ disconnectAudioNative(getByteAddress(device));
+ break;
+ }
mAudioState = BluetoothHeadset.STATE_AUDIO_CONNECTED;
setAudioParameters(device); /* Set proper Audio Parameters. */
mAudioManager.setBluetoothScoOn(true);
@@ -2250,6 +2268,16 @@ final class HeadsetStateMachine extends StateMachine {
Log.e(TAG, "Handsfree phone proxy null for query phone state");
}
}
+
+ private void processIntentScoVolume(Intent intent, BluetoothDevice device) {
+ int volumeValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
+ if (mPhoneState.getSpeakerVolume() != volumeValue) {
+ mPhoneState.setSpeakerVolume(volumeValue);
+ setVolumeNative(HeadsetHalConstants.VOLUME_TYPE_SPK,
+ volumeValue, getByteAddress(device));
+ }
+ }
+
private void processMultiHFDisconnect(BluetoothDevice device) {
log("MultiHFPending state: processMultiHFDisconnect");
if (mActiveScoDevice != null && mActiveScoDevice.equals(device)) {
@@ -2390,10 +2418,16 @@ final class HeadsetStateMachine extends StateMachine {
}
public boolean isBluetoothVoiceDialingEnabled( BluetoothDevice device) {
- int RemoteBrsf = mHeadsetBrsf.get(device);
- Log.d(TAG, "isBluetoothVoiceDialingEnabled mRemoteBrsf: " + RemoteBrsf +
- "supported: " + (RemoteBrsf & BRSF_HF_VOICE_REG_ACT));
- return ((RemoteBrsf & BRSF_HF_VOICE_REG_ACT) != 0x0) ? true : false;
+ int remoteBrsf = 0;
+ if (mHeadsetBrsf != null && !mHeadsetBrsf.isEmpty()) {
+ remoteBrsf = mHeadsetBrsf.get(device);
+ } else {
+ Log.e(TAG,"remote device supported features not found");
+ return false;
+ }
+ Log.d(TAG, "isBluetoothVoiceDialingEnabled mRemoteBrsf: " + remoteBrsf +
+ "supported: " + (remoteBrsf & BRSF_HF_VOICE_REG_ACT));
+ return ((remoteBrsf & BRSF_HF_VOICE_REG_ACT) != 0x0) ? true : false;
}
int getAudioState(BluetoothDevice device) {
@@ -2495,7 +2529,11 @@ final class HeadsetStateMachine extends StateMachine {
// Whereas for VoiceDial we want to activate the SCO connection but we are still
// in MODE_NORMAL and hence the need to explicitly suspend the A2DP stream
mAudioManager.setParameters("A2dpSuspended=true");
- connectAudioNative(getByteAddress(device));
+ if (device != null) {
+ connectAudioNative(getByteAddress(device));
+ } else {
+ Log.e(TAG, "device not found for VR");
+ }
}
if (mStartVoiceRecognitionWakeLock.isHeld()) {
@@ -2663,9 +2701,15 @@ final class HeadsetStateMachine extends StateMachine {
{
// 1. update nrec value
// 2. update headset name
+ int mCodec = 0;
+ int mNrec = 0;
HashMap<String, Integer> AudioParam = mHeadsetAudioParam.get(device);
- int mCodec = AudioParam.get("codec");
- int mNrec = AudioParam.get("NREC");
+ if (AudioParam != null && !AudioParam.isEmpty()) {
+ mCodec = AudioParam.get("codec");
+ mNrec = AudioParam.get("NREC");
+ } else {
+ Log.e(TAG,"setAudioParameters: AudioParam not found");
+ }
if (mCodec != WBS_CODEC) {
Log.d(TAG, "Use NBS PCM samples:" + device);
mAudioManager.setParameters(HEADSET_WBS + "=off");
@@ -3002,8 +3046,7 @@ final class HeadsetStateMachine extends StateMachine {
mPhoneState.setCallState(callState.mCallState);
mPhoneState.setNumber(callState.mNumber);
mPhoneState.setType(callState.mType);
- if (mDialingOut) {
- if (callState.mCallState ==
+ if (mDialingOut && callState.mCallState ==
HeadsetHalConstants.CALL_STATE_DIALING) {
BluetoothDevice device = getDeviceForMessage(DIALING_OUT_TIMEOUT);
if (device == null) {
@@ -3012,11 +3055,7 @@ 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 */
@@ -3087,18 +3126,27 @@ final class HeadsetStateMachine extends StateMachine {
// 0 disable noice reduction
private void processNoiceReductionEvent(int enable, BluetoothDevice device) {
HashMap<String, Integer> AudioParamNrec = mHeadsetAudioParam.get(device);
- if (enable == 1)
- AudioParamNrec.put("NREC", 1);
- else
- AudioParamNrec.put("NREC", 0);
- log("NREC value for device :" + device + " is: " + AudioParamNrec.get("NREC"));
+ if (AudioParamNrec != null && !AudioParamNrec.isEmpty()) {
+ if (enable == 1)
+ AudioParamNrec.put("NREC", 1);
+ else
+ AudioParamNrec.put("NREC", 0);
+ log("NREC value for device :" + device + " is: " +
+ AudioParamNrec.get("NREC"));
+ } else {
+ Log.e(TAG,"processNoiceReductionEvent: AudioParamNrec is null ");
+ }
}
// 2 - WBS on
// 1 - NBS on
private void processWBSEvent(int enable, BluetoothDevice device) {
HashMap<String, Integer> AudioParamCodec = mHeadsetAudioParam.get(device);
- AudioParamCodec.put("codec", enable);
+ if (AudioParamCodec != null && !AudioParamCodec.isEmpty()) {
+ AudioParamCodec.put("codec", enable);
+ } else {
+ Log.e(TAG,"processWBSEvent: AudioParamNrec is null ");
+ }
if (enable == 2) {
Log.d(TAG, "AudioManager.setParameters bt_wbs=on for " +
device.getName() + " - " + device.getAddress());
@@ -3615,6 +3663,14 @@ final class HeadsetStateMachine extends StateMachine {
(mPhoneState.getCallState() != HeadsetHalConstants.CALL_STATE_IDLE));
}
+ // Accept incoming SCO only when there is active call, VR activated,
+ // active VOIP call and Incoming call with inband ringtone supported
+ private boolean isScoAcceptable() {
+ return (((mPhoneState.getCallState() == HeadsetHalConstants.CALL_STATE_INCOMING) &&
+ ((mLocalBrsf & BRSF_AG_IN_BAND_RING) != 0)) || mVoiceRecognitionStarted ||
+ isInCall());
+ }
+
boolean isConnected() {
IState currentState = getCurrentState();
return (currentState == mConnected || currentState == mAudioOn);
diff --git a/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java b/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
index 10464b9ee..bf01bbf34 100644
--- a/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
+++ b/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
@@ -2149,6 +2149,32 @@ final class HeadsetClientStateMachine extends StateMachine {
+ event.valueInt);
processAudioEvent(event.valueInt, event.device);
break;
+ case EVENT_TYPE_RING_INDICATION:
+ /* PTS test case TC_HF_ICA_BV_05_I creates SCO even
+ * after disabling in-band ringtone, disconnect SCO
+ * if inband ringtone is disabled */
+ Log.i(TAG,"Ring Indication in Audio connected state " +
+ "mInBandRingtone " + mInBandRingtone);
+ if (mInBandRingtone !=
+ HeadsetClientHalConstants.IN_BAND_RING_NOT_PROVIDED) {
+ break;
+ }
+ if (disconnectAudioNative(getByteAddress(mCurrentDevice))) {
+ mAudioState = BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
+ //abandon audio focus
+ if (mAudioManager.getMode() != AudioManager.MODE_NORMAL) {
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ Log.d(TAG, "abandonAudioFocus");
+ //abandon audio focus after the mode has been set back to normal
+ mAudioManager.abandonAudioFocusForCall();
+ }
+ Log.d(TAG,"hfp_enable=false");
+ mAudioManager.setParameters("hfp_enable=false");
+ broadcastAudioState(mCurrentDevice,
+ BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED,
+ BluetoothHeadsetClient.STATE_AUDIO_CONNECTED);
+ }
+ break;
default:
return NOT_HANDLED;
}
diff --git a/src/com/android/bluetooth/map/BluetoothMapContentObserver.java b/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
index 8160809c5..4a8caaafb 100644
--- a/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
+++ b/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
@@ -1045,13 +1045,13 @@ public class BluetoothMapContentObserver {
Intent intent;
intent = new Intent(ACTION_MESSAGE_DELIVERY, null);
intent.putExtra("HANDLE", msgInfo.id);
- deliveryIntents.add(PendingIntent.getBroadcast(mContext, 0, intent,
- PendingIntent.FLAG_UPDATE_CURRENT));
+ deliveryIntents.add(PendingIntent.getBroadcast(mContext,(int)System.currentTimeMillis(),
+ intent, PendingIntent.FLAG_UPDATE_CURRENT));
intent = new Intent(ACTION_MESSAGE_SENT, null);
intent.putExtra("HANDLE", msgInfo.id);
- sentIntents.add(PendingIntent.getBroadcast(mContext, 0, intent,
- PendingIntent.FLAG_UPDATE_CURRENT));
+ sentIntents.add(PendingIntent.getBroadcast(mContext, (int)System.currentTimeMillis(),
+ intent,PendingIntent.FLAG_UPDATE_CURRENT));
}
Log.d(TAG, "sendMessage to " + msgInfo.phone);
diff --git a/src/com/android/bluetooth/map/BluetoothMapbMessageMmsEmail.java b/src/com/android/bluetooth/map/BluetoothMapbMessageMmsEmail.java
index bab40d9f8..59f77efea 100755
--- a/src/com/android/bluetooth/map/BluetoothMapbMessageMmsEmail.java
+++ b/src/com/android/bluetooth/map/BluetoothMapbMessageMmsEmail.java
@@ -749,7 +749,8 @@ public class BluetoothMapbMessageMmsEmail extends BluetoothMapbMessage {
if (beginMsg == -1) {
throw new IllegalArgumentException("Ill-formatted bMessage, no BEGIN:MSG");
}
- int endMsg = body.lastIndexOf("END:MSG", beginMsg);
+ //Last occurence of END:MSG
+ int endMsg = body.lastIndexOf("END:MSG");
if (endMsg == -1) {
throw new IllegalArgumentException("Ill-formatted bMessage, no END:MSG");
}
@@ -764,7 +765,8 @@ public class BluetoothMapbMessageMmsEmail extends BluetoothMapbMessage {
int endVersionPos;
if(rfc822Flag == 0){
if(mimeFlag == 0) {
- endVersionPos = body.lastIndexOf("END:MSG", beginVersionPos) ;
+ //Last occurence of END:MSG
+ endVersionPos = body.lastIndexOf("END:MSG") ;
if (endVersionPos != -1) {
setEmailBody(body.substring(beginVersionPos, (endVersionPos - CRLF.length())));
} else {
diff --git a/src/com/android/bluetooth/opp/BluetoothOppNotification.java b/src/com/android/bluetooth/opp/BluetoothOppNotification.java
index cd4b58344..161cd576f 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppNotification.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppNotification.java
@@ -45,6 +45,7 @@ import android.database.sqlite.SQLiteException;
import android.content.res.Resources.NotFoundException;
import android.net.Uri;
import android.util.Log;
+import android.os.PowerManager;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
@@ -102,7 +103,7 @@ class BluetoothOppNotification {
private NotificationUpdateThread mUpdateNotificationThread;
- private int mPendingUpdate = 0;
+ private PowerManager mPowerManager;
private static final int NOTIFICATION_ID_OUTBOUND = -1000005;
@@ -111,8 +112,10 @@ class BluetoothOppNotification {
private boolean mOutboundUpdateCompleteNotification = true;
private boolean mInboundUpdateCompleteNotification = true;
+ private int confirmation = 0;
private int mInboundActiveNotificationId = 0;
private int mOutboundActiveNotificationId = 0;
+ private int mRunning = 0;
private int mIncomingShownId = 0;
@@ -148,6 +151,7 @@ class BluetoothOppNotification {
mNotificationMgr = (NotificationManager)mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotifications = new HashMap<String, NotificationItem>();
+ mPowerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
}
/**
@@ -155,14 +159,10 @@ class BluetoothOppNotification {
*/
public void updateNotification() {
synchronized (BluetoothOppNotification.this) {
- mPendingUpdate++;
- if (mPendingUpdate > 1) {
- if (V) Log.v(TAG, "update too frequent, put in queue");
- return;
- }
- if (!mHandler.hasMessages(NOTIFY)) {
- if (V) Log.v(TAG, "send message");
- mHandler.sendMessage(mHandler.obtainMessage(NOTIFY));
+ if (mUpdateNotificationThread == null) {
+ if (V) Log.v(TAG, "new notify thread!!!");
+ mUpdateNotificationThread = new NotificationUpdateThread();
+ mUpdateNotificationThread.start();
}
}
}
@@ -170,45 +170,24 @@ class BluetoothOppNotification {
public void btOffNotification() {
if (V) Log.v(TAG, "Update Notification while BT is Turning OFF");
synchronized (BluetoothOppNotification.this) {
+ if (mUpdateNotificationThread != null) {
+ try {
+ mUpdateNotificationThread.interrupt();
+ mUpdateNotificationThread.join();
+ mUpdateNotificationThread = null;
+ } catch (InterruptedException ie) {
+ Log.e(TAG, "Notification thread join interrupted");
+ }
+ }
+
updateActiveNotification();
- mPendingUpdate = 0;
mInboundUpdateCompleteNotification = true;
mOutboundUpdateCompleteNotification = true;
updateCompletedNotification();
- mPendingUpdate = 0;
cancelIncomingFileConfirmNotification();
}
}
- private static final int NOTIFY = 0;
- // Use 1 second timer to limit notification frequency.
- // 1. On the first notification, create the update thread.
- // Buffer other updates.
- // 2. Update thread will clear mPendingUpdate.
- // 3. Handler sends a delayed message to self
- // 4. Handler checks if there are any more updates after 1 second.
- // 5. If there is an update, update it else stop.
- private Handler mHandler = new Handler() {
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case NOTIFY:
- synchronized (BluetoothOppNotification.this) {
- if (mPendingUpdate > 0 && mUpdateNotificationThread == null) {
- if (V) Log.v(TAG, "new notify threadi!");
- mUpdateNotificationThread = new NotificationUpdateThread();
- mUpdateNotificationThread.start();
- if (V) Log.v(TAG, "send delay message");
- mHandler.sendMessageDelayed(mHandler.obtainMessage(NOTIFY), 1000);
- } else if (mPendingUpdate > 0) {
- if (V) Log.v(TAG, "previous thread is not finished yet");
- mHandler.sendMessageDelayed(mHandler.obtainMessage(NOTIFY), 1000);
- }
- break;
- }
- }
- }
- };
-
private class NotificationUpdateThread extends Thread {
public NotificationUpdateThread() {
@@ -218,18 +197,35 @@ class BluetoothOppNotification {
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- synchronized (BluetoothOppNotification.this) {
- if (mUpdateNotificationThread != this) {
- throw new IllegalStateException(
- "multiple UpdateThreads in BluetoothOppNotification");
+ do {
+ synchronized (BluetoothOppNotification.this) {
+ if (mUpdateNotificationThread != this) {
+ throw new IllegalStateException(
+ "multiple UpdateThreads in BluetoothOppNotification");
+ }
}
- mPendingUpdate = 0;
- }
- updateActiveNotification();
- updateCompletedNotification();
- updateIncomingFileConfirmNotification();
+
+ updateActiveNotification();
+ updateCompletedNotification();
+ updateIncomingFileConfirmNotification();
+
+ try {
+ if ((confirmation == BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED)
+ || mPowerManager.isScreenOn()) {
+ Thread.sleep(BluetoothShare.UI_UPDATE_INTERVAL);
+ }
+ } catch (InterruptedException e) {
+ if (V) Log.v(TAG, "NotificationThread sleep is interrupted (1), exiting");
+ return;
+ }
+
+ if (V) Log.v(TAG, "Running = " + mRunning);
+ } while ((mRunning > 0) && (mPowerManager.isScreenOn()
+ || (confirmation == BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED)));
+
synchronized (BluetoothOppNotification.this) {
mUpdateNotificationThread = null;
+ if (V) Log.v(TAG, "NotificationThread is stopped!!!");
}
}
}
@@ -258,6 +254,7 @@ class BluetoothOppNotification {
cursor = mContext.getContentResolver().query(BluetoothShare.CONTENT_URI, null,
WHERE_RUNNING, null, BluetoothShare._ID);
+ mRunning = cursor.getCount();
} catch (SQLiteException e) {
cursor = null;
Log.e(TAG, "SQLite exception: " + e);
@@ -317,7 +314,7 @@ class BluetoothOppNotification {
int id = cursor.getInt(idIndex);
long total = cursor.getLong(totalBytesIndex);
long current = cursor.getLong(currentBytesIndex);
- int confirmation = cursor.getInt(confirmIndex);
+ confirmation = cursor.getInt(confirmIndex);
String destination = cursor.getString(destinationIndex);
String fileName = cursor.getString(dataIndex);
@@ -385,6 +382,7 @@ class BluetoothOppNotification {
intent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_PROGRESS, progress);
intent.putExtra(Constants.EXTRA_BT_OPP_ADDRESS, item.destination);
mContext.sendBroadcast(intent, Constants.HANDOVER_STATUS_PERMISSION);
+ if (V) Log.v(TAG, "Handover OPP transfer is inprogress");
continue;
}
// Build the notification object
diff --git a/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java b/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
index 6dcf5ef9a..6684b1fd7 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
@@ -85,6 +85,8 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession {
private Handler mCallback;
+ private PowerManager pm;
+
private long position;
public BluetoothOppObexClientSession(Context context, ObexTransport transport) {
@@ -133,7 +135,6 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession {
}
private class ContentResolverUpdateThread extends Thread {
- private static final int sSleepTime = 1000;
private Uri contentUri;
private Context mContext1;
private volatile boolean interrupted = false;
@@ -150,10 +151,12 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession {
ContentValues updateValues;
while (true) {
- updateValues = new ContentValues();
- updateValues.put(BluetoothShare.CURRENT_BYTES, position);
- mContext1.getContentResolver().update(contentUri, updateValues,
- null, null);
+ if (pm.isScreenOn()) {
+ 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 == true) {
@@ -162,7 +165,7 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession {
}
try {
- Thread.sleep(sSleepTime);
+ Thread.sleep(BluetoothShare.UI_UPDATE_INTERVAL);
} catch (InterruptedException e1) {
if (V) Log.v(TAG, "ContentResolverUpdateThread was interrupted (1), exiting");
return;
@@ -208,7 +211,7 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession {
waitingForShare = true;
mWaitingForRemote = false;
mNumShares = initialNumShares;
- PowerManager pm = (PowerManager)mContext1.getSystemService(Context.POWER_SERVICE);
+ pm = (PowerManager)mContext1.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
}
@@ -362,6 +365,7 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession {
if (status == BluetoothShare.STATUS_SUCCESS) {
Message msg = Message.obtain(mCallback);
msg.what = BluetoothOppObexSession.MSG_SHARE_COMPLETE;
+ mInfo.mStatus = status;
msg.obj = mInfo;
msg.sendToTarget();
} else {
@@ -628,7 +632,7 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession {
if (uiUpdateThread == null) {
uiUpdateThread = new ContentResolverUpdateThread(mContext1,
- contentUri);
+ contentUri);
if (V) Log.v(TAG, "Worker for Updation : Created");
uiUpdateThread.start();
}
@@ -664,8 +668,11 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession {
} else if (!mInterrupted && position == fileInfo.mLength) {
long endTime = System.currentTimeMillis();
Log.i(TAG, "SendFile finished sending file " + fileInfo.mFileName
- + " length " + fileInfo.mLength
- + "Bytes in " + (endTime - beginTime) + "ms" );
+ + " length " + fileInfo.mLength + " Bytes. Approx. throughput is "
+ + BluetoothShare.throughputInKbps(fileInfo.mLength,
+ (endTime - beginTime))
+ + " Kbps");
+ status = BluetoothShare.STATUS_SUCCESS;
outputStream.close();
} else {
error = true;
diff --git a/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java b/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java
index 110305804..c7876409e 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java
@@ -110,20 +110,22 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
private BluetoothOppReceiveFileInfo mFileInfo;
+ private PowerManager pm;
+
private WakeLock mWakeLock;
private WakeLock mPartialWakeLock;
+ private long position;
+
boolean mTimeoutMsgSent = false;
boolean mTransferInProgress = false;
- private int position;
-
public BluetoothOppObexServerSession(Context context, ObexTransport transport) {
mContext = context;
mTransport = transport;
- PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+ pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.ON_AFTER_RELEASE, TAG);
mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
@@ -194,7 +196,6 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
private class ContentResolverUpdateThread extends Thread {
- private static final int sSleepTime = 1000;
private Uri contentUri;
private Context mContext1;
private volatile boolean interrupted = false;
@@ -210,10 +211,12 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
ContentValues updateValues;
while (true) {
- updateValues = new ContentValues();
- updateValues.put(BluetoothShare.CURRENT_BYTES, position);
- mContext1.getContentResolver().update(contentUri, updateValues,
- null, null);
+ if (pm.isScreenOn()) {
+ 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 == true) {
@@ -222,7 +225,7 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
}
try {
- Thread.sleep(sSleepTime);
+ Thread.sleep(BluetoothShare.UI_UPDATE_INTERVAL);
} catch (InterruptedException e1) {
if (V) Log.v(TAG, "Server ContentResolverUpdateThread was interrupted (1), exiting");
return;
@@ -381,9 +384,7 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
values.put(BluetoothShare.FILENAME_HINT, name);
- if (length != null) {
- values.put(BluetoothShare.TOTAL_BYTES, length.intValue());
- }
+ values.put(BluetoothShare.TOTAL_BYTES, length);
values.put(BluetoothShare.MIMETYPE, mimeType);
@@ -661,8 +662,9 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
if (position == fileInfo.mLength) {
long endTime = System.currentTimeMillis();
Log.i(TAG, "Receiving file completed for " + fileInfo.mFileName
- + " length " + fileInfo.mLength
- + " Bytes in " + (endTime - beginTime) + "ms" );
+ + " length " + fileInfo.mLength + " Bytes. Approx. throughput is "
+ + BluetoothShare.throughputInKbps(fileInfo.mLength, (endTime - beginTime))
+ + " Kbps");
status = BluetoothShare.STATUS_SUCCESS;
} else {
Log.i(TAG, "Reading file failed at " + position + " of " + fileInfo.mLength);
diff --git a/src/com/android/bluetooth/opp/BluetoothOppProvider.java b/src/com/android/bluetooth/opp/BluetoothOppProvider.java
index 132b950df..a3f3ef30f 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppProvider.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppProvider.java
@@ -228,6 +228,13 @@ public final class BluetoothOppProvider extends ContentProvider {
}
}
+ private static final void copyLong(String key, ContentValues from, ContentValues to) {
+ Long i = from.getAsLong(key);
+ if (i != null) {
+ to.put(key, i);
+ }
+ }
+
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
@@ -245,8 +252,7 @@ public final class BluetoothOppProvider extends ContentProvider {
copyString(BluetoothShare.DESTINATION, values, filteredValues);
copyInteger(BluetoothShare.VISIBILITY, values, filteredValues);
- copyInteger(BluetoothShare.TOTAL_BYTES, values, filteredValues);
-
+ copyLong(BluetoothShare.TOTAL_BYTES, values, filteredValues);
if (values.getAsInteger(BluetoothShare.VISIBILITY) == null) {
filteredValues.put(BluetoothShare.VISIBILITY, BluetoothShare.VISIBILITY_VISIBLE);
}
diff --git a/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java b/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java
index 4bd9c21fd..327261add 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java
@@ -113,7 +113,7 @@ public class BluetoothOppReceiveFileInfo {
try {
if (metadataCursor.moveToFirst()) {
hint = metadataCursor.getString(0);
- length = metadataCursor.getInt(1);
+ length = metadataCursor.getLong(1);
mimeType = metadataCursor.getString(2);
}
} finally {
diff --git a/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java b/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java
index f060a04e6..3901e7a31 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java
@@ -127,7 +127,7 @@ public class BluetoothOppSendFileInfo {
try {
if (metadataCursor.moveToFirst()) {
fileName = metadataCursor.getString(0);
- length = metadataCursor.getInt(1);
+ length = metadataCursor.getLong(1);
if (D) Log.d(TAG, "fileName = " + fileName + " length = " + length);
}
} finally {
diff --git a/src/com/android/bluetooth/opp/BluetoothOppService.java b/src/com/android/bluetooth/opp/BluetoothOppService.java
index ad99c7e29..e0acd273c 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppService.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppService.java
@@ -96,8 +96,6 @@ public class BluetoothOppService extends Service {
/** Class to handle Notification Manager updates */
private BluetoothOppNotification mNotifier;
- private boolean mPendingUpdate;
-
private UpdateThread mUpdateThread;
private ArrayList<BluetoothOppShareInfo> mShares;
@@ -418,6 +416,17 @@ public class BluetoothOppService extends Service {
break;
case BluetoothAdapter.STATE_TURNING_OFF:
if (V) Log.v(TAG, "Receiver DISABLED_ACTION ");
+
+ if (mUpdateThread != null) {
+ try {
+ mUpdateThread.interrupt();
+ mUpdateThread.join();
+ mUpdateThread = null;
+ } catch (InterruptedException ie) {
+ Log.e(TAG, "OPPService Thread join interrupted");
+ }
+ }
+
mNotifier.btOffNotification();
//FIX: Don't block main thread
/*
@@ -439,10 +448,10 @@ public class BluetoothOppService extends Service {
private void updateFromProvider() {
synchronized (BluetoothOppService.this) {
- mPendingUpdate = true;
if ((mUpdateThread == null) && (mAdapter != null)
&& mAdapter.isEnabled()) {
if (V) Log.v(TAG, "Starting a new thread");
+ mPowerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
mUpdateThread = new UpdateThread();
mUpdateThread.start();
}
@@ -459,25 +468,14 @@ public class BluetoothOppService extends Service {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
boolean keepService = false;
- for (;;) {
+ do {
synchronized (BluetoothOppService.this) {
if (mUpdateThread != this) {
throw new IllegalStateException(
"multiple UpdateThreads in BluetoothOppService");
}
- if (V) Log.v(TAG, "pendingUpdate is " + mPendingUpdate + " keepUpdateThread is "
- + keepService + " sListenStarted is " + mListenStarted);
- if (!mPendingUpdate) {
- mUpdateThread = null;
- if (!keepService && !mListenStarted) {
- if (V) Log.v(TAG, "Need to stop self");
- stopSelf();
- break;
- }
- if (V) Log.v(TAG, "***returning from updatethread***");
- return;
- }
- mPendingUpdate = false;
+ if (V) Log.v(TAG, "keepUpdateThread is " + keepService + " sListenStarted is "
+ + mListenStarted);
}
Cursor cursor;
try {
@@ -612,6 +610,39 @@ public class BluetoothOppService extends Service {
cursor.close();
cursor = null;
+
+ if (V) {
+ if (mServerSession != null) {
+ Log.v(TAG, "Server Session is active");
+ } else {
+ Log.v(TAG, "No active Server Session");
+ }
+
+ if (mTransfer != null) {
+ Log.v(TAG, "Client Session is active");
+ } else {
+ Log.v(TAG, "No active Client Session");
+ }
+ }
+
+ try {
+ if (((mServerSession != null) || (mTransfer != null))
+ && mPowerManager.isScreenOn()) {
+ Thread.sleep(BluetoothShare.UI_UPDATE_INTERVAL);
+ }
+ } catch (InterruptedException e) {
+ if (V) Log.v(TAG, "OppService Thread sleep is interrupted (1), exiting");
+ return;
+ }
+ } while (mPowerManager.isScreenOn() && ((mServerSession != null) || (mTransfer != null)));
+
+ synchronized (BluetoothOppService.this) {
+ mUpdateThread = null;
+ if (!keepService && !mListenStarted) {
+ if (V) Log.v(TAG, "Need to stop self");
+ stopSelf();
+ }
+ if (V) Log.v(TAG, "***returning from updatethread***");
}
}
@@ -808,26 +839,12 @@ public class BluetoothOppService extends Service {
info.mConfirm = newConfirm;
int newStatus = cursor.getInt(statusColumn);
int oldStatus = info.mStatus;
- if (!BluetoothShare.isStatusCompleted(info.mStatus)
- && BluetoothShare.isStatusCompleted(newStatus)) {
+ if (BluetoothShare.isStatusCompleted(info.mStatus)) {
mNotifier.mNotificationMgr.cancel(info.mId);
}
if (V) Log.v(TAG," UpdateShare: oldStatus = " + oldStatus + " newStatus = " + newStatus);
info.mStatus = newStatus;
- if ((!BluetoothShare.isStatusCompleted(oldStatus))
- && (BluetoothShare.isStatusCompleted(newStatus))) {
- if (V) Log.v(TAG," UpdateShare: Share Completed: oldStatus = " + oldStatus + " newStatus = " + newStatus);
- try {
- if((info.mDirection == BluetoothShare.DIRECTION_OUTBOUND) && (mTransfer != null)) {
- mTransfer.markShareComplete(newStatus);
- } else if (mServerTransfer != null) {
- mServerTransfer.markShareComplete(newStatus);
- }
- } catch (Exception e) {
- Log.e(TAG, "Exception: updateShare: oldStatus: " + oldStatus + " newStatus: " + newStatus);
- }
- }
info.mTotalBytes = cursor.getLong(cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES));
info.mCurrentBytes = cursor.getLong(cursor
.getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES));
diff --git a/src/com/android/bluetooth/opp/BluetoothOppTransfer.java b/src/com/android/bluetooth/opp/BluetoothOppTransfer.java
index 55d116f73..acdd188de 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppTransfer.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppTransfer.java
@@ -564,31 +564,7 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
setConfirmed();
}
}
- public void markShareComplete(int newstatus) {
- Log.d(TAG,"markShareComplete: newStatus = " + newstatus);
- if (newstatus == BluetoothShare.STATUS_SUCCESS) {
- Message msg = Message.obtain(mSessionHandler);
- msg.what = BluetoothOppObexSession.MSG_SHARE_COMPLETE;
- msg.obj = mCurrentShare;
- msg.sendToTarget();
- } else if ((newstatus == BluetoothShare.STATUS_FORBIDDEN) &&
- Constants.ZERO_LENGTH_FILE) {
- /* Mark the status as success when a zero length file is rejected
- * by the remote device. It allows us to continue the transfer if
- * we have a batch and the file(s) are yet to be sent in the row.
- */
- Message msg = Message.obtain(mSessionHandler);
- msg.what = BluetoothOppObexSession.MSG_SHARE_COMPLETE;
- msg.obj = mCurrentShare;
- msg.sendToTarget();
- Constants.ZERO_LENGTH_FILE = false;
- } else {
- Message msg = Message.obtain(mSessionHandler);
- msg.what = BluetoothOppObexSession.MSG_SESSION_ERROR;
- msg.obj = mCurrentShare;
- msg.sendToTarget();
- }
- }
+
/**
* Set transfer confirmed status. It should only be called for inbound
* transfer
diff --git a/src/com/android/bluetooth/opp/BluetoothShare.java b/src/com/android/bluetooth/opp/BluetoothShare.java
index d0333257a..3242e7e34 100644
--- a/src/com/android/bluetooth/opp/BluetoothShare.java
+++ b/src/com/android/bluetooth/opp/BluetoothShare.java
@@ -421,4 +421,16 @@ public final class BluetoothShare implements BaseColumns {
*/
public static final int STATUS_CONNECTION_ERROR = 497;
+ /**
+ * Ongoing transfer progress update interval to 1 second
+ */
+ public static final int UI_UPDATE_INTERVAL = 1000;
+
+ /**
+ * Returns the throughput of the file transfer
+ */
+ public static float throughputInKbps(long fileSize, long timeDuration) {
+ float throughput = (float)(fileSize * 8 * 1000) / (timeDuration * 1024);
+ return throughput;
+ }
}