Loading android/app/res/values/strings_pbap.xml +1 −0 Original line number Diff line number Diff line Loading @@ -24,5 +24,6 @@ <string name="alwaysallowed">Always allowed?</string> <string name="defaultname">Carkit</string> <string name="unknownName">Unknown name</string> <string name="ownNumber">My phone number</string> <string name="defaultnumber">000000</string> </resources> android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java +55 −15 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.os.Handler; import android.text.TextUtils; import android.util.Log; import android.provider.CallLog.Calls; import android.provider.ContactsContract.Contacts; import android.provider.CallLog; import java.io.IOException; Loading Loading @@ -144,6 +145,12 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { private BluetoothPbapVcardManager mVcardManager; private int mOrderBy = ORDER_BY_INDEXED; public static int ORDER_BY_INDEXED = 0; public static int ORDER_BY_ALPHABETICAL = 1; public static class ContentType { public static final int PHONEBOOK = 1; Loading Loading @@ -330,16 +337,16 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { if (D) Log.d(TAG, "Guess what carkit actually want from current path (" + mCurrentPath + ")"); if (mCurrentPath.compareTo(PB_PATH) == 0) { if (mCurrentPath.equals(PB_PATH)) { appParamValue.needTag = ContentType.PHONEBOOK; } else if (mCurrentPath.compareTo(ICH_PATH) == 0) { } else if (mCurrentPath.equals(ICH_PATH)) { appParamValue.needTag = ContentType.INCOMING_CALL_HISTORY; } else if (mCurrentPath.compareTo(OCH_PATH) == 0) { } else if (mCurrentPath.equals(OCH_PATH)) { appParamValue.needTag = ContentType.OUTGOING_CALL_HISTORY; } else if (mCurrentPath.compareTo(MCH_PATH) == 0) { } else if (mCurrentPath.equals(MCH_PATH)) { appParamValue.needTag = ContentType.MISSED_CALL_HISTORY; mNeedNewMissedCallsNum = true; } else if (mCurrentPath.compareTo(CCH_PATH) == 0) { } else if (mCurrentPath.equals(CCH_PATH)) { appParamValue.needTag = ContentType.COMBINED_CALL_HISTORY; } else { Log.w(TAG, "mCurrentpath is not valid path!!!"); Loading Loading @@ -419,8 +426,16 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { public String searchValue; // Indicate which vCard parameter the search operation shall be carried // out on. Can be "Name | Number | Sound", default value is "Name". public String searchAttr; // Indicate which sorting order shall be used for the // <x-bt/vcard-listing> listing object. // Can be "Alphabetical | Indexed | Phonetical", default value is // "Indexed". public String order; public int needTag; public boolean vcard21; Loading @@ -430,6 +445,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { listStartOffset = 0; searchValue = ""; searchAttr = ""; order = ""; needTag = 0x00; vcard21 = true; } Loading @@ -437,7 +453,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { public void dump() { Log.i(TAG, "maxListCount=" + maxListCount + " listStartOffset=" + listStartOffset + " searchValue=" + searchValue + " searchAttr=" + searchAttr + " needTag=" + needTag + " vcard21=" + vcard21); + needTag + " vcard21=" + vcard21 + " order=" + order); } } Loading @@ -453,8 +469,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { i += ApplicationParameter.TRIPLET_LENGTH.FILTER_LENGTH; break; case ApplicationParameter.TRIPLET_TAGID.ORDER_TAGID: // TODO capture this field to use i += 2; // length and tag field in triplet appParamValue.order = Byte.toString(appParam[i]); i += ApplicationParameter.TRIPLET_LENGTH.ORDER_LENGTH; break; case ApplicationParameter.TRIPLET_TAGID.SEARCH_VALUE_TAGID: Loading Loading @@ -491,7 +507,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { break; case ApplicationParameter.TRIPLET_TAGID.FORMAT_TAGID: i += 2;// length field in triplet if (Byte.toString(appParam[i]).compareTo("0") != 0) { if (appParam[i] != 0) { appParamValue.vcard21 = false; } i += ApplicationParameter.TRIPLET_LENGTH.FORMAT_LENGTH; Loading Loading @@ -521,8 +537,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { // Phonebook listing request if (type == ContentType.PHONEBOOK) { // begin of search by name if (searchAttr.compareTo("0") == 0) { ArrayList<String> nameList = mVcardManager.getPhonebookNameList(); if (searchAttr.equals("0")) { ArrayList<String> nameList = mVcardManager.getPhonebookNameList(mOrderBy ); int requestSize = nameList.size() >= maxListCount ? maxListCount : nameList.size(); int startPoint = listStartOffset; int endPoint = startPoint + requestSize; Loading Loading @@ -555,7 +571,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { } }// end of search by name // begin of search by number else if (searchAttr.compareTo("1") == 0) { else if (searchAttr.equals("1")) { ArrayList<String> numberList = mVcardManager.getPhonebookNumberList(); int requestSize = numberList.size() >= maxListCount ? maxListCount : numberList .size(); Loading Loading @@ -770,9 +786,9 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { // If searchAttr is not set by PCE, set default value per spec. appParamValue.searchAttr = "0"; if (D) Log.d(TAG, "searchAttr is not set by PCE, assume search by name by default"); } else if (searchAttr.compareTo("0") != 0 && searchAttr.compareTo("1") != 0) { } else if (!searchAttr.equals("0") && !searchAttr.equals("1")) { Log.w(TAG, "search attr not supported"); if (searchAttr.compareTo("2") == 0) { if (searchAttr.equals("2")) { // search by sound is not supported currently Log.w(TAG, "do not support search by sound"); return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED; Loading @@ -793,6 +809,30 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { return ResponseCodes.OBEX_HTTP_OK; } String orderPara = appParamValue.order.trim(); if (TextUtils.isEmpty(orderPara)) { // If order parameter is not set by PCE, set default value per spec. appParamValue.order = "0"; if (D) Log.d(TAG, "Order parameter is not set by PCE. " + "Assume order by 'Indexed' by default"); } else if (!orderPara.equals("0") && !orderPara.equals("1")) { if (V) Log.v(TAG, "Order parameter is not supported: " + appParamValue.order); if (orderPara.equals("2")) { // Order by sound is not supported currently Log.w(TAG, "Do not support order by sound"); return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED; } return ResponseCodes.OBEX_HTTP_PRECON_FAILED; } else { Log.i(TAG, "Order parameter is valid: " + orderPara); } if (orderPara.equals("0")) { mOrderBy = ORDER_BY_INDEXED; } else if (orderPara.equals("1")) { mOrderBy = ORDER_BY_ALPHABETICAL; } int sendResult = sendVcardListingXml(appParamValue.needTag, op, appParamValue.maxListCount, appParamValue.listStartOffset, appParamValue.searchValue, appParamValue.searchAttr); Loading Loading @@ -835,8 +875,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { String ownerVcard = mVcardManager.getOwnerPhoneNumberVcard(vcard21); return pushBytes(op, ownerVcard); } else { return mVcardManager.composeAndSendPhonebookVcards(op, intIndex, intIndex, vcard21, null); return mVcardManager.composeAndSendPhonebookOneVcard(op, intIndex, vcard21, null, mOrderBy ); } } else { if (intIndex <= 0 || intIndex > size) { Loading android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java +1 −1 Original line number Diff line number Diff line Loading @@ -427,7 +427,7 @@ public class BluetoothPbapService extends Service { } sLocalPhoneName = tm.getLine1AlphaTag(); if (TextUtils.isEmpty(sLocalPhoneName)) { sLocalPhoneName = this.getString(R.string.unknownName); sLocalPhoneName = this.getString(R.string.ownNumber); } } Loading android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java +98 −32 Original line number Diff line number Diff line Loading @@ -90,10 +90,23 @@ public class BluetoothPbapVcardManager { private static final int CONTACTS_DISPLAY_NAME_COLUMN_INDEX = 4; static final String SORT_ORDER_NAME = Contacts.DISPLAY_NAME + " ASC"; static final String SORT_ORDER_PHONE_NUMBER = CommonDataKinds.Phone.NUMBER + " ASC"; static final String[] CONTACTS_PROJECTION = new String[] { Contacts._ID, // 0 Contacts.DISPLAY_NAME, // 1 }; static final int CONTACTS_ID_COLUMN_INDEX = 0; static final int CONTACTS_NAME_COLUMN_INDEX = 1; // call histories use dynamic handles, and handles should order by date; the // most recently one should be the first handle. In table "calls", _id and // date are consistent in ordering, to implement simply, we sort by _id // here. static final String CALLLOG_SORT_ORDER = Calls._ID + " DESC"; public BluetoothPbapVcardManager(final Context context) { mContext = context; mResolver = mContext.getContentResolver(); Loading Loading @@ -123,7 +136,7 @@ public class BluetoothPbapVcardManager { } public final int getContactsSize() { Uri myUri = RawContacts.CONTENT_URI; final Uri myUri = Contacts.CONTENT_URI; int size = 0; Cursor contactCursor = null; try { Loading @@ -140,7 +153,7 @@ public class BluetoothPbapVcardManager { } public final int getCallHistorySize(final int type) { Uri myUri = CallLog.Calls.CONTENT_URI; final Uri myUri = CallLog.Calls.CONTENT_URI; String selection = BluetoothPbapObexServer.createSelectionPara(type); int size = 0; Cursor callCursor = null; Loading @@ -159,7 +172,7 @@ public class BluetoothPbapVcardManager { } public final ArrayList<String> loadCallHistoryList(final int type) { Uri myUri = CallLog.Calls.CONTENT_URI; final Uri myUri = CallLog.Calls.CONTENT_URI; String selection = BluetoothPbapObexServer.createSelectionPara(type); String[] projection = new String[] { Calls.NUMBER, Calls.CACHED_NAME Loading @@ -171,7 +184,7 @@ public class BluetoothPbapVcardManager { ArrayList<String> list = new ArrayList<String>(); try { callCursor = mResolver.query(myUri, projection, selection, null, CallLog.Calls.DEFAULT_SORT_ORDER); CALLLOG_SORT_ORDER); if (callCursor != null) { for (callCursor.moveToFirst(); !callCursor.isAfterLast(); callCursor.moveToNext()) { Loading @@ -191,18 +204,24 @@ public class BluetoothPbapVcardManager { return list; } public final ArrayList<String> getPhonebookNameList() { public final ArrayList<String> getPhonebookNameList(final int orderByWhat) { ArrayList<String> nameList = new ArrayList<String>(); nameList.add(BluetoothPbapService.getLocalPhoneName()); Uri myUri = Phone.CONTENT_URI; Cursor phoneCursor = null; final Uri myUri = Contacts.CONTENT_URI; Cursor contactCursor = null; try { phoneCursor = mResolver.query(myUri, PHONES_PROJECTION, null, null, SORT_ORDER_NAME); if (phoneCursor != null) { for (phoneCursor.moveToFirst(); !phoneCursor.isAfterLast(); phoneCursor if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_INDEXED) { contactCursor = mResolver.query(myUri, CONTACTS_PROJECTION, null, null, Contacts._ID); } else if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) { contactCursor = mResolver.query(myUri, CONTACTS_PROJECTION, null, null, Contacts.DISPLAY_NAME); } if (contactCursor != null) { for (contactCursor.moveToFirst(); !contactCursor.isAfterLast(); contactCursor .moveToNext()) { String name = phoneCursor.getString(CONTACTS_DISPLAY_NAME_COLUMN_INDEX); String name = contactCursor.getString(CONTACTS_NAME_COLUMN_INDEX); if (TextUtils.isEmpty(name)) { name = mContext.getString(android.R.string.unknownName); } Loading @@ -210,8 +229,8 @@ public class BluetoothPbapVcardManager { } } } finally { if (phoneCursor != null) { phoneCursor.close(); if (contactCursor != null) { contactCursor.close(); } } return nameList; Loading @@ -221,7 +240,7 @@ public class BluetoothPbapVcardManager { ArrayList<String> numberList = new ArrayList<String>(); numberList.add(BluetoothPbapService.getLocalPhoneNum()); Uri myUri = Phone.CONTENT_URI; final Uri myUri = Phone.CONTENT_URI; Cursor phoneCursor = null; try { phoneCursor = mResolver.query(myUri, PHONES_PROJECTION, null, null, Loading Loading @@ -252,7 +271,7 @@ public class BluetoothPbapVcardManager { } String typeSelection = BluetoothPbapObexServer.createSelectionPara(type); Uri myUri = CallLog.Calls.CONTENT_URI; final Uri myUri = CallLog.Calls.CONTENT_URI; final String[] CALLLOG_PROJECTION = new String[] { CallLog.Calls._ID, // 0 }; Loading @@ -264,7 +283,7 @@ public class BluetoothPbapVcardManager { try { // Need test to see if order by _ID is ok here, or by date? callsCursor = mResolver.query(myUri, CALLLOG_PROJECTION, typeSelection, null, CallLog.Calls._ID); CALLLOG_SORT_ORDER); if (callsCursor != null) { callsCursor.moveToPosition(startPoint - 1); startPointId = callsCursor.getLong(ID_COLUMN_INDEX); Loading @@ -287,8 +306,10 @@ public class BluetoothPbapVcardManager { if (startPoint == endPoint) { recordSelection = Calls._ID + "=" + startPointId; } else { recordSelection = Calls._ID + ">=" + startPointId + " AND " + Calls._ID + "<=" + endPointId; // The query to call table is by "_id DESC" order, so change // correspondingly. recordSelection = Calls._ID + ">=" + endPointId + " AND " + Calls._ID + "<=" + startPointId; } String selection; Loading @@ -309,27 +330,23 @@ public class BluetoothPbapVcardManager { Log.e(TAG, "internal error: startPoint or endPoint is not correct."); return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; } Uri myUri = RawContacts.CONTENT_URI; final String[] RAW_CONTACTS_PROJECTION = new String[] { RawContacts._ID, // 0 }; final int ID_COLUMN_INDEX = 0; final Uri myUri = Contacts.CONTENT_URI; Cursor contactCursor = null; long startPointId = 0; long endPointId = 0; try { contactCursor = mResolver.query(myUri, RAW_CONTACTS_PROJECTION, null, null, RawContacts._ID); contactCursor = mResolver.query(myUri, CONTACTS_PROJECTION, null, null, Contacts._ID); if (contactCursor != null) { contactCursor.moveToPosition(startPoint - 1); startPointId = contactCursor.getLong(ID_COLUMN_INDEX); startPointId = contactCursor.getLong(CONTACTS_ID_COLUMN_INDEX); if (V) Log.v(TAG, "Query startPointId = " + startPointId); if (startPoint == endPoint) { endPointId = startPointId; } else { contactCursor.moveToPosition(endPoint - 1); endPointId = contactCursor.getLong(ID_COLUMN_INDEX); endPointId = contactCursor.getLong(CONTACTS_ID_COLUMN_INDEX); } if (V) Log.v(TAG, "Query endPointId = " + endPointId); } Loading @@ -339,11 +356,11 @@ public class BluetoothPbapVcardManager { } } String selection; final String selection; if (startPoint == endPoint) { selection = RawContacts._ID + "=" + startPointId; selection = Contacts._ID + "=" + startPointId; } else { selection = RawContacts._ID + ">=" + startPointId + " AND " + RawContacts._ID + "<=" selection = Contacts._ID + ">=" + startPointId + " AND " + Contacts._ID + "<=" + endPointId; } Loading @@ -352,6 +369,55 @@ public class BluetoothPbapVcardManager { return composeAndSendVCards(op, selection, vcardType21, ownerVCard, true); } public final int composeAndSendPhonebookOneVcard(final Operation op, final int offset, final boolean vcardType21, String ownerVCard, int orderByWhat) { if (offset < 1) { Log.e(TAG, "Internal error: offset is not correct."); return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; } final Uri myUri = Contacts.CONTENT_URI; Cursor contactCursor = null; String selection = null; long contactId = 0; if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_INDEXED) { try { contactCursor = mResolver.query(myUri, CONTACTS_PROJECTION, null, null, Contacts._ID); if (contactCursor != null) { contactCursor.moveToPosition(offset - 1); contactId = contactCursor.getLong(CONTACTS_ID_COLUMN_INDEX); if (V) Log.v(TAG, "Query startPointId = " + contactId); } } finally { if (contactCursor != null) { contactCursor.close(); } } } else if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) { try { contactCursor = mResolver.query(myUri, CONTACTS_PROJECTION, null, null, Contacts.DISPLAY_NAME); if (contactCursor != null) { contactCursor.moveToPosition(offset - 1); contactId = contactCursor.getLong(CONTACTS_ID_COLUMN_INDEX); if (V) Log.v(TAG, "Query startPointId = " + contactId); } } finally { if (contactCursor != null) { contactCursor.close(); } } } else { Log.e(TAG, "Parameter orderByWhat is not supported!"); return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; } selection = Contacts._ID + "=" + contactId; if (V) Log.v(TAG, "Query selection is: " + selection); return composeAndSendVCards(op, selection, vcardType21, ownerVCard, true); } public final int composeAndSendVCards(final Operation op, final String selection, final boolean vcardType21, String ownerVCard, boolean isContacts) { long timestamp = 0; Loading Loading
android/app/res/values/strings_pbap.xml +1 −0 Original line number Diff line number Diff line Loading @@ -24,5 +24,6 @@ <string name="alwaysallowed">Always allowed?</string> <string name="defaultname">Carkit</string> <string name="unknownName">Unknown name</string> <string name="ownNumber">My phone number</string> <string name="defaultnumber">000000</string> </resources>
android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java +55 −15 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.os.Handler; import android.text.TextUtils; import android.util.Log; import android.provider.CallLog.Calls; import android.provider.ContactsContract.Contacts; import android.provider.CallLog; import java.io.IOException; Loading Loading @@ -144,6 +145,12 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { private BluetoothPbapVcardManager mVcardManager; private int mOrderBy = ORDER_BY_INDEXED; public static int ORDER_BY_INDEXED = 0; public static int ORDER_BY_ALPHABETICAL = 1; public static class ContentType { public static final int PHONEBOOK = 1; Loading Loading @@ -330,16 +337,16 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { if (D) Log.d(TAG, "Guess what carkit actually want from current path (" + mCurrentPath + ")"); if (mCurrentPath.compareTo(PB_PATH) == 0) { if (mCurrentPath.equals(PB_PATH)) { appParamValue.needTag = ContentType.PHONEBOOK; } else if (mCurrentPath.compareTo(ICH_PATH) == 0) { } else if (mCurrentPath.equals(ICH_PATH)) { appParamValue.needTag = ContentType.INCOMING_CALL_HISTORY; } else if (mCurrentPath.compareTo(OCH_PATH) == 0) { } else if (mCurrentPath.equals(OCH_PATH)) { appParamValue.needTag = ContentType.OUTGOING_CALL_HISTORY; } else if (mCurrentPath.compareTo(MCH_PATH) == 0) { } else if (mCurrentPath.equals(MCH_PATH)) { appParamValue.needTag = ContentType.MISSED_CALL_HISTORY; mNeedNewMissedCallsNum = true; } else if (mCurrentPath.compareTo(CCH_PATH) == 0) { } else if (mCurrentPath.equals(CCH_PATH)) { appParamValue.needTag = ContentType.COMBINED_CALL_HISTORY; } else { Log.w(TAG, "mCurrentpath is not valid path!!!"); Loading Loading @@ -419,8 +426,16 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { public String searchValue; // Indicate which vCard parameter the search operation shall be carried // out on. Can be "Name | Number | Sound", default value is "Name". public String searchAttr; // Indicate which sorting order shall be used for the // <x-bt/vcard-listing> listing object. // Can be "Alphabetical | Indexed | Phonetical", default value is // "Indexed". public String order; public int needTag; public boolean vcard21; Loading @@ -430,6 +445,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { listStartOffset = 0; searchValue = ""; searchAttr = ""; order = ""; needTag = 0x00; vcard21 = true; } Loading @@ -437,7 +453,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { public void dump() { Log.i(TAG, "maxListCount=" + maxListCount + " listStartOffset=" + listStartOffset + " searchValue=" + searchValue + " searchAttr=" + searchAttr + " needTag=" + needTag + " vcard21=" + vcard21); + needTag + " vcard21=" + vcard21 + " order=" + order); } } Loading @@ -453,8 +469,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { i += ApplicationParameter.TRIPLET_LENGTH.FILTER_LENGTH; break; case ApplicationParameter.TRIPLET_TAGID.ORDER_TAGID: // TODO capture this field to use i += 2; // length and tag field in triplet appParamValue.order = Byte.toString(appParam[i]); i += ApplicationParameter.TRIPLET_LENGTH.ORDER_LENGTH; break; case ApplicationParameter.TRIPLET_TAGID.SEARCH_VALUE_TAGID: Loading Loading @@ -491,7 +507,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { break; case ApplicationParameter.TRIPLET_TAGID.FORMAT_TAGID: i += 2;// length field in triplet if (Byte.toString(appParam[i]).compareTo("0") != 0) { if (appParam[i] != 0) { appParamValue.vcard21 = false; } i += ApplicationParameter.TRIPLET_LENGTH.FORMAT_LENGTH; Loading Loading @@ -521,8 +537,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { // Phonebook listing request if (type == ContentType.PHONEBOOK) { // begin of search by name if (searchAttr.compareTo("0") == 0) { ArrayList<String> nameList = mVcardManager.getPhonebookNameList(); if (searchAttr.equals("0")) { ArrayList<String> nameList = mVcardManager.getPhonebookNameList(mOrderBy ); int requestSize = nameList.size() >= maxListCount ? maxListCount : nameList.size(); int startPoint = listStartOffset; int endPoint = startPoint + requestSize; Loading Loading @@ -555,7 +571,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { } }// end of search by name // begin of search by number else if (searchAttr.compareTo("1") == 0) { else if (searchAttr.equals("1")) { ArrayList<String> numberList = mVcardManager.getPhonebookNumberList(); int requestSize = numberList.size() >= maxListCount ? maxListCount : numberList .size(); Loading Loading @@ -770,9 +786,9 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { // If searchAttr is not set by PCE, set default value per spec. appParamValue.searchAttr = "0"; if (D) Log.d(TAG, "searchAttr is not set by PCE, assume search by name by default"); } else if (searchAttr.compareTo("0") != 0 && searchAttr.compareTo("1") != 0) { } else if (!searchAttr.equals("0") && !searchAttr.equals("1")) { Log.w(TAG, "search attr not supported"); if (searchAttr.compareTo("2") == 0) { if (searchAttr.equals("2")) { // search by sound is not supported currently Log.w(TAG, "do not support search by sound"); return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED; Loading @@ -793,6 +809,30 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { return ResponseCodes.OBEX_HTTP_OK; } String orderPara = appParamValue.order.trim(); if (TextUtils.isEmpty(orderPara)) { // If order parameter is not set by PCE, set default value per spec. appParamValue.order = "0"; if (D) Log.d(TAG, "Order parameter is not set by PCE. " + "Assume order by 'Indexed' by default"); } else if (!orderPara.equals("0") && !orderPara.equals("1")) { if (V) Log.v(TAG, "Order parameter is not supported: " + appParamValue.order); if (orderPara.equals("2")) { // Order by sound is not supported currently Log.w(TAG, "Do not support order by sound"); return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED; } return ResponseCodes.OBEX_HTTP_PRECON_FAILED; } else { Log.i(TAG, "Order parameter is valid: " + orderPara); } if (orderPara.equals("0")) { mOrderBy = ORDER_BY_INDEXED; } else if (orderPara.equals("1")) { mOrderBy = ORDER_BY_ALPHABETICAL; } int sendResult = sendVcardListingXml(appParamValue.needTag, op, appParamValue.maxListCount, appParamValue.listStartOffset, appParamValue.searchValue, appParamValue.searchAttr); Loading Loading @@ -835,8 +875,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { String ownerVcard = mVcardManager.getOwnerPhoneNumberVcard(vcard21); return pushBytes(op, ownerVcard); } else { return mVcardManager.composeAndSendPhonebookVcards(op, intIndex, intIndex, vcard21, null); return mVcardManager.composeAndSendPhonebookOneVcard(op, intIndex, vcard21, null, mOrderBy ); } } else { if (intIndex <= 0 || intIndex > size) { Loading
android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java +1 −1 Original line number Diff line number Diff line Loading @@ -427,7 +427,7 @@ public class BluetoothPbapService extends Service { } sLocalPhoneName = tm.getLine1AlphaTag(); if (TextUtils.isEmpty(sLocalPhoneName)) { sLocalPhoneName = this.getString(R.string.unknownName); sLocalPhoneName = this.getString(R.string.ownNumber); } } Loading
android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java +98 −32 Original line number Diff line number Diff line Loading @@ -90,10 +90,23 @@ public class BluetoothPbapVcardManager { private static final int CONTACTS_DISPLAY_NAME_COLUMN_INDEX = 4; static final String SORT_ORDER_NAME = Contacts.DISPLAY_NAME + " ASC"; static final String SORT_ORDER_PHONE_NUMBER = CommonDataKinds.Phone.NUMBER + " ASC"; static final String[] CONTACTS_PROJECTION = new String[] { Contacts._ID, // 0 Contacts.DISPLAY_NAME, // 1 }; static final int CONTACTS_ID_COLUMN_INDEX = 0; static final int CONTACTS_NAME_COLUMN_INDEX = 1; // call histories use dynamic handles, and handles should order by date; the // most recently one should be the first handle. In table "calls", _id and // date are consistent in ordering, to implement simply, we sort by _id // here. static final String CALLLOG_SORT_ORDER = Calls._ID + " DESC"; public BluetoothPbapVcardManager(final Context context) { mContext = context; mResolver = mContext.getContentResolver(); Loading Loading @@ -123,7 +136,7 @@ public class BluetoothPbapVcardManager { } public final int getContactsSize() { Uri myUri = RawContacts.CONTENT_URI; final Uri myUri = Contacts.CONTENT_URI; int size = 0; Cursor contactCursor = null; try { Loading @@ -140,7 +153,7 @@ public class BluetoothPbapVcardManager { } public final int getCallHistorySize(final int type) { Uri myUri = CallLog.Calls.CONTENT_URI; final Uri myUri = CallLog.Calls.CONTENT_URI; String selection = BluetoothPbapObexServer.createSelectionPara(type); int size = 0; Cursor callCursor = null; Loading @@ -159,7 +172,7 @@ public class BluetoothPbapVcardManager { } public final ArrayList<String> loadCallHistoryList(final int type) { Uri myUri = CallLog.Calls.CONTENT_URI; final Uri myUri = CallLog.Calls.CONTENT_URI; String selection = BluetoothPbapObexServer.createSelectionPara(type); String[] projection = new String[] { Calls.NUMBER, Calls.CACHED_NAME Loading @@ -171,7 +184,7 @@ public class BluetoothPbapVcardManager { ArrayList<String> list = new ArrayList<String>(); try { callCursor = mResolver.query(myUri, projection, selection, null, CallLog.Calls.DEFAULT_SORT_ORDER); CALLLOG_SORT_ORDER); if (callCursor != null) { for (callCursor.moveToFirst(); !callCursor.isAfterLast(); callCursor.moveToNext()) { Loading @@ -191,18 +204,24 @@ public class BluetoothPbapVcardManager { return list; } public final ArrayList<String> getPhonebookNameList() { public final ArrayList<String> getPhonebookNameList(final int orderByWhat) { ArrayList<String> nameList = new ArrayList<String>(); nameList.add(BluetoothPbapService.getLocalPhoneName()); Uri myUri = Phone.CONTENT_URI; Cursor phoneCursor = null; final Uri myUri = Contacts.CONTENT_URI; Cursor contactCursor = null; try { phoneCursor = mResolver.query(myUri, PHONES_PROJECTION, null, null, SORT_ORDER_NAME); if (phoneCursor != null) { for (phoneCursor.moveToFirst(); !phoneCursor.isAfterLast(); phoneCursor if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_INDEXED) { contactCursor = mResolver.query(myUri, CONTACTS_PROJECTION, null, null, Contacts._ID); } else if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) { contactCursor = mResolver.query(myUri, CONTACTS_PROJECTION, null, null, Contacts.DISPLAY_NAME); } if (contactCursor != null) { for (contactCursor.moveToFirst(); !contactCursor.isAfterLast(); contactCursor .moveToNext()) { String name = phoneCursor.getString(CONTACTS_DISPLAY_NAME_COLUMN_INDEX); String name = contactCursor.getString(CONTACTS_NAME_COLUMN_INDEX); if (TextUtils.isEmpty(name)) { name = mContext.getString(android.R.string.unknownName); } Loading @@ -210,8 +229,8 @@ public class BluetoothPbapVcardManager { } } } finally { if (phoneCursor != null) { phoneCursor.close(); if (contactCursor != null) { contactCursor.close(); } } return nameList; Loading @@ -221,7 +240,7 @@ public class BluetoothPbapVcardManager { ArrayList<String> numberList = new ArrayList<String>(); numberList.add(BluetoothPbapService.getLocalPhoneNum()); Uri myUri = Phone.CONTENT_URI; final Uri myUri = Phone.CONTENT_URI; Cursor phoneCursor = null; try { phoneCursor = mResolver.query(myUri, PHONES_PROJECTION, null, null, Loading Loading @@ -252,7 +271,7 @@ public class BluetoothPbapVcardManager { } String typeSelection = BluetoothPbapObexServer.createSelectionPara(type); Uri myUri = CallLog.Calls.CONTENT_URI; final Uri myUri = CallLog.Calls.CONTENT_URI; final String[] CALLLOG_PROJECTION = new String[] { CallLog.Calls._ID, // 0 }; Loading @@ -264,7 +283,7 @@ public class BluetoothPbapVcardManager { try { // Need test to see if order by _ID is ok here, or by date? callsCursor = mResolver.query(myUri, CALLLOG_PROJECTION, typeSelection, null, CallLog.Calls._ID); CALLLOG_SORT_ORDER); if (callsCursor != null) { callsCursor.moveToPosition(startPoint - 1); startPointId = callsCursor.getLong(ID_COLUMN_INDEX); Loading @@ -287,8 +306,10 @@ public class BluetoothPbapVcardManager { if (startPoint == endPoint) { recordSelection = Calls._ID + "=" + startPointId; } else { recordSelection = Calls._ID + ">=" + startPointId + " AND " + Calls._ID + "<=" + endPointId; // The query to call table is by "_id DESC" order, so change // correspondingly. recordSelection = Calls._ID + ">=" + endPointId + " AND " + Calls._ID + "<=" + startPointId; } String selection; Loading @@ -309,27 +330,23 @@ public class BluetoothPbapVcardManager { Log.e(TAG, "internal error: startPoint or endPoint is not correct."); return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; } Uri myUri = RawContacts.CONTENT_URI; final String[] RAW_CONTACTS_PROJECTION = new String[] { RawContacts._ID, // 0 }; final int ID_COLUMN_INDEX = 0; final Uri myUri = Contacts.CONTENT_URI; Cursor contactCursor = null; long startPointId = 0; long endPointId = 0; try { contactCursor = mResolver.query(myUri, RAW_CONTACTS_PROJECTION, null, null, RawContacts._ID); contactCursor = mResolver.query(myUri, CONTACTS_PROJECTION, null, null, Contacts._ID); if (contactCursor != null) { contactCursor.moveToPosition(startPoint - 1); startPointId = contactCursor.getLong(ID_COLUMN_INDEX); startPointId = contactCursor.getLong(CONTACTS_ID_COLUMN_INDEX); if (V) Log.v(TAG, "Query startPointId = " + startPointId); if (startPoint == endPoint) { endPointId = startPointId; } else { contactCursor.moveToPosition(endPoint - 1); endPointId = contactCursor.getLong(ID_COLUMN_INDEX); endPointId = contactCursor.getLong(CONTACTS_ID_COLUMN_INDEX); } if (V) Log.v(TAG, "Query endPointId = " + endPointId); } Loading @@ -339,11 +356,11 @@ public class BluetoothPbapVcardManager { } } String selection; final String selection; if (startPoint == endPoint) { selection = RawContacts._ID + "=" + startPointId; selection = Contacts._ID + "=" + startPointId; } else { selection = RawContacts._ID + ">=" + startPointId + " AND " + RawContacts._ID + "<=" selection = Contacts._ID + ">=" + startPointId + " AND " + Contacts._ID + "<=" + endPointId; } Loading @@ -352,6 +369,55 @@ public class BluetoothPbapVcardManager { return composeAndSendVCards(op, selection, vcardType21, ownerVCard, true); } public final int composeAndSendPhonebookOneVcard(final Operation op, final int offset, final boolean vcardType21, String ownerVCard, int orderByWhat) { if (offset < 1) { Log.e(TAG, "Internal error: offset is not correct."); return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; } final Uri myUri = Contacts.CONTENT_URI; Cursor contactCursor = null; String selection = null; long contactId = 0; if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_INDEXED) { try { contactCursor = mResolver.query(myUri, CONTACTS_PROJECTION, null, null, Contacts._ID); if (contactCursor != null) { contactCursor.moveToPosition(offset - 1); contactId = contactCursor.getLong(CONTACTS_ID_COLUMN_INDEX); if (V) Log.v(TAG, "Query startPointId = " + contactId); } } finally { if (contactCursor != null) { contactCursor.close(); } } } else if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) { try { contactCursor = mResolver.query(myUri, CONTACTS_PROJECTION, null, null, Contacts.DISPLAY_NAME); if (contactCursor != null) { contactCursor.moveToPosition(offset - 1); contactId = contactCursor.getLong(CONTACTS_ID_COLUMN_INDEX); if (V) Log.v(TAG, "Query startPointId = " + contactId); } } finally { if (contactCursor != null) { contactCursor.close(); } } } else { Log.e(TAG, "Parameter orderByWhat is not supported!"); return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; } selection = Contacts._ID + "=" + contactId; if (V) Log.v(TAG, "Query selection is: " + selection); return composeAndSendVCards(op, selection, vcardType21, ownerVCard, true); } public final int composeAndSendVCards(final Operation op, final String selection, final boolean vcardType21, String ownerVCard, boolean isContacts) { long timestamp = 0; Loading