diff options
100 files changed, 2390 insertions, 1682 deletions
diff --git a/android/app/Android.bp b/android/app/Android.bp index b7cfc48c5b..5af8cfd487 100644 --- a/android/app/Android.bp +++ b/android/app/Android.bp @@ -33,7 +33,7 @@ java_library { srcs: ["lib/mapapi/**/*.java"], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "Tiramisu", sdk_version: "module_current", @@ -45,7 +45,7 @@ java_library { srcs: [":framework-mms-shared-srcs"], libs: ["unsupportedappusage"], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "Tiramisu", sdk_version: "module_current", @@ -79,7 +79,7 @@ cc_library_shared { scs: true, }, apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "Tiramisu", } @@ -155,7 +155,7 @@ android_app { "android.hardware.bluetooth.audio-V2-ndk", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], errorprone: { javacflags: [ @@ -176,7 +176,7 @@ java_library { ":srcs_bluetooth_protos", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "Tiramisu", sdk_version: "module_current", diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java index cc8e361b81..76f1c3f004 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -159,20 +159,20 @@ public class LeAudioService extends ProfileService { private final Map<BluetoothDevice, Integer> mDeviceGroupIdMap = new ConcurrentHashMap<>(); private final Map<BluetoothDevice, Integer> mDeviceAudioLocationMap = new ConcurrentHashMap<>(); - private final int mContextSupportingInputAudio = - BluetoothLeAudio.CONTEXT_TYPE_COMMUNICATION | BluetoothLeAudio.CONTEXT_TYPE_MAN_MACHINE; - - private final int mContextSupportingOutputAudio = BluetoothLeAudio.CONTEXT_TYPE_COMMUNICATION | - BluetoothLeAudio.CONTEXT_TYPE_MEDIA | - BluetoothLeAudio.CONTEXT_TYPE_INSTRUCTIONAL | - BluetoothLeAudio.CONTEXT_TYPE_ATTENTION_SEEKING | - BluetoothLeAudio.CONTEXT_TYPE_IMMEDIATE_ALERT | - BluetoothLeAudio.CONTEXT_TYPE_MAN_MACHINE | - BluetoothLeAudio.CONTEXT_TYPE_EMERGENCY_ALERT | - BluetoothLeAudio.CONTEXT_TYPE_RINGTONE | - BluetoothLeAudio.CONTEXT_TYPE_TV | - BluetoothLeAudio.CONTEXT_TYPE_LIVE | - BluetoothLeAudio.CONTEXT_TYPE_GAME; + private final int mContextSupportingInputAudio = BluetoothLeAudio.CONTEXT_TYPE_CONVERSATIONAL + | BluetoothLeAudio.CONTEXT_TYPE_VOICE_ASSISTANTS; + + private final int mContextSupportingOutputAudio = BluetoothLeAudio.CONTEXT_TYPE_CONVERSATIONAL + | BluetoothLeAudio.CONTEXT_TYPE_MEDIA + | BluetoothLeAudio.CONTEXT_TYPE_GAME + | BluetoothLeAudio.CONTEXT_TYPE_INSTRUCTIONAL + | BluetoothLeAudio.CONTEXT_TYPE_VOICE_ASSISTANTS + | BluetoothLeAudio.CONTEXT_TYPE_LIVE + | BluetoothLeAudio.CONTEXT_TYPE_SOUND_EFFECTS + | BluetoothLeAudio.CONTEXT_TYPE_NOTIFICATIONS + | BluetoothLeAudio.CONTEXT_TYPE_RINGTONE + | BluetoothLeAudio.CONTEXT_TYPE_ALERTS + | BluetoothLeAudio.CONTEXT_TYPE_EMERGENCY_ALARM; private BroadcastReceiver mBondStateChangedReceiver; private BroadcastReceiver mConnectionStateChangedReceiver; @@ -1845,6 +1845,11 @@ public class LeAudioService extends ProfileService { } private void handleGroupNodeRemoved(BluetoothDevice device, int groupId) { + LeAudioGroupDescriptor descriptor = getGroupDescriptor(groupId); + if (Objects.equals(device, descriptor.mLostLeadDeviceWhileStreaming)) { + clearLostDevicesWhileStreaming(descriptor); + } + synchronized (mGroupLock) { mDeviceGroupIdMap.remove(device); if (!mDeviceGroupIdMap.containsValue(groupId)) { diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapContent.java b/android/app/src/com/android/bluetooth/map/BluetoothMapContent.java index afa59bd76a..12e950b9dc 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapContent.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapContent.java @@ -19,7 +19,6 @@ import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; import android.net.Uri; -import android.net.Uri.Builder; import android.os.ParcelFileDescriptor; import android.provider.BaseColumns; import android.provider.ContactsContract; @@ -54,7 +53,6 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -83,13 +81,13 @@ public class BluetoothMapContent { private static final int MASK_READ = 0x00001000; private static final int MASK_SENT = 0x00002000; private static final int MASK_PROTECTED = 0x00004000; - private static final int MASK_REPLYTO_ADDRESSING = 0x00008000; + // private static final int MASK_REPLYTO_ADDRESSING = 0x00008000; // TODO: Duplicate in proposed spec // private static final int MASK_RECEPTION_STATE = 0x00010000; private static final int MASK_DELIVERY_STATUS = 0x00010000; private static final int MASK_CONVERSATION_ID = 0x00020000; private static final int MASK_CONVERSATION_NAME = 0x00040000; - private static final int MASK_FOLDER_TYPE = 0x00100000; + // private static final int MASK_FOLDER_TYPE = 0x00100000; // TODO: about to be removed from proposed spec // private static final int MASK_SEQUENCE_NUMBER = 0x00200000; private static final int MASK_ATTACHMENT_MIME = 0x00100000; @@ -122,7 +120,7 @@ public class BluetoothMapContent { private static final int FILTER_READ_STATUS_UNREAD_ONLY = 0x01; private static final int FILTER_READ_STATUS_READ_ONLY = 0x02; - private static final int FILTER_READ_STATUS_ALL = 0x00; + // private static final int FILTER_READ_STATUS_ALL = 0x00; /* Type of MMS address. From Telephony.java it must be one of PduHeaders.BCC, */ /* PduHeaders.CC, PduHeaders.FROM, PduHeaders.TO. These are from PduHeaders.java */ @@ -251,7 +249,7 @@ public class BluetoothMapContent { MMS_SMS_THREAD_COL_RECIPIENT_IDS = projection.indexOf(Threads.RECIPIENT_IDS); } - private class FilterInfo { + private static class FilterInfo { public static final int TYPE_SMS = 0; public static final int TYPE_MMS = 1; public static final int TYPE_EMAIL = 2; @@ -446,6 +444,7 @@ public class BluetoothMapContent { c.close(); } } catch (IOException e) { + Log.w(TAG, e); } } @@ -544,19 +543,6 @@ public class BluetoothMapContent { e.setRead((read == 1), ((ap.getParameterMask() & MASK_READ) != 0)); } - private void setConvoRead(BluetoothMapConvoListingElement e, Cursor c, FilterInfo fi, - BluetoothMapAppParams ap) { - String setread = null; - int read = 0; - read = c.getInt(fi.mConvoColRead); - - - if (V) { - Log.d(TAG, "setRead: " + setread); - } - e.setRead((read == 1), ((ap.getParameterMask() & MASK_READ) != 0)); - } - private void setPriority(BluetoothMapMessageListingElement e, Cursor c, FilterInfo fi, BluetoothMapAppParams ap) { if ((ap.getParameterMask() & MASK_PRIORITY) != 0) { @@ -672,8 +658,7 @@ public class BluetoothMapContent { } } - private void setReceptionStatus(BluetoothMapMessageListingElement e, Cursor c, FilterInfo fi, - BluetoothMapAppParams ap) { + private void setReceptionStatus(BluetoothMapMessageListingElement e, BluetoothMapAppParams ap) { if ((ap.getParameterMask() & MASK_RECEPTION_STATUS) != 0) { String status = "complete"; if (V) { @@ -736,7 +721,7 @@ public class BluetoothMapContent { } } - private TYPE getType(Cursor c, FilterInfo fi) { + private TYPE getType(FilterInfo fi) { TYPE type = null; if (V) { Log.d(TAG, "getType: for filterMsgType" + fi.mMsgType); @@ -764,64 +749,7 @@ public class BluetoothMapContent { return type; } - private void setFolderType(BluetoothMapMessageListingElement e, Cursor c, FilterInfo fi, - BluetoothMapAppParams ap) { - if ((ap.getParameterMask() & MASK_FOLDER_TYPE) != 0) { - String folderType = null; - int folderId = 0; - if (fi.mMsgType == FilterInfo.TYPE_SMS) { - folderId = c.getInt(fi.mSmsColFolder); - if (folderId == 1) { - folderType = BluetoothMapContract.FOLDER_NAME_INBOX; - } else if (folderId == 2) { - folderType = BluetoothMapContract.FOLDER_NAME_SENT; - } else if (folderId == 3) { - folderType = BluetoothMapContract.FOLDER_NAME_DRAFT; - } else if (folderId == 4 || folderId == 5 || folderId == 6) { - folderType = BluetoothMapContract.FOLDER_NAME_OUTBOX; - } else { - folderType = BluetoothMapContract.FOLDER_NAME_DELETED; - } - } else if (fi.mMsgType == FilterInfo.TYPE_MMS) { - folderId = c.getInt(fi.mMmsColFolder); - if (folderId == 1) { - folderType = BluetoothMapContract.FOLDER_NAME_INBOX; - } else if (folderId == 2) { - folderType = BluetoothMapContract.FOLDER_NAME_SENT; - } else if (folderId == 3) { - folderType = BluetoothMapContract.FOLDER_NAME_DRAFT; - } else if (folderId == 4) { - folderType = BluetoothMapContract.FOLDER_NAME_OUTBOX; - } else { - folderType = BluetoothMapContract.FOLDER_NAME_DELETED; - } - } else if (fi.mMsgType == FilterInfo.TYPE_EMAIL) { - // TODO: need to find name from id and then set folder type - } else if (fi.mMsgType == FilterInfo.TYPE_IM) { - folderId = c.getInt(fi.mMessageColFolder); - if (folderId == BluetoothMapContract.FOLDER_ID_INBOX) { - folderType = BluetoothMapContract.FOLDER_NAME_INBOX; - } else if (folderId == BluetoothMapContract.FOLDER_ID_SENT) { - folderType = BluetoothMapContract.FOLDER_NAME_SENT; - } else if (folderId == BluetoothMapContract.FOLDER_ID_DRAFT) { - folderType = BluetoothMapContract.FOLDER_NAME_DRAFT; - } else if (folderId == BluetoothMapContract.FOLDER_ID_OUTBOX) { - folderType = BluetoothMapContract.FOLDER_NAME_OUTBOX; - } else if (folderId == BluetoothMapContract.FOLDER_ID_DELETED) { - folderType = BluetoothMapContract.FOLDER_NAME_DELETED; - } else { - folderType = BluetoothMapContract.FOLDER_NAME_OTHER; - } - } - if (V) { - Log.d(TAG, "setFolderType: " + folderType); - } - e.setFolderType(folderType); - } - } - - private String getRecipientNameEmail(BluetoothMapMessageListingElement e, Cursor c, - FilterInfo fi) { + private String getRecipientNameEmail(Cursor c, FilterInfo fi) { String toAddress, ccAddress, bccAddress; toAddress = c.getString(fi.mMessageColToAddress); @@ -905,8 +833,7 @@ public class BluetoothMapContent { return sb.toString(); } - private String getRecipientAddressingEmail(BluetoothMapMessageListingElement e, Cursor c, - FilterInfo fi) { + private String getRecipientAddressingEmail(Cursor c, FilterInfo fi) { String toAddress, ccAddress, bccAddress; toAddress = c.getString(fi.mMessageColToAddress); ccAddress = c.getString(fi.mMessageColCcAddress); @@ -1018,7 +945,7 @@ public class BluetoothMapContent { address = getAddressMms(mResolver, id, MMS_TO); } else if (fi.mMsgType == FilterInfo.TYPE_EMAIL) { /* Might be another way to handle addresses */ - address = getRecipientAddressingEmail(e, c, fi); + address = getRecipientAddressingEmail(c, fi); } if (V) { Log.v(TAG, "setRecipientAddressing: " + address); @@ -1057,7 +984,7 @@ public class BluetoothMapContent { } } else if (fi.mMsgType == FilterInfo.TYPE_EMAIL) { /* Might be another way to handle address and names */ - name = getRecipientNameEmail(e, c, fi); + name = getRecipientNameEmail(c, fi); } if (V) { Log.v(TAG, "setRecipientName: " + name); @@ -1121,7 +1048,6 @@ public class BluetoothMapContent { } String[] emails = new String[1]; emails[0] = tokens[i].getAddress(); - String name = tokens[i].getName(); if (!first) { address += "; "; //Delimiter } @@ -1269,8 +1195,7 @@ public class BluetoothMapContent { } - private void setLastActivity(BluetoothMapConvoListingElement e, Cursor c, FilterInfo fi, - BluetoothMapAppParams ap) { + private void setLastActivity(BluetoothMapConvoListingElement e, Cursor c, FilterInfo fi) { long date = 0; if (fi.mMsgType == FilterInfo.TYPE_SMS || fi.mMsgType == FilterInfo.TYPE_MMS) { date = c.getLong(MMS_SMS_THREAD_COL_DATE); @@ -1348,8 +1273,7 @@ public class BluetoothMapContent { } } - private void setHandle(BluetoothMapMessageListingElement e, Cursor c, FilterInfo fi, - BluetoothMapAppParams ap) { + private void setHandle(BluetoothMapMessageListingElement e, Cursor c, FilterInfo fi) { long handle = -1; if (fi.mMsgType == FilterInfo.TYPE_SMS) { handle = c.getLong(fi.mSmsColId); @@ -1367,9 +1291,9 @@ public class BluetoothMapContent { private BluetoothMapMessageListingElement element(Cursor c, FilterInfo fi, BluetoothMapAppParams ap) { BluetoothMapMessageListingElement e = new BluetoothMapMessageListingElement(); - setHandle(e, c, fi, ap); + setHandle(e, c, fi); setDateTime(e, c, fi, ap); - e.setType(getType(c, fi), (ap.getParameterMask() & MASK_TYPE) != 0); + e.setType(getType(fi), (ap.getParameterMask() & MASK_TYPE) != 0); setRead(e, c, fi, ap); // we set number and name for sender/recipient later // they require lookup on contacts so no need to @@ -1378,12 +1302,10 @@ public class BluetoothMapContent { return e; } - private BluetoothMapConvoListingElement createConvoElement(Cursor c, FilterInfo fi, - BluetoothMapAppParams ap) { + private BluetoothMapConvoListingElement createConvoElement(Cursor c, FilterInfo fi) { BluetoothMapConvoListingElement e = new BluetoothMapConvoListingElement(); - setLastActivity(e, c, fi, ap); - e.setType(getType(c, fi)); -// setConvoRead(e, c, fi, ap); + setLastActivity(e, c, fi); + e.setType(getType(fi)); e.setCursorIndex(c.getPosition()); return e; } @@ -1466,9 +1388,8 @@ public class BluetoothMapContent { Log.v(TAG, "recipientIds with spaces: " + recipientIds + "\n"); } if (recipientIds != null) { - String[] recipients = null; + String[] recipients = recipientIds.split(" "); whereClause = ""; - recipients = recipientIds.split(" "); for (String id : recipients) { if (whereClause.length() != 0) { whereClause += " OR "; @@ -1533,7 +1454,7 @@ public class BluetoothMapContent { * Matching functions for originator and recipient for MMS * @return true if found a match */ - private boolean matchRecipientMms(Cursor c, FilterInfo fi, String recip) { + private boolean matchRecipientMms(Cursor c, String recip) { boolean res; long id = c.getLong(c.getColumnIndex(BaseColumns._ID)); String phone = getAddressMms(mResolver, id, MMS_TO); @@ -1614,7 +1535,7 @@ public class BluetoothMapContent { if (fi.mMsgType == FilterInfo.TYPE_SMS) { res = matchRecipientSms(c, fi, recip); } else if (fi.mMsgType == FilterInfo.TYPE_MMS) { - res = matchRecipientMms(c, fi, recip); + res = matchRecipientMms(c, recip); } else { if (D) { Log.d(TAG, "matchRecipient: Unknown msg type: " + fi.mMsgType); @@ -1627,7 +1548,7 @@ public class BluetoothMapContent { return res; } - private boolean matchOriginatorMms(Cursor c, FilterInfo fi, String orig) { + private boolean matchOriginatorMms(Cursor c, String orig) { boolean res; long id = c.getLong(c.getColumnIndex(BaseColumns._ID)); String phone = getAddressMms(mResolver, id, MMS_FROM); @@ -1708,7 +1629,7 @@ public class BluetoothMapContent { if (fi.mMsgType == FilterInfo.TYPE_SMS) { res = matchOriginatorSms(c, fi, orig); } else if (fi.mMsgType == FilterInfo.TYPE_MMS) { - res = matchOriginatorMms(c, fi, orig); + res = matchOriginatorMms(c, orig); } else { if (D) { Log.d(TAG, "matchOriginator: Unknown msg type: " + fi.mMsgType); @@ -1727,7 +1648,7 @@ public class BluetoothMapContent { /* * Where filter functions - * */ + */ private String setWhereFilterFolderTypeSms(String folder) { String where = ""; if (BluetoothMapContract.FOLDER_NAME_INBOX.equalsIgnoreCase(folder)) { @@ -1863,32 +1784,6 @@ public class BluetoothMapContent { return where; } - private String setWhereFilterLastActivity(BluetoothMapAppParams ap, FilterInfo fi) { - String where = ""; - if ((ap.getFilterLastActivityBegin() != -1)) { - if (fi.mMsgType == FilterInfo.TYPE_SMS) { - where = " AND " + Sms.DATE + " >= " + ap.getFilterLastActivityBegin(); - } else if (fi.mMsgType == FilterInfo.TYPE_MMS) { - where = " AND " + Mms.DATE + " >= " + (ap.getFilterLastActivityBegin() / 1000L); - } else if (fi.mMsgType == FilterInfo.TYPE_EMAIL || fi.mMsgType == FilterInfo.TYPE_IM) { - where = " AND " + BluetoothMapContract.ConversationColumns.LAST_THREAD_ACTIVITY - + " >= " + (ap.getFilterPeriodBegin()); - } - } - if ((ap.getFilterLastActivityEnd() != -1)) { - if (fi.mMsgType == FilterInfo.TYPE_SMS) { - where += " AND " + Sms.DATE + " < " + ap.getFilterLastActivityEnd(); - } else if (fi.mMsgType == FilterInfo.TYPE_MMS) { - where += " AND " + Mms.DATE + " < " + (ap.getFilterPeriodEnd() / 1000L); - } else if (fi.mMsgType == FilterInfo.TYPE_EMAIL || fi.mMsgType == FilterInfo.TYPE_IM) { - where += " AND " + BluetoothMapContract.ConversationColumns.LAST_THREAD_ACTIVITY - + " < " + (ap.getFilterLastActivityEnd()); - } - } - return where; - } - - private String setWhereFilterOriginatorEmail(BluetoothMapAppParams ap) { String where = ""; String orig = ap.getFilterOriginator(); @@ -2027,8 +1922,8 @@ public class BluetoothMapContent { /* Used only for SMS/MMS */ - private void setConvoWhereFilterSmsMms(StringBuilder selection, ArrayList<String> selectionArgs, - FilterInfo fi, BluetoothMapAppParams ap) { + private void setConvoWhereFilterSmsMms(StringBuilder selection, FilterInfo fi, + BluetoothMapAppParams ap) { if (smsSelected(fi, ap) || mmsSelected(ap)) { @@ -2075,8 +1970,7 @@ public class BluetoothMapContent { /** * Determine from application parameter if sms should be included. * The filter mask is set for message types not selected - * @param fi - * @param ap + * * @return boolean true if sms is selected, false if not */ private boolean smsSelected(FilterInfo fi, BluetoothMapAppParams ap) { @@ -2112,8 +2006,7 @@ public class BluetoothMapContent { /** * Determine from application parameter if mms should be included. * The filter mask is set for message types not selected - * @param fi - * @param ap + * * @return boolean true if mms is selected, false if not */ private boolean mmsSelected(BluetoothMapAppParams ap) { @@ -2137,8 +2030,7 @@ public class BluetoothMapContent { /** * Determine from application parameter if email should be included. * The filter mask is set for message types not selected - * @param fi - * @param ap + * * @return boolean true if email is selected, false if not */ private boolean emailSelected(BluetoothMapAppParams ap) { @@ -2162,8 +2054,7 @@ public class BluetoothMapContent { /** * Determine from application parameter if IM should be included. * The filter mask is set for message types not selected - * @param fi - * @param ap + * * @return boolean true if im is selected, false if not */ private boolean imSelected(BluetoothMapAppParams ap) { @@ -2230,7 +2121,6 @@ public class BluetoothMapContent { Cursor emailCursor = null; Cursor imCursor = null; String limit = ""; - int countNum = ap.getMaxListCount(); int offsetNum = ap.getStartOffset(); if (ap.getMaxListCount() > 0) { limit = " LIMIT " + (ap.getMaxListCount() + ap.getStartOffset()); @@ -2351,7 +2241,6 @@ public class BluetoothMapContent { BluetoothMapMessageListingElement e = null; // store column index so we dont have to look them up anymore (optimization) fi.setEmailMessageColumns(emailCursor); - int cnt = 0; if (D) { Log.d(TAG, "Found " + emailCursor.getCount() + " email messages."); } @@ -2445,7 +2334,7 @@ public class BluetoothMapContent { setPriority(ele, tmpCursor, fi, ap); setSent(ele, tmpCursor, fi, ap); setProtected(ele, tmpCursor, fi, ap); - setReceptionStatus(ele, tmpCursor, fi, ap); + setReceptionStatus(ele, ap); setAttachment(ele, tmpCursor, fi, ap); if (mMsgListingVersion > BluetoothMapUtils.MAP_MESSAGE_LISTING_FORMAT_V10) { @@ -2677,9 +2566,9 @@ public class BluetoothMapContent { * Build the conversation listing. * @param ap The Application Parameters * @param sizeOnly TRUE: don't populate the list members, only build the list to get the size. - * @return + * @return the BluetoothMapConvoListing */ - public BluetoothMapConvoListing convoListing(BluetoothMapAppParams ap, boolean sizeOnly) { + BluetoothMapConvoListing convoListing(BluetoothMapAppParams ap, boolean sizeOnly) { if (D) { Log.d(TAG, "convoListing: " + " messageType = " + ap.getFilterMessageType()); @@ -2739,8 +2628,8 @@ public class BluetoothMapContent { limit = " LIMIT " + maxThreads; } StringBuilder sortOrder = new StringBuilder(Threads.DATE + " DESC"); - if ((!sizeOnly) && ((msgTypesInclude & ~(BluetoothMapAppParams.FILTER_NO_SMS_GSM - | BluetoothMapAppParams.FILTER_NO_SMS_CDMA) + if ((!sizeOnly) && (((msgTypesInclude & ~(BluetoothMapAppParams.FILTER_NO_SMS_GSM + | BluetoothMapAppParams.FILTER_NO_SMS_CDMA)) | BluetoothMapAppParams.FILTER_NO_MMS) == 0) && ap.getFilterRecipient() == null) { // SMS/MMS messages only and no recipient filter - use optimization. @@ -2751,14 +2640,8 @@ public class BluetoothMapContent { offsetNum = 0; } StringBuilder selection = new StringBuilder(120); // This covers most cases - ArrayList<String> selectionArgs = new ArrayList<String>(12); // Covers all cases selection.append("1=1 "); // just to simplify building the where-clause - setConvoWhereFilterSmsMms(selection, selectionArgs, fi, ap); - String[] args = null; - if (selectionArgs.size() > 0) { - args = new String[selectionArgs.size()]; - selectionArgs.toArray(args); - } + setConvoWhereFilterSmsMms(selection, fi, ap); Uri uri = Threads.CONTENT_URI.buildUpon() .appendQueryParameter("simple", "true") .build(); @@ -2769,7 +2652,7 @@ public class BluetoothMapContent { } // TODO: Optimize: Reduce projection based on convo parameter mask smsMmsCursor = - mResolver.query(uri, MMS_SMS_THREAD_PROJECTION, selection.toString(), args, + mResolver.query(uri, MMS_SMS_THREAD_PROJECTION, selection.toString(), null, sortOrder.toString()); if (smsMmsCursor != null) { // store column index so we don't have to look them up anymore (optimization) @@ -2782,7 +2665,7 @@ public class BluetoothMapContent { int count = 0; // We have no Recipient filter, add contacts after the list is reduced while (smsMmsCursor.moveToNext()) { - convoElement = createConvoElement(smsMmsCursor, fi, ap); + convoElement = createConvoElement(smsMmsCursor, fi); convoList.add(convoElement); count++; if (!sizeOnly && count >= maxThreads) { @@ -2794,7 +2677,7 @@ public class BluetoothMapContent { SmsMmsContacts contacts = new SmsMmsContacts(); while (smsMmsCursor.moveToNext()) { int count = 0; - convoElement = createConvoElement(smsMmsCursor, fi, ap); + convoElement = createConvoElement(smsMmsCursor, fi); String idsStr = smsMmsCursor.getString(MMS_SMS_THREAD_COL_RECIPIENT_IDS); // Add elements only if we do find a contact - if not we cannot apply @@ -2851,7 +2734,7 @@ public class BluetoothMapContent { long threadId = imEmailCursor.getLong(fi.mConvoColConvoId); long nextThreadId; count++; - e = createConvoElement(imEmailCursor, fi, ap); + e = createConvoElement(imEmailCursor, fi); convoList.add(e); do { @@ -2950,14 +2833,12 @@ public class BluetoothMapContent { /** * Refreshes the entire list of SMS/MMS conversation version counters. Use it to generate a * new ConvoListVersinoCounter in mSmsMmsConvoListVersion - * @return + * @return true if a list change has been detected */ - /* package */ boolean refreshSmsMmsConvoVersions() { boolean listChangeDetected = false; - Cursor cursor = null; Uri uri = Threads.CONTENT_URI.buildUpon().appendQueryParameter("simple", "true").build(); - cursor = + Cursor cursor = mResolver.query(uri, MMS_SMS_THREAD_PROJECTION, null, null, Threads.DATE + " DESC"); try { if (cursor != null) { @@ -3037,9 +2918,8 @@ public class BluetoothMapContent { /** * Refreshes the entire list of SMS/MMS conversation version counters. Use it to generate a * new ConvoListVersinoCounter in mSmsMmsConvoListVersion - * @return + * @return true if a list change has been detected */ - /* package */ boolean refreshImEmailConvoVersions() { boolean listChangeDetected = false; FilterInfo fi = new FilterInfo(); @@ -3236,12 +3116,6 @@ public class BluetoothMapContent { ele.setVersionCounter(convoElement.getVersionCounter()); } - /** - * @param ele - * @param smsMmsCursor - * @param ap - * @param contacts - */ private void populateSmsMmsConvoElement(BluetoothMapConvoListingElement ele, Cursor smsMmsCursor, BluetoothMapAppParams ap, SmsMmsContacts contacts) { smsMmsCursor.moveToPosition(ele.getCursorIndex()); @@ -3299,11 +3173,6 @@ public class BluetoothMapContent { } } - /** - * @param ele - * @param tmpCursor - * @param fi - */ private void populateImEmailConvoElement(BluetoothMapConvoListingElement ele, Cursor tmpCursor, BluetoothMapAppParams ap, FilterInfo fi) { tmpCursor.moveToPosition(ele.getCursorIndex()); @@ -3384,7 +3253,7 @@ public class BluetoothMapContent { * @return the new URI with the appended parameters (if any) */ private Uri appendConvoListQueryParameters(BluetoothMapAppParams ap, Uri contentUri) { - Builder newUri = contentUri.buildUpon(); + Uri.Builder newUri = contentUri.buildUpon(); String str = ap.getFilterRecipient(); if (str != null) { str = str.trim(); @@ -3432,12 +3301,6 @@ public class BluetoothMapContent { * * Procedure if we don't have a filter * - Add all contacts - * - * @param convoElement - * @param contacts - * @param idsStr - * @param recipientFilter - * @return */ private boolean addSmsMmsContacts(BluetoothMapConvoListingElement convoElement, SmsMmsContacts contacts, String idsStr, String recipientFilter, @@ -3529,7 +3392,7 @@ public class BluetoothMapContent { /** * Get the folder name of an SMS message or MMS message. - * @param c the cursor pointing at the message + * * @return the folder name. */ private String getFolderName(int type, int threadId) { @@ -3573,8 +3436,9 @@ public class BluetoothMapContent { return getEmailMessage(id, appParams, folderElement); case IM: return getIMMessage(id, appParams, folderElement); + default: + throw new IllegalArgumentException("Invalid message handle."); } - throw new IllegalArgumentException("Invalid message handle."); } private String setVCardFromPhoneNumber(BluetoothMapbMessage message, String phone, @@ -3774,7 +3638,6 @@ public class BluetoothMapContent { * Read out a mime data part and return the data in a byte array. * @param contentPartUri TODO * @param partid the content provider id of the Mime Part. - * @return */ private byte[] readRawDataPart(Uri contentPartUri, long partid) { String uriStr = new String(contentPartUri + "/" + partid); @@ -3909,79 +3772,6 @@ public class BluetoothMapContent { } /** - * Read out the mms parts and update the bMessage object provided i {@linkplain message} - * @param id the content provider ID of the message - * @param message the bMessage object to add the information to - */ - private void extractIMParts(long id, BluetoothMapbMessageMime message) { - /* Handling of filtering out non-text parts for exclude - * attachments is handled within the bMessage object. */ - final String[] projection = null; - String selection = new String(BluetoothMapContract.MessageColumns._ID + "=" + id); - String uriStr = - new String(mBaseUri + BluetoothMapContract.TABLE_MESSAGE + "/" + id + "/part"); - Uri uriAddress = Uri.parse(uriStr); - BluetoothMapbMessageMime.MimePart part; - Cursor c = mResolver.query(uriAddress, projection, selection, null, null); - try { - if (c.moveToFirst()) { - do { - Long partId = c.getLong( - c.getColumnIndex(BluetoothMapContract.MessagePartColumns._ID)); - String charset = c.getString( - c.getColumnIndex(BluetoothMapContract.MessagePartColumns.CHARSET)); - String filename = c.getString( - c.getColumnIndex(BluetoothMapContract.MessagePartColumns.FILENAME)); - String text = c.getString( - c.getColumnIndex(BluetoothMapContract.MessagePartColumns.TEXT)); - String body = c.getString( - c.getColumnIndex(BluetoothMapContract.MessagePartColumns.RAW_DATA)); - String cid = c.getString( - c.getColumnIndex(BluetoothMapContract.MessagePartColumns.CONTENT_ID)); - - if (V) { - Log.d(TAG, " _id : " + partId + "\n charset : " + charset - + "\n filename : " + filename + "\n text : " + text - + "\n cid : " + cid); - } - - part = message.addMimePart(); - part.mContentId = cid; - try { - if (text.equalsIgnoreCase("yes")) { - part.mData = body.getBytes("UTF-8"); - part.mCharsetName = "utf-8"; - } else { - part.mData = readRawDataPart( - Uri.parse(mBaseUri + BluetoothMapContract.TABLE_MESSAGE_PART), - partId); - if (charset != null) { - part.mCharsetName = - CharacterSets.getMimeName(Integer.parseInt(charset)); - } - } - } catch (NumberFormatException e) { - Log.d(TAG, "extractIMParts", e); - part.mData = null; - part.mCharsetName = null; - } catch (UnsupportedEncodingException e) { - Log.d(TAG, "extractIMParts", e); - part.mData = null; - part.mCharsetName = null; - } - part.mFileName = filename; - } while (c.moveToNext()); - } - } finally { - if (c != null) { - c.close(); - } - } - - message.updateCharset(); - } - - /** * * @param id the content provider id for the message to fetch. * @param appParams The application parameter object received from the client. @@ -4192,12 +3982,14 @@ public class BluetoothMapContent { is.close(); } } catch (IOException e) { + Log.w(TAG, e); } try { if (fd != null) { fd.close(); } } catch (IOException e) { + Log.w(TAG, e); } } return message.encode(); @@ -4209,14 +4001,6 @@ public class BluetoothMapContent { } throw new IllegalArgumentException("EMAIL handle not found"); } - /** - * - * @param id the content provider id for the message to fetch. - * @param appParams The application parameter object received from the client. - * @return a byte[] containing the UTF-8 encoded bMessage to send to the client. - * @throws UnsupportedEncodingException if UTF-8 is not supported, - * which is guaranteed to be supported on an android device - */ /** * @@ -4277,8 +4061,6 @@ public class BluetoothMapContent { // The parts - //FIXME use the parts when ready - until then use the body column for text-only - // extractIMParts(id, message); //FIXME next few lines are temporary code MimePart part = message.addMimePart(); part.mData = diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapConfig.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapConfig.java index 28051a6fe7..01c1e9ad4b 100644 --- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapConfig.java +++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapConfig.java @@ -22,6 +22,7 @@ import android.content.res.Resources; import android.util.Log; import com.android.bluetooth.R; +import com.android.internal.annotations.VisibleForTesting; public class BluetoothPbapConfig { private static boolean sUseProfileForOwnerVcard = true; @@ -57,4 +58,9 @@ public class BluetoothPbapConfig { public static boolean includePhotosInVcard() { return sIncludePhotosInVcard; } + + @VisibleForTesting + public static void setIncludePhotosInVcard(boolean includePhotosInVcard) { + sIncludePhotosInVcard = includePhotosInVcard; + } } diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java index 74935cc50c..14e26470a9 100644 --- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java +++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java @@ -53,6 +53,7 @@ import android.util.Log; import com.android.bluetooth.R; import com.android.bluetooth.util.DevicePolicyUtils; +import com.android.internal.annotations.VisibleForTesting; import com.android.obex.Operation; import com.android.obex.ResponseCodes; import com.android.obex.ServerOperation; @@ -140,7 +141,6 @@ public class BluetoothPbapVcardManager { } //End enhancement - BluetoothPbapCallLogComposer composer = new BluetoothPbapCallLogComposer(mContext); String name = BluetoothPbapService.getLocalPhoneName(); String number = BluetoothPbapService.getLocalPhoneNum(); String vcard = BluetoothPbapCallLogComposer.composeVCardForPhoneOwnNumber( @@ -174,7 +174,7 @@ public class BluetoothPbapVcardManager { * @param type specifies which phonebook object, e.g., pb, fav * @return */ - public final int getContactsSize(final int type) { + private int getContactsSize(final int type) { final Uri myUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext); Cursor contactCursor = null; String selectionClause = null; @@ -182,8 +182,8 @@ public class BluetoothPbapVcardManager { selectionClause = Phone.STARRED + " = 1"; } try { - contactCursor = mResolver.query(myUri, - new String[]{Phone.CONTACT_ID}, selectionClause, + contactCursor = BluetoothPbapMethodProxy.getInstance().contentResolverQuery(mResolver, + myUri, new String[]{Phone.CONTACT_ID}, selectionClause, null, Phone.CONTACT_ID); if (contactCursor == null) { return 0; @@ -203,14 +203,14 @@ public class BluetoothPbapVcardManager { return 0; } - public final int getCallHistorySize(final int type) { + private int getCallHistorySize(final int type) { final Uri myUri = CallLog.Calls.CONTENT_URI; String selection = BluetoothPbapObexServer.createSelectionPara(type); int size = 0; Cursor callCursor = null; try { - callCursor = - mResolver.query(myUri, null, selection, null, CallLog.Calls.DEFAULT_SORT_ORDER); + callCursor = BluetoothPbapMethodProxy.getInstance().contentResolverQuery(mResolver, + myUri, null, selection, null, CallLog.Calls.DEFAULT_SORT_ORDER); if (callCursor != null) { size = callCursor.getCount(); } @@ -225,9 +225,12 @@ public class BluetoothPbapVcardManager { return size; } - private static final int CALLS_NUMBER_COLUMN_INDEX = 0; - private static final int CALLS_NAME_COLUMN_INDEX = 1; - private static final int CALLS_NUMBER_PRESENTATION_COLUMN_INDEX = 2; + @VisibleForTesting + static final int CALLS_NUMBER_COLUMN_INDEX = 0; + @VisibleForTesting + static final int CALLS_NAME_COLUMN_INDEX = 1; + @VisibleForTesting + static final int CALLS_NUMBER_PRESENTATION_COLUMN_INDEX = 2; public final ArrayList<String> loadCallHistoryList(final int type) { final Uri myUri = CallLog.Calls.CONTENT_URI; @@ -240,7 +243,8 @@ public class BluetoothPbapVcardManager { Cursor callCursor = null; ArrayList<String> list = new ArrayList<String>(); try { - callCursor = mResolver.query(myUri, projection, selection, null, CALLLOG_SORT_ORDER); + callCursor = BluetoothPbapMethodProxy.getInstance().contentResolverQuery(mResolver, + myUri, projection, selection, null, CALLLOG_SORT_ORDER); if (callCursor != null) { for (callCursor.moveToFirst(); !callCursor.isAfterLast(); callCursor.moveToNext()) { String name = callCursor.getString(CALLS_NAME_COLUMN_INDEX); @@ -291,7 +295,8 @@ public class BluetoothPbapVcardManager { if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) { orderBy = Phone.DISPLAY_NAME; } - contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, null, null, orderBy); + contactCursor = BluetoothPbapMethodProxy.getInstance().contentResolverQuery(mResolver, + myUri, PHONES_CONTACTS_PROJECTION, null, null, orderBy); if (contactCursor != null) { appendDistinctNameIdList(nameList, mContext.getString(android.R.string.unknownName), contactCursor); @@ -349,7 +354,8 @@ public class BluetoothPbapVcardManager { final Uri myUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext); Cursor contactCursor = null; try { - contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, null, null, + contactCursor = BluetoothPbapMethodProxy.getInstance().contentResolverQuery(mResolver, + myUri, PHONES_CONTACTS_PROJECTION, null, null, Phone.CONTACT_ID); ArrayList<String> contactNameIdList = new ArrayList<String>(); @@ -423,7 +429,6 @@ public class BluetoothPbapVcardManager { public final ArrayList<String> getContactNamesByNumber(final String phoneNumber) { ArrayList<String> nameList = new ArrayList<String>(); - ArrayList<String> tempNameList = new ArrayList<String>(); Cursor contactCursor = null; Uri uri = null; @@ -438,7 +443,8 @@ public class BluetoothPbapVcardManager { } try { - contactCursor = mResolver.query(uri, projection, null, null, Phone.CONTACT_ID); + contactCursor = BluetoothPbapMethodProxy.getInstance().contentResolverQuery(mResolver, + uri, projection, null, null, Phone.CONTACT_ID); if (contactCursor != null) { appendDistinctNameIdList(nameList, mContext.getString(android.R.string.unknownName), @@ -457,13 +463,6 @@ public class BluetoothPbapVcardManager { contactCursor = null; } } - int tempListSize = tempNameList.size(); - for (int index = 0; index < tempListSize; index++) { - String object = tempNameList.get(index); - if (!nameList.contains(object)) { - nameList.add(object); - } - } return nameList; } @@ -479,7 +478,8 @@ public class BluetoothPbapVcardManager { long primaryVcMsb = 0; ArrayList<String> list = new ArrayList<String>(); try { - callCursor = mResolver.query(myUri, null, selection, null, null); + callCursor = BluetoothPbapMethodProxy.getInstance().contentResolverQuery(mResolver, + myUri, null, selection, null, null); while (callCursor != null && callCursor.moveToNext()) { count = count + 1; } @@ -522,7 +522,8 @@ public class BluetoothPbapVcardManager { long endPointId = 0; try { // Need test to see if order by _ID is ok here, or by date? - callsCursor = mResolver.query(myUri, CALLLOG_PROJECTION, typeSelection, null, + callsCursor = BluetoothPbapMethodProxy.getInstance().contentResolverQuery(mResolver, + myUri, CALLLOG_PROJECTION, typeSelection, null, CALLLOG_SORT_ORDER); if (callsCursor != null) { callsCursor.moveToPosition(startPoint - 1); @@ -595,7 +596,8 @@ public class BluetoothPbapVcardManager { } try { - contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, selectionClause, + contactCursor = BluetoothPbapMethodProxy.getInstance().contentResolverQuery(mResolver, + myUri, PHONES_CONTACTS_PROJECTION, selectionClause, null, Phone.CONTACT_ID); if (contactCursor != null) { contactIdCursor = @@ -638,7 +640,8 @@ public class BluetoothPbapVcardManager { if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) { orderBy = Phone.DISPLAY_NAME; } - contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, null, null, orderBy); + contactCursor = BluetoothPbapMethodProxy.getInstance().contentResolverQuery(mResolver, + myUri, PHONES_CONTACTS_PROJECTION, null, null, orderBy); } catch (CursorWindowAllocationException e) { Log.e(TAG, "CursorWindowAllocationException while composing phonebook one vcard"); } finally { @@ -1013,7 +1016,8 @@ public class BluetoothPbapVcardManager { } public String stripTelephoneNumber(String vCard) { - String[] attr = vCard.split(System.getProperty("line.separator")); + String separator = System.getProperty("line.separator"); + String[] attr = vCard.split(separator); String stripedVCard = ""; for (int i = 0; i < attr.length; i++) { if (attr[i].startsWith("TEL")) { @@ -1036,7 +1040,7 @@ public class BluetoothPbapVcardManager { for (int i = 0; i < attr.length; i++) { if (!attr[i].isEmpty()) { - stripedVCard = stripedVCard.concat(attr[i] + "\n"); + stripedVCard = stripedVCard.concat(attr[i] + separator); } } if (V) { @@ -1045,6 +1049,7 @@ public class BluetoothPbapVcardManager { return stripedVCard; } + // TODO: Merge this class with BluetoothPbapSimVcardManager.HandlerForStringBuffer /** * Handler to emit vCards to PCE. */ diff --git a/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java b/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java index d73ae5b3b0..436b89dfb6 100644 --- a/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java +++ b/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java @@ -157,7 +157,7 @@ public class TbsGeneric { mTbsGatt = tbsGatt; int ccid = ContentControlIdKeeper.acquireCcid(new ParcelUuid(TbsGatt.UUID_GTBS), - BluetoothLeAudio.CONTEXT_TYPE_COMMUNICATION); + BluetoothLeAudio.CONTEXT_TYPE_CONVERSATIONAL); if (!isCcidValid(ccid)) { Log.e(TAG, " CCID is not valid"); cleanup(); @@ -280,7 +280,7 @@ public class TbsGeneric { // Acquire CCID for TbsObject. The CCID is released on remove() Bearer bearer = new Bearer(token, callback, uci, uriSchemes, capabilities, providerName, technology, ContentControlIdKeeper.acquireCcid(new ParcelUuid(UUID.randomUUID()), - BluetoothLeAudio.CONTEXT_TYPE_COMMUNICATION)); + BluetoothLeAudio.CONTEXT_TYPE_CONVERSATIONAL)); if (isCcidValid(bearer.ccid)) { mBearerList.add(bearer); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java index 5aa6539daa..e53b3312a6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java @@ -1106,7 +1106,7 @@ public class LeAudioServiceTest { doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class)); connectTestDevice(mSingleDevice, testGroupId); injectAudioConfChanged(testGroupId, BluetoothLeAudio.CONTEXT_TYPE_MEDIA | - BluetoothLeAudio.CONTEXT_TYPE_COMMUNICATION); + BluetoothLeAudio.CONTEXT_TYPE_CONVERSATIONAL); injectGroupStatusChange(testGroupId, BluetoothLeAudio.GROUP_STATUS_ACTIVE); String action = BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED; @@ -1127,7 +1127,7 @@ public class LeAudioServiceTest { String action = BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED; Integer contexts = BluetoothLeAudio.CONTEXT_TYPE_MEDIA | - BluetoothLeAudio.CONTEXT_TYPE_COMMUNICATION; + BluetoothLeAudio.CONTEXT_TYPE_CONVERSATIONAL; injectAudioConfChanged(testGroupId, contexts); Intent intent = TestUtils.waitForNoIntent(TIMEOUT_MS, mDeviceQueueMap.get(mSingleDevice)); @@ -1189,7 +1189,7 @@ public class LeAudioServiceTest { connectTestDevice(mSingleDevice, testGroupId); injectAudioConfChanged(testGroupId, BluetoothLeAudio.CONTEXT_TYPE_MEDIA | - BluetoothLeAudio.CONTEXT_TYPE_COMMUNICATION); + BluetoothLeAudio.CONTEXT_TYPE_CONVERSATIONAL); sendEventAndVerifyIntentForGroupStatusChanged(testGroupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); sendEventAndVerifyIntentForGroupStatusChanged(testGroupId, LeAudioStackEvent.GROUP_STATUS_INACTIVE); diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapContractTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapContractTest.java new file mode 100644 index 0000000000..0a34f886e6 --- /dev/null +++ b/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapContractTest.java @@ -0,0 +1,127 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.bluetooth.mapapi; + +import static com.google.common.truth.Truth.assertThat; + +import android.net.Uri; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class BluetoothMapContractTest { + + private static final String TEST_AUTHORITY = "com.test"; + private static final String ACCOUNT_ID = "test_account_id"; + private static final String MESSAGE_ID = "test_message_id"; + private static final String CONTACT_ID = "test_contact_id"; + + @Test + public void testBuildAccountUri() { + final String expectedUriString = "content://" + TEST_AUTHORITY + "/" + + BluetoothMapContract.TABLE_ACCOUNT; + + Uri result = BluetoothMapContract.buildAccountUri(TEST_AUTHORITY); + assertThat(result.toString()).isEqualTo(expectedUriString); + } + + @Test + public void testBuildAccountUriWithId() { + final String expectedUriString = "content://" + TEST_AUTHORITY + "/" + + BluetoothMapContract.TABLE_ACCOUNT + "/" + ACCOUNT_ID; + + Uri result = BluetoothMapContract.buildAccountUriwithId(TEST_AUTHORITY, ACCOUNT_ID); + assertThat(result.toString()).isEqualTo(expectedUriString); + } + + @Test + public void testBuildMessageUri() { + final String expectedUriString = "content://" + TEST_AUTHORITY + "/" + + BluetoothMapContract.TABLE_MESSAGE; + + Uri result = BluetoothMapContract.buildMessageUri(TEST_AUTHORITY); + assertThat(result.toString()).isEqualTo(expectedUriString); + } + + @Test + public void testBuildMessageUri_withAccountId() { + final String expectedUriString = "content://" + TEST_AUTHORITY + "/" + + ACCOUNT_ID + "/" + BluetoothMapContract.TABLE_MESSAGE; + + Uri result = BluetoothMapContract.buildMessageUri(TEST_AUTHORITY, ACCOUNT_ID); + assertThat(result.toString()).isEqualTo(expectedUriString); + } + + @Test + public void testBuildMessageUriWithId() { + final String expectedUriString = "content://" + TEST_AUTHORITY + "/" + + ACCOUNT_ID + "/" + BluetoothMapContract.TABLE_MESSAGE + "/" + MESSAGE_ID; + + Uri result = BluetoothMapContract.buildMessageUriWithId( + TEST_AUTHORITY, ACCOUNT_ID, MESSAGE_ID); + assertThat(result.toString()).isEqualTo(expectedUriString); + } + + @Test + public void testBuildFolderUri() { + final String expectedUriString = "content://" + TEST_AUTHORITY + "/" + + ACCOUNT_ID + "/" + BluetoothMapContract.TABLE_FOLDER; + + Uri result = BluetoothMapContract.buildFolderUri(TEST_AUTHORITY, ACCOUNT_ID); + assertThat(result.toString()).isEqualTo(expectedUriString); + } + + @Test + public void testBuildConversationUri() { + final String expectedUriString = "content://" + TEST_AUTHORITY + "/" + + ACCOUNT_ID + "/" + BluetoothMapContract.TABLE_CONVERSATION; + + Uri result = BluetoothMapContract.buildConversationUri(TEST_AUTHORITY, ACCOUNT_ID); + assertThat(result.toString()).isEqualTo(expectedUriString); + } + + @Test + public void testBuildConvoContactsUri() { + final String expectedUriString = "content://" + TEST_AUTHORITY + "/" + + BluetoothMapContract.TABLE_CONVOCONTACT; + + Uri result = BluetoothMapContract.buildConvoContactsUri(TEST_AUTHORITY); + assertThat(result.toString()).isEqualTo(expectedUriString); + } + + @Test + public void testBuildConvoContactsUri_withAccountId() { + final String expectedUriString = "content://" + TEST_AUTHORITY + "/" + + ACCOUNT_ID + "/" + BluetoothMapContract.TABLE_CONVOCONTACT; + + Uri result = BluetoothMapContract.buildConvoContactsUri(TEST_AUTHORITY, ACCOUNT_ID); + assertThat(result.toString()).isEqualTo(expectedUriString); + } + + @Test + public void testBuildConvoContactsUriWithId() { + final String expectedUriString = "content://" + TEST_AUTHORITY + "/" + + ACCOUNT_ID + "/" + BluetoothMapContract.TABLE_CONVOCONTACT + "/" + CONTACT_ID; + + Uri result = BluetoothMapContract.buildConvoContactsUriWithId( + TEST_AUTHORITY, ACCOUNT_ID, CONTACT_ID); + assertThat(result.toString()).isEqualTo(expectedUriString); + } +} diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java index 4e84ecdb8a..5492e1cc98 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java @@ -204,8 +204,8 @@ public class BluetoothPbapSimVcardManagerTest { return currentPosition.get() >= size; }); when(cursor.moveToNext()).then((Answer<Boolean>) i -> { - currentPosition.getAndAdd(1); - return true; + int pos = currentPosition.addAndGet(1); + return pos < size; }); when(cursor.getString(anyInt())).then((Answer<String>) i -> { return nameList.get(currentPosition.get()); @@ -254,8 +254,8 @@ public class BluetoothPbapSimVcardManagerTest { return currentPosition.get() >= size; }); when(cursor.moveToNext()).then((Answer<Boolean>) i -> { - currentPosition.getAndAdd(1); - return true; + int pos = currentPosition.addAndGet(1); + return pos < size; }); when(cursor.getString(anyInt())).then((Answer<String>) i -> { return nameList.get(currentPosition.get()); @@ -289,8 +289,8 @@ public class BluetoothPbapSimVcardManagerTest { return currentPosition.get() >= size; }); when(cursor.moveToNext()).then((Answer<Boolean>) i -> { - currentPosition.getAndAdd(1); - return true; + int pos = currentPosition.addAndGet(1); + return pos < size; }); when(cursor.getString(anyInt())).then((Answer<String>) i -> { return nameList.get(currentPosition.get()); @@ -328,8 +328,8 @@ public class BluetoothPbapSimVcardManagerTest { return currentPosition.get() >= size; }); when(cursor.moveToNext()).then((Answer<Boolean>) i -> { - currentPosition.getAndAdd(1); - return true; + int pos = currentPosition.addAndGet(1); + return pos < size; }); when(cursor.getString(BluetoothPbapSimVcardManager.NAME_COLUMN_INDEX)).then( (Answer<String>) i -> { diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerTest.java new file mode 100644 index 0000000000..b6cceb5709 --- /dev/null +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerTest.java @@ -0,0 +1,336 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.bluetooth.pbap; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.provider.CallLog; +import android.provider.ContactsContract; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.bluetooth.R; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.mockito.stubbing.Answer; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class BluetoothPbapVcardManagerTest { + + private static final String TAG = BluetoothPbapVcardManagerTest.class.getSimpleName(); + + @Spy + BluetoothPbapMethodProxy mPbapMethodProxy = BluetoothPbapMethodProxy.getInstance(); + + Context mContext; + BluetoothPbapVcardManager mManager; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + BluetoothPbapMethodProxy.setInstanceForTesting(mPbapMethodProxy); + mContext = InstrumentationRegistry.getTargetContext(); + mManager = new BluetoothPbapVcardManager(mContext); + } + + @After + public void tearDown() { + BluetoothPbapMethodProxy.setInstanceForTesting(null); + } + + @Test + public void testGetOwnerPhoneNumberVcard_whenUseProfileForOwnerVcard() { + BluetoothPbapConfig.setIncludePhotosInVcard(true); + + assertThat(mManager.getOwnerPhoneNumberVcard(/*vcardType21=*/true, /*filter=*/null)) + .isNotNull(); + } + + @Test + public void testGetOwnerPhoneNumberVcard_whenNotUseProfileForOwnerVcard() { + BluetoothPbapConfig.setIncludePhotosInVcard(false); + + assertThat(mManager.getOwnerPhoneNumberVcard(/*vcardType21=*/true, /*filter=*/null)) + .isNotNull(); + } + + @Test + public void testGetPhonebookSize_whenTypeIsPhonebook() { + Cursor cursor = mock(Cursor.class); + doReturn(cursor).when(mPbapMethodProxy) + .contentResolverQuery(any(), any(), any(), any(), any(), any()); + + // 5 distinct contact IDs. + final List<Integer> contactIdsWithDuplicates = Arrays.asList(0, 1, 1, 2, 2, 3, 3, 4, 4); + + // Implement Cursor iteration + final int size = contactIdsWithDuplicates.size(); + AtomicInteger currentPosition = new AtomicInteger(0); + when(cursor.moveToPosition(anyInt())).then((Answer<Boolean>) i -> { + int position = i.getArgument(0); + currentPosition.set(position); + return true; + }); + when(cursor.moveToNext()).then((Answer<Boolean>) i -> { + int pos = currentPosition.addAndGet(1); + return pos < size; + }); + when(cursor.getLong(anyInt())).then((Answer<Long>) i -> { + return (long) contactIdsWithDuplicates.get(currentPosition.get()); + }); + + // 5 distinct contact IDs + self (which is only included for phonebook) + final int expectedSize = 5 + 1; + + assertThat(mManager.getPhonebookSize(BluetoothPbapObexServer.ContentType.PHONEBOOK, null)) + .isEqualTo(expectedSize); + } + + @Test + public void testGetPhonebookSize_whenTypeIsFavorites() { + Cursor cursor = mock(Cursor.class); + doReturn(cursor).when(mPbapMethodProxy) + .contentResolverQuery(any(), any(), any(), any(), any(), any()); + + // 5 distinct contact IDs. + final List<Integer> contactIdsWithDuplicates = Arrays.asList( + 0, 1, 1, 2, // starred + 2, 3, 3, 4, 4 // not starred + ); + + // Implement Cursor iteration + final int starredSize = 4; + AtomicInteger currentPosition = new AtomicInteger(0); + when(cursor.moveToPosition(anyInt())).then((Answer<Boolean>) i -> { + int position = i.getArgument(0); + currentPosition.set(position); + return true; + }); + when(cursor.moveToNext()).then((Answer<Boolean>) i -> { + int pos = currentPosition.addAndGet(1); + return pos < starredSize; + }); + when(cursor.getLong(anyInt())).then((Answer<Long>) i -> { + return (long) contactIdsWithDuplicates.get(currentPosition.get()); + }); + + // Among 4 starred contact Ids, there are 3 distinct contact IDs + final int expectedSize = 3; + + assertThat(mManager.getPhonebookSize(BluetoothPbapObexServer.ContentType.FAVORITES, null)) + .isEqualTo(expectedSize); + } + + @Test + public void testGetPhonebookSize_whenTypeIsSimPhonebook() { + Cursor cursor = mock(Cursor.class); + doReturn(cursor).when(mPbapMethodProxy) + .contentResolverQuery(any(), any(), any(), any(), any(), any()); + final int expectedSize = 10; + when(cursor.getCount()).thenReturn(expectedSize); + BluetoothPbapSimVcardManager simVcardManager = mock(BluetoothPbapSimVcardManager.class); + + assertThat(mManager.getPhonebookSize(BluetoothPbapObexServer.ContentType.SIM_PHONEBOOK, + simVcardManager)).isEqualTo(expectedSize); + verify(simVcardManager).getSIMContactsSize(); + } + + @Test + public void testGetPhonebookSize_whenTypeIsHistory() { + final int historySize = 10; + Cursor cursor = mock(Cursor.class); + when(cursor.getCount()).thenReturn(historySize); + doReturn(cursor).when(mPbapMethodProxy) + .contentResolverQuery(any(), any(), any(), any(), any(), any()); + + assertThat(mManager.getPhonebookSize( + BluetoothPbapObexServer.ContentType.INCOMING_CALL_HISTORY, null)) + .isEqualTo(historySize); + } + + @Test + public void testLoadCallHistoryList() { + Cursor cursor = mock(Cursor.class); + doReturn(cursor).when(mPbapMethodProxy) + .contentResolverQuery(any(), any(), any(), any(), any(), any()); + + List<String> nameList = Arrays.asList("A", "B", "", ""); + List<String> numberList = Arrays.asList("0000", "1111", "2222", "3333"); + List<Integer> presentationAllowedList = Arrays.asList( + CallLog.Calls.PRESENTATION_ALLOWED, + CallLog.Calls.PRESENTATION_ALLOWED, + CallLog.Calls.PRESENTATION_ALLOWED, + CallLog.Calls.PRESENTATION_UNKNOWN); // The number "3333" should not be shown. + + List<String> expectedResult = Arrays.asList( + "A", "B", "2222", mContext.getString(R.string.unknownNumber)); + + // Implement Cursor iteration + final int size = nameList.size(); + AtomicInteger currentPosition = new AtomicInteger(0); + when(cursor.moveToFirst()).then((Answer<Boolean>) i -> { + currentPosition.set(0); + return true; + }); + when(cursor.isAfterLast()).then((Answer<Boolean>) i -> { + return currentPosition.get() >= size; + }); + when(cursor.moveToNext()).then((Answer<Boolean>) i -> { + int pos = currentPosition.addAndGet(1); + return pos < size; + }); + when(cursor.getString(BluetoothPbapVcardManager.CALLS_NAME_COLUMN_INDEX)) + .then((Answer<String>) i -> { + return nameList.get(currentPosition.get()); + }); + when(cursor.getString(BluetoothPbapVcardManager.CALLS_NUMBER_COLUMN_INDEX)) + .then((Answer<String>) i -> { + return numberList.get(currentPosition.get()); + }); + when(cursor.getInt(BluetoothPbapVcardManager.CALLS_NUMBER_PRESENTATION_COLUMN_INDEX)) + .then((Answer<Integer>) i -> { + return presentationAllowedList.get(currentPosition.get()); + }); + + assertThat(mManager.loadCallHistoryList( + BluetoothPbapObexServer.ContentType.INCOMING_CALL_HISTORY)) + .isEqualTo(expectedResult); + } + + @Test + public void testGetPhonebookNameList() { + final String localPhoneName = "test_local_phone_name"; + BluetoothPbapService.setLocalPhoneName(localPhoneName); + + Cursor cursor = mock(Cursor.class); + doReturn(cursor).when(mPbapMethodProxy) + .contentResolverQuery(any(), any(), any(), any(), any(), any()); + + List<String> nameList = Arrays.asList("A", "B", "C", ""); + List<Integer> contactIdList = Arrays.asList(0, 1, 2, 3); + + List<String> expectedResult = Arrays.asList( + localPhoneName, + "A,0", + "B,1", + "C,2", + mContext.getString(android.R.string.unknownName) + ",3"); + + // Implement Cursor iteration + final int size = nameList.size(); + AtomicInteger currentPosition = new AtomicInteger(0); + when(cursor.moveToPosition(anyInt())).then((Answer<Boolean>) i -> { + int position = i.getArgument(0); + currentPosition.set(position); + return true; + }); + when(cursor.moveToNext()).then((Answer<Boolean>) i -> { + int pos = currentPosition.addAndGet(1); + return pos < size; + }); + + final int contactIdColumn = 0; + final int nameColumn = 1; + when(cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID)).thenReturn(contactIdColumn); + when(cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME)).thenReturn(nameColumn); + + when(cursor.getLong(contactIdColumn)).then((Answer<Long>) i -> { + return (long) contactIdList.get(currentPosition.get()); + }); + when(cursor.getString(nameColumn)).then((Answer<String>) i -> { + return nameList.get(currentPosition.get()); + }); + + assertThat(mManager.getPhonebookNameList(BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL)) + .isEqualTo(expectedResult); + } + + @Test + public void testGetContactNamesByNumber_whenNumberIsNull() { + Cursor cursor = mock(Cursor.class); + doReturn(cursor).when(mPbapMethodProxy) + .contentResolverQuery(any(), any(), any(), any(), any(), any()); + + List<String> nameList = Arrays.asList("A", "B", "C", ""); + List<Integer> contactIdList = Arrays.asList(0, 1, 2, 3); + + List<String> expectedResult = Arrays.asList( + "A,0", + "B,1", + "C,2", + mContext.getString(android.R.string.unknownName) + ",3"); + + // Implement Cursor iteration + final int size = nameList.size(); + AtomicInteger currentPosition = new AtomicInteger(0); + when(cursor.moveToPosition(anyInt())).then((Answer<Boolean>) i -> { + int position = i.getArgument(0); + currentPosition.set(position); + return true; + }); + when(cursor.moveToNext()).then((Answer<Boolean>) i -> { + int pos = currentPosition.addAndGet(1); + return pos < size; + }); + + final int contactIdColumn = 0; + final int nameColumn = 1; + when(cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID)).thenReturn(contactIdColumn); + when(cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME)).thenReturn(nameColumn); + + when(cursor.getLong(contactIdColumn)).then((Answer<Long>) i -> { + return (long) contactIdList.get(currentPosition.get()); + }); + when(cursor.getString(nameColumn)).then((Answer<String>) i -> { + return nameList.get(currentPosition.get()); + }); + + assertThat(mManager.getContactNamesByNumber(null)) + .isEqualTo(expectedResult); + } + + @Test + public void testStripTelephoneNumber() { + final String separator = System.getProperty("line.separator"); + final String vCard = "SomeRandomLine" + separator + "TEL:+1-(588)-328-382" + separator; + final String expectedResult = "SomeRandomLine" + separator + "TEL:+1588328382" + separator; + + assertThat(mManager.stripTelephoneNumber(vCard)).isEqualTo(expectedResult); + } +} diff --git a/android/pandora/mmi2grpc/mmi2grpc/__init__.py b/android/pandora/mmi2grpc/mmi2grpc/__init__.py index 9be42e53c6..9d7f49b855 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/__init__.py +++ b/android/pandora/mmi2grpc/mmi2grpc/__init__.py @@ -66,7 +66,7 @@ class IUT: # Note: we don't keep a single gRPC channel instance in the IUT class # because reset is allowed to close the gRPC server. with grpc.insecure_channel(f'localhost:{self.port}') as channel: - self._retry(Host(channel).Reset)(wait_for_ready=True) + self._retry(Host(channel).HardReset)(wait_for_ready=True) def __exit__(self, exc_type, exc_value, exc_traceback): self._a2dp = None diff --git a/android/pandora/mmi2grpc/mmi2grpc/sm.py b/android/pandora/mmi2grpc/mmi2grpc/sm.py index cc9986ddcc..2fa33a5f72 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/sm.py +++ b/android/pandora/mmi2grpc/mmi2grpc/sm.py @@ -94,5 +94,5 @@ class SMProxy(ProfileProxy): """ Please reset your device. """ - self.host.Reset() + self.host.SoftReset() return "OK" diff --git a/android/pandora/server/configs/PtsBotTestMts.xml b/android/pandora/server/configs/PtsBotTestMts.xml index 617032a75b..88985a58ef 100644 --- a/android/pandora/server/configs/PtsBotTestMts.xml +++ b/android/pandora/server/configs/PtsBotTestMts.xml @@ -34,6 +34,6 @@ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.android.bluetooth" /> + <option name="mainline-module-package-name" value="com.android.btservices" /> </object> </configuration> diff --git a/android/pandora/server/proto/pandora/host.proto b/android/pandora/server/proto/pandora/host.proto index d51417140c..e1f6271fae 100644 --- a/android/pandora/server/proto/pandora/host.proto +++ b/android/pandora/server/proto/pandora/host.proto @@ -11,13 +11,16 @@ import "google/protobuf/empty.proto"; // At startup, the Host must be in BR/EDR connectable mode // (see GAP connectability modes) service Host { - // Reset the host. - // **After** responding to this command, the GRPC server should loose + // Hard reset the host. + // **After** responding to this command, the gRPC server should loose // all its state. // This is comparable to a process restart or an hardware reset. - // The GRPC server might take some time to be available after + // The gRPC server might take some time to be available after // this command. - rpc Reset(google.protobuf.Empty) returns (google.protobuf.Empty); + rpc HardReset(google.protobuf.Empty) returns (google.protobuf.Empty); + // Soft reset the host by performing an HCI reset. Previous bonds must + // not be removed and the gRPC server must not be restarted. + rpc SoftReset(google.protobuf.Empty) returns (google.protobuf.Empty); // Read the local Bluetooth device address. // This should return the same value as a Read BD_ADDR HCI command. rpc ReadLocalAddress(google.protobuf.Empty) returns (ReadLocalAddressResponse); @@ -56,7 +59,7 @@ message ReadLocalAddressResponse { // A Token representing an ACL connection. // It's acquired via a Connect on the Host service. message Connection { - // Opaque value filled by the GRPC server, must not + // Opaque value filled by the gRPC server, must not // be modified nor crafted. bytes cookie = 1; } diff --git a/android/pandora/server/src/com/android/pandora/Host.kt b/android/pandora/server/src/com/android/pandora/Host.kt index e726cde6d3..239875413b 100644 --- a/android/pandora/server/src/com/android/pandora/Host.kt +++ b/android/pandora/server/src/com/android/pandora/Host.kt @@ -35,17 +35,17 @@ import io.grpc.stub.StreamObserver import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.channels.trySendBlocking import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.launch -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.channels.trySendBlocking -import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.runBlocking import pandora.HostGrpc.HostImplBase import pandora.HostProto.* @@ -80,37 +80,53 @@ class Host(private val context: Context, private val server: Server) : HostImplB scope.cancel() } - override fun reset(request: Empty, responseObserver: StreamObserver<Empty>) { - grpcUnary<Empty>(scope, responseObserver) { - Log.i(TAG, "reset") + private suspend fun rebootBluetooth() { + Log.i(TAG, "rebootBluetooth") - bluetoothAdapter.clearBluetooth() + val stateFlow = + flow.filter { it.getAction() == BluetoothAdapter.ACTION_STATE_CHANGED }.map { + it.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) + } + + if (bluetoothAdapter.isEnabled) { + bluetoothAdapter.disable() + stateFlow.filter { it == BluetoothAdapter.STATE_OFF }.first() + } - val stateFlow = - flow - .filter { it.getAction() == BluetoothAdapter.ACTION_STATE_CHANGED } - .map { it.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) } + // TODO: b/234892968 + delay(2000L) - if (bluetoothAdapter.isEnabled) { - bluetoothAdapter.disable() - stateFlow.filter { it == BluetoothAdapter.STATE_OFF }.first() - } + bluetoothAdapter.enable() + stateFlow.filter { it == BluetoothAdapter.STATE_ON }.first() + } - // TODO: b/234892968 - delay(2000L) + override fun hardReset(request: Empty, responseObserver: StreamObserver<Empty>) { + grpcUnary<Empty>(scope, responseObserver) { + Log.i(TAG, "hardReset") - bluetoothAdapter.enable() - stateFlow.filter { it == BluetoothAdapter.STATE_ON }.first() + bluetoothAdapter.clearBluetooth() - // The last expression is the return value. - Empty.getDefaultInstance() - } + rebootBluetooth() + + // The last expression is the return value. + Empty.getDefaultInstance() + } .invokeOnCompletion { Log.i(TAG, "Shutdown the gRPC Server") server.shutdownNow() } } + override fun softReset(request: Empty, responseObserver: StreamObserver<Empty>) { + grpcUnary<Empty>(scope, responseObserver) { + Log.i(TAG, "softReset") + + rebootBluetooth() + + Empty.getDefaultInstance() + } + } + override fun readLocalAddress( request: Empty, responseObserver: StreamObserver<ReadLocalAddressResponse> @@ -269,8 +285,8 @@ class Host(private val context: Context, private val server: Server) : HostImplB } override fun connectLE( - request: ConnectLERequest, - responseObserver: StreamObserver<ConnectLEResponse> + request: ConnectLERequest, + responseObserver: StreamObserver<ConnectLEResponse> ) { grpcUnary<ConnectLEResponse>(scope, responseObserver) { val ptsAddress = request.address.decodeToString() @@ -279,9 +295,7 @@ class Host(private val context: Context, private val server: Server) : HostImplB GattInstance(device!!, TRANSPORT_LE, context).waitForState(BluetoothProfile.STATE_CONNECTED) ConnectLEResponse.newBuilder() .setConnection( - Connection.newBuilder() - .setCookie(ByteString.copyFromUtf8(device.address)) - .build() + Connection.newBuilder().setCookie(ByteString.copyFromUtf8(device.address)).build() ) .build() } @@ -317,9 +331,9 @@ class Host(private val context: Context, private val server: Server) : HostImplB } } } - val bluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner - bluetoothLeScanner?.startScan(leScanCallback) ?: run { trySendBlocking(null) } - awaitClose { bluetoothLeScanner?.stopScan(leScanCallback) } + val bluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner + bluetoothLeScanner?.startScan(leScanCallback) ?: run { trySendBlocking(null) } + awaitClose { bluetoothLeScanner?.stopScan(leScanCallback) } } bluetoothDevice = flow.first() } diff --git a/android/pandora/test/connect.py b/android/pandora/test/connect.py index 73173417cc..f2b9fd8316 100644 --- a/android/pandora/test/connect.py +++ b/android/pandora/test/connect.py @@ -30,7 +30,7 @@ class ExampleTest(base_test.BaseTestClass): self.ref = self.pandora_devices[1] def setup_test(self): - self.dut.host.Reset() + self.dut.host.HardReset() # TODO: wait for server time.sleep(3) diff --git a/apex/Android.bp b/apex/Android.bp index 6d0d50a116..5c71a3e89c 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -108,7 +108,7 @@ sdk { bootclasspath_fragment { name: "com.android.btservices-bootclasspath-fragment", contents: ["framework-bluetooth"], - apex_available: ["com.android.bluetooth"], + apex_available: ["com.android.btservices"], // The bootclasspath_fragments that provide APIs on which this depends. fragments: [ @@ -158,5 +158,5 @@ bootclasspath_fragment { systemserverclasspath_fragment { name: "com.android.btservices-systemserverclasspath-fragment", standalone_contents: ["service-bluetooth"], - apex_available: ["com.android.bluetooth"], + apex_available: ["com.android.btservices"], } diff --git a/framework/Android.bp b/framework/Android.bp index ad61d12dcc..920e791394 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -78,7 +78,7 @@ java_sdk_library { ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], permitted_packages: [ diff --git a/framework/java/android/bluetooth/BluetoothLeAudio.java b/framework/java/android/bluetooth/BluetoothLeAudio.java index ea39b64a76..685c08ef7d 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudio.java +++ b/framework/java/android/bluetooth/BluetoothLeAudio.java @@ -233,7 +233,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { * Indicates conversation between humans as, for example, in telephony or video calls. * @hide */ - public static final int CONTEXT_TYPE_COMMUNICATION = 0x0002; + public static final int CONTEXT_TYPE_CONVERSATIONAL = 0x0002; /** * Indicates media as, for example, in music, public radio, podcast or video soundtrack. @@ -242,64 +242,66 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { public static final int CONTEXT_TYPE_MEDIA = 0x0004; /** - * Indicates instructional audio as, for example, in navigation, traffic announcements - * or user guidance. + * Indicates audio associated with a video gaming. * @hide */ - public static final int CONTEXT_TYPE_INSTRUCTIONAL = 0x0008; + public static final int CONTEXT_TYPE_GAME = 0x0008; /** - * Indicates attention seeking audio as, for example, in beeps signalling arrival of a message - * or keyboard clicks. + * Indicates instructional audio as, for example, in navigation, announcements or user + * guidance. * @hide */ - public static final int CONTEXT_TYPE_ATTENTION_SEEKING = 0x0010; + public static final int CONTEXT_TYPE_INSTRUCTIONAL = 0x0010; /** - * Indicates immediate alerts as, for example, in a low battery alarm, timer expiry or alarm - * clock. + * Indicates man machine communication as, for example, with voice recognition or virtual + * assistant. * @hide */ - public static final int CONTEXT_TYPE_IMMEDIATE_ALERT = 0x0020; + public static final int CONTEXT_TYPE_VOICE_ASSISTANTS = 0x0020; /** - * Indicates man machine communication as, for example, with voice recognition or virtual - * assistant. + * Indicates audio associated with a live audio stream. + * * @hide */ - public static final int CONTEXT_TYPE_MAN_MACHINE = 0x0040; + public static final int CONTEXT_TYPE_LIVE = 0x0040; /** - * Indicates emergency alerts as, for example, with fire alarms or other urgent alerts. + * Indicates sound effects as, for example, in keyboard, touch feedback; menu and user + * interface sounds, and other system sounds. * @hide */ - public static final int CONTEXT_TYPE_EMERGENCY_ALERT = 0x0080; + public static final int CONTEXT_TYPE_SOUND_EFFECTS = 0x0080; /** - * Indicates ringtone as in a call alert. + * Indicates notification and reminder sounds, attention-seeking audio, for example, in beeps + * signaling the arrival of a message. * @hide */ - public static final int CONTEXT_TYPE_RINGTONE = 0x0100; + public static final int CONTEXT_TYPE_NOTIFICATIONS = 0x0100; + /** - * Indicates audio associated with a television program and/or with metadata conforming to the - * Bluetooth Broadcast TV profile. + * Indicates ringtone as in a call alert. * @hide */ - public static final int CONTEXT_TYPE_TV = 0x0200; + public static final int CONTEXT_TYPE_RINGTONE = 0x0200; /** - * Indicates audio associated with a low latency live audio stream. - * + * Indicates alerts and timers, immediate alerts as, for example, in a low battery alarm, + * timer expiry or alarm clock. * @hide */ - public static final int CONTEXT_TYPE_LIVE = 0x0400; + public static final int CONTEXT_TYPE_ALERTS = 0x0400; + /** - * Indicates audio associated with a video game stream. + * Indicates emergency alarm as, for example, with fire alarms or other urgent alerts. * @hide */ - public static final int CONTEXT_TYPE_GAME = 0x0800; + public static final int CONTEXT_TYPE_EMERGENCY_ALARM = 0x0800; /** * This represents an invalid group ID. diff --git a/framework/tests/src/android/bluetooth/BluetoothCodecStatusTest.java b/framework/tests/src/android/bluetooth/BluetoothCodecStatusTest.java deleted file mode 100644 index 1cb2dcae86..0000000000 --- a/framework/tests/src/android/bluetooth/BluetoothCodecStatusTest.java +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bluetooth; - -import android.test.suitebuilder.annotation.SmallTest; - -import junit.framework.TestCase; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -/** - * Unit test cases for {@link BluetoothCodecStatus}. - * <p> - * To run this test, use: - * runtest --path core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java - */ -public class BluetoothCodecStatusTest extends TestCase { - - // Codec configs: A and B are same; C is different - private static final BluetoothCodecConfig config_A = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig config_B = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig config_C = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO, - 1000, 2000, 3000, 4000); - - // Local capabilities: A and B are same; C is different - private static final BluetoothCodecConfig local_capability1_A = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig local_capability1_B = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig local_capability1_C = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO, - 1000, 2000, 3000, 4000); - - - private static final BluetoothCodecConfig local_capability2_A = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig local_capability2_B = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig local_capability2_C = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig local_capability3_A = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig local_capability3_B = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig local_capability3_C = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig local_capability4_A = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000, - BluetoothCodecConfig.BITS_PER_SAMPLE_24, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig local_capability4_B = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000, - BluetoothCodecConfig.BITS_PER_SAMPLE_24, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig local_capability4_C = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000, - BluetoothCodecConfig.BITS_PER_SAMPLE_24, - BluetoothCodecConfig.CHANNEL_MODE_STEREO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig local_capability5_A = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000 | - BluetoothCodecConfig.SAMPLE_RATE_88200 | - BluetoothCodecConfig.SAMPLE_RATE_96000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16 | - BluetoothCodecConfig.BITS_PER_SAMPLE_24 | - BluetoothCodecConfig.BITS_PER_SAMPLE_32, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig local_capability5_B = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000 | - BluetoothCodecConfig.SAMPLE_RATE_88200 | - BluetoothCodecConfig.SAMPLE_RATE_96000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16 | - BluetoothCodecConfig.BITS_PER_SAMPLE_24 | - BluetoothCodecConfig.BITS_PER_SAMPLE_32, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig local_capability5_C = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000 | - BluetoothCodecConfig.SAMPLE_RATE_88200 | - BluetoothCodecConfig.SAMPLE_RATE_96000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16 | - BluetoothCodecConfig.BITS_PER_SAMPLE_24 | - BluetoothCodecConfig.BITS_PER_SAMPLE_32, - BluetoothCodecConfig.CHANNEL_MODE_STEREO, - 1000, 2000, 3000, 4000); - - - // Selectable capabilities: A and B are same; C is different - private static final BluetoothCodecConfig selectable_capability1_A = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig selectable_capability1_B = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig selectable_capability1_C = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig selectable_capability2_A = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig selectable_capability2_B = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig selectable_capability2_C = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig selectable_capability3_A = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig selectable_capability3_B = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig selectable_capability3_C = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.CHANNEL_MODE_STEREO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig selectable_capability4_A = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_24, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig selectable_capability4_B = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_24, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig selectable_capability4_C = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.BITS_PER_SAMPLE_24, - BluetoothCodecConfig.CHANNEL_MODE_STEREO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig selectable_capability5_A = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000 | - BluetoothCodecConfig.SAMPLE_RATE_88200 | - BluetoothCodecConfig.SAMPLE_RATE_96000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16 | - BluetoothCodecConfig.BITS_PER_SAMPLE_24 | - BluetoothCodecConfig.BITS_PER_SAMPLE_32, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig selectable_capability5_B = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000 | - BluetoothCodecConfig.SAMPLE_RATE_88200 | - BluetoothCodecConfig.SAMPLE_RATE_96000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16 | - BluetoothCodecConfig.BITS_PER_SAMPLE_24 | - BluetoothCodecConfig.BITS_PER_SAMPLE_32, - BluetoothCodecConfig.CHANNEL_MODE_STEREO | - BluetoothCodecConfig.CHANNEL_MODE_MONO, - 1000, 2000, 3000, 4000); - - private static final BluetoothCodecConfig selectable_capability5_C = - buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.SAMPLE_RATE_44100 | - BluetoothCodecConfig.SAMPLE_RATE_48000 | - BluetoothCodecConfig.SAMPLE_RATE_88200 | - BluetoothCodecConfig.SAMPLE_RATE_96000, - BluetoothCodecConfig.BITS_PER_SAMPLE_16 | - BluetoothCodecConfig.BITS_PER_SAMPLE_24 | - BluetoothCodecConfig.BITS_PER_SAMPLE_32, - BluetoothCodecConfig.CHANNEL_MODE_STEREO, - 1000, 2000, 3000, 4000); - - private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_A = - new ArrayList() {{ - add(local_capability1_A); - add(local_capability2_A); - add(local_capability3_A); - add(local_capability4_A); - add(local_capability5_A); - }}; - - private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_B = - new ArrayList() {{ - add(local_capability1_B); - add(local_capability2_B); - add(local_capability3_B); - add(local_capability4_B); - add(local_capability5_B); - }}; - - private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_B_REORDERED = - new ArrayList() {{ - add(local_capability5_B); - add(local_capability4_B); - add(local_capability2_B); - add(local_capability3_B); - add(local_capability1_B); - }}; - - private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_C = - new ArrayList() {{ - add(local_capability1_C); - add(local_capability2_C); - add(local_capability3_C); - add(local_capability4_C); - add(local_capability5_C); - }}; - - private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_A = - new ArrayList() {{ - add(selectable_capability1_A); - add(selectable_capability2_A); - add(selectable_capability3_A); - add(selectable_capability4_A); - add(selectable_capability5_A); - }}; - - private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_B = - new ArrayList() {{ - add(selectable_capability1_B); - add(selectable_capability2_B); - add(selectable_capability3_B); - add(selectable_capability4_B); - add(selectable_capability5_B); - }}; - - private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_B_REORDERED = - new ArrayList() {{ - add(selectable_capability5_B); - add(selectable_capability4_B); - add(selectable_capability2_B); - add(selectable_capability3_B); - add(selectable_capability1_B); - }}; - - private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_C = - new ArrayList() {{ - add(selectable_capability1_C); - add(selectable_capability2_C); - add(selectable_capability3_C); - add(selectable_capability4_C); - add(selectable_capability5_C); - }}; - - private static final BluetoothCodecStatus bcs_A = - new BluetoothCodecStatus(config_A, LOCAL_CAPABILITY_A, SELECTABLE_CAPABILITY_A); - private static final BluetoothCodecStatus bcs_B = - new BluetoothCodecStatus(config_B, LOCAL_CAPABILITY_B, SELECTABLE_CAPABILITY_B); - private static final BluetoothCodecStatus bcs_B_reordered = - new BluetoothCodecStatus(config_B, LOCAL_CAPABILITY_B_REORDERED, - SELECTABLE_CAPABILITY_B_REORDERED); - private static final BluetoothCodecStatus bcs_C = - new BluetoothCodecStatus(config_C, LOCAL_CAPABILITY_C, SELECTABLE_CAPABILITY_C); - - @SmallTest - public void testBluetoothCodecStatus_get_methods() { - - assertTrue(Objects.equals(bcs_A.getCodecConfig(), config_A)); - assertTrue(Objects.equals(bcs_A.getCodecConfig(), config_B)); - assertFalse(Objects.equals(bcs_A.getCodecConfig(), config_C)); - - assertTrue(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_A)); - assertTrue(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_B)); - assertFalse(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_C)); - - assertTrue(bcs_A.getCodecsSelectableCapabilities() - .equals(SELECTABLE_CAPABILITY_A)); - assertTrue(bcs_A.getCodecsSelectableCapabilities() - .equals(SELECTABLE_CAPABILITY_B)); - assertFalse(bcs_A.getCodecsSelectableCapabilities() - .equals(SELECTABLE_CAPABILITY_C)); - } - - @SmallTest - public void testBluetoothCodecStatus_equals() { - assertTrue(bcs_A.equals(bcs_B)); - assertTrue(bcs_B.equals(bcs_A)); - assertTrue(bcs_A.equals(bcs_B_reordered)); - assertTrue(bcs_B_reordered.equals(bcs_A)); - assertFalse(bcs_A.equals(bcs_C)); - assertFalse(bcs_C.equals(bcs_A)); - } - - private static BluetoothCodecConfig buildBluetoothCodecConfig(int sourceCodecType, - int codecPriority, int sampleRate, int bitsPerSample, int channelMode, - long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4) { - return new BluetoothCodecConfig.Builder() - .setCodecType(sourceCodecType) - .setCodecPriority(codecPriority) - .setSampleRate(sampleRate) - .setBitsPerSample(bitsPerSample) - .setChannelMode(channelMode) - .setCodecSpecific1(codecSpecific1) - .setCodecSpecific2(codecSpecific2) - .setCodecSpecific3(codecSpecific3) - .setCodecSpecific4(codecSpecific4) - .build(); - - } -} diff --git a/framework/tests/src/android/bluetooth/le/AdvertiseDataTest.java b/framework/tests/src/android/bluetooth/le/AdvertiseDataTest.java deleted file mode 100644 index e58d905357..0000000000 --- a/framework/tests/src/android/bluetooth/le/AdvertiseDataTest.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bluetooth.le; - -import android.os.Parcel; -import android.os.ParcelUuid; -import android.test.suitebuilder.annotation.SmallTest; - -import junit.framework.TestCase; - -/** - * Unit test cases for {@link AdvertiseData}. - * <p> - * To run the test, use adb shell am instrument -e class 'android.bluetooth.le.AdvertiseDataTest' -w - * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner' - */ -public class AdvertiseDataTest extends TestCase { - - private AdvertiseData.Builder mAdvertiseDataBuilder; - - @Override - protected void setUp() throws Exception { - mAdvertiseDataBuilder = new AdvertiseData.Builder(); - } - - @SmallTest - public void testEmptyData() { - Parcel parcel = Parcel.obtain(); - AdvertiseData data = mAdvertiseDataBuilder.build(); - data.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - AdvertiseData dataFromParcel = - AdvertiseData.CREATOR.createFromParcel(parcel); - assertEquals(data, dataFromParcel); - } - - @SmallTest - public void testEmptyServiceUuid() { - Parcel parcel = Parcel.obtain(); - AdvertiseData data = mAdvertiseDataBuilder.setIncludeDeviceName(true).build(); - data.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - AdvertiseData dataFromParcel = - AdvertiseData.CREATOR.createFromParcel(parcel); - assertEquals(data, dataFromParcel); - } - - @SmallTest - public void testEmptyManufacturerData() { - Parcel parcel = Parcel.obtain(); - int manufacturerId = 50; - byte[] manufacturerData = new byte[0]; - AdvertiseData data = - mAdvertiseDataBuilder.setIncludeDeviceName(true) - .addManufacturerData(manufacturerId, manufacturerData).build(); - data.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - AdvertiseData dataFromParcel = - AdvertiseData.CREATOR.createFromParcel(parcel); - assertEquals(data, dataFromParcel); - } - - @SmallTest - public void testEmptyServiceData() { - Parcel parcel = Parcel.obtain(); - ParcelUuid uuid = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB"); - byte[] serviceData = new byte[0]; - AdvertiseData data = - mAdvertiseDataBuilder.setIncludeDeviceName(true) - .addServiceData(uuid, serviceData).build(); - data.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - AdvertiseData dataFromParcel = - AdvertiseData.CREATOR.createFromParcel(parcel); - assertEquals(data, dataFromParcel); - } - - @SmallTest - public void testServiceUuid() { - Parcel parcel = Parcel.obtain(); - ParcelUuid uuid = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB"); - ParcelUuid uuid2 = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB"); - - AdvertiseData data = - mAdvertiseDataBuilder.setIncludeDeviceName(true) - .addServiceUuid(uuid).addServiceUuid(uuid2).build(); - data.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - AdvertiseData dataFromParcel = - AdvertiseData.CREATOR.createFromParcel(parcel); - assertEquals(data, dataFromParcel); - } - - @SmallTest - public void testManufacturerData() { - Parcel parcel = Parcel.obtain(); - ParcelUuid uuid = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB"); - ParcelUuid uuid2 = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB"); - - int manufacturerId = 50; - byte[] manufacturerData = new byte[] { - (byte) 0xF0, 0x00, 0x02, 0x15 }; - AdvertiseData data = - mAdvertiseDataBuilder.setIncludeDeviceName(true) - .addServiceUuid(uuid).addServiceUuid(uuid2) - .addManufacturerData(manufacturerId, manufacturerData).build(); - - data.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - AdvertiseData dataFromParcel = - AdvertiseData.CREATOR.createFromParcel(parcel); - assertEquals(data, dataFromParcel); - } - - @SmallTest - public void testServiceData() { - Parcel parcel = Parcel.obtain(); - ParcelUuid uuid = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB"); - byte[] serviceData = new byte[] { - (byte) 0xF0, 0x00, 0x02, 0x15 }; - AdvertiseData data = - mAdvertiseDataBuilder.setIncludeDeviceName(true) - .addServiceData(uuid, serviceData).build(); - data.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - AdvertiseData dataFromParcel = - AdvertiseData.CREATOR.createFromParcel(parcel); - assertEquals(data, dataFromParcel); - } -} diff --git a/framework/tests/src/android/bluetooth/le/ScanFilterTest.java b/framework/tests/src/android/bluetooth/le/ScanFilterTest.java deleted file mode 100644 index 35da4bceb6..0000000000 --- a/framework/tests/src/android/bluetooth/le/ScanFilterTest.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bluetooth.le; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.le.ScanFilter; -import android.bluetooth.le.ScanRecord; -import android.os.Parcel; -import android.os.ParcelUuid; -import android.test.suitebuilder.annotation.SmallTest; - -import junit.framework.TestCase; - -/** - * Unit test cases for Bluetooth LE scan filters. - * <p> - * To run this test, use adb shell am instrument -e class 'android.bluetooth.ScanFilterTest' -w - * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner' - */ -public class ScanFilterTest extends TestCase { - - private static final String DEVICE_MAC = "01:02:03:04:05:AB"; - private ScanResult mScanResult; - private ScanFilter.Builder mFilterBuilder; - - @Override - protected void setUp() throws Exception { - byte[] scanRecord = new byte[] { - 0x02, 0x01, 0x1a, // advertising flags - 0x05, 0x02, 0x0b, 0x11, 0x0a, 0x11, // 16 bit service uuids - 0x04, 0x09, 0x50, 0x65, 0x64, // setName - 0x02, 0x0A, (byte) 0xec, // tx power level - 0x05, 0x16, 0x0b, 0x11, 0x50, 0x64, // service data - 0x05, (byte) 0xff, (byte) 0xe0, 0x00, 0x02, 0x15, // manufacturer specific data - 0x03, 0x50, 0x01, 0x02, // an unknown data type won't cause trouble - }; - - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - BluetoothDevice device = adapter.getRemoteDevice(DEVICE_MAC); - mScanResult = new ScanResult(device, ScanRecord.parseFromBytes(scanRecord), - -10, 1397545200000000L); - mFilterBuilder = new ScanFilter.Builder(); - } - - @SmallTest - public void testsetNameFilter() { - ScanFilter filter = mFilterBuilder.setDeviceName("Ped").build(); - assertTrue("setName filter fails", filter.matches(mScanResult)); - - filter = mFilterBuilder.setDeviceName("Pem").build(); - assertFalse("setName filter fails", filter.matches(mScanResult)); - - } - - @SmallTest - public void testDeviceFilter() { - ScanFilter filter = mFilterBuilder.setDeviceAddress(DEVICE_MAC).build(); - assertTrue("device filter fails", filter.matches(mScanResult)); - - filter = mFilterBuilder.setDeviceAddress("11:22:33:44:55:66").build(); - assertFalse("device filter fails", filter.matches(mScanResult)); - } - - @SmallTest - public void testsetServiceUuidFilter() { - ScanFilter filter = mFilterBuilder.setServiceUuid( - ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB")).build(); - assertTrue("uuid filter fails", filter.matches(mScanResult)); - - filter = mFilterBuilder.setServiceUuid( - ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB")).build(); - assertFalse("uuid filter fails", filter.matches(mScanResult)); - - filter = mFilterBuilder - .setServiceUuid(ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB"), - ParcelUuid.fromString("FFFFFFF0-FFFF-FFFF-FFFF-FFFFFFFFFFFF")) - .build(); - assertTrue("uuid filter fails", filter.matches(mScanResult)); - } - - @SmallTest - public void testsetServiceDataFilter() { - byte[] setServiceData = new byte[] { - 0x50, 0x64 }; - ParcelUuid serviceDataUuid = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB"); - ScanFilter filter = mFilterBuilder.setServiceData(serviceDataUuid, setServiceData).build(); - assertTrue("service data filter fails", filter.matches(mScanResult)); - - byte[] emptyData = new byte[0]; - filter = mFilterBuilder.setServiceData(serviceDataUuid, emptyData).build(); - assertTrue("service data filter fails", filter.matches(mScanResult)); - - byte[] prefixData = new byte[] { - 0x50 }; - filter = mFilterBuilder.setServiceData(serviceDataUuid, prefixData).build(); - assertTrue("service data filter fails", filter.matches(mScanResult)); - - byte[] nonMatchData = new byte[] { - 0x51, 0x64 }; - byte[] mask = new byte[] { - (byte) 0x00, (byte) 0xFF }; - filter = mFilterBuilder.setServiceData(serviceDataUuid, nonMatchData, mask).build(); - assertTrue("partial service data filter fails", filter.matches(mScanResult)); - - filter = mFilterBuilder.setServiceData(serviceDataUuid, nonMatchData).build(); - assertFalse("service data filter fails", filter.matches(mScanResult)); - } - - @SmallTest - public void testManufacturerSpecificData() { - byte[] setManufacturerData = new byte[] { - 0x02, 0x15 }; - int manufacturerId = 0xE0; - ScanFilter filter = - mFilterBuilder.setManufacturerData(manufacturerId, setManufacturerData).build(); - assertTrue("manufacturer data filter fails", filter.matches(mScanResult)); - - byte[] emptyData = new byte[0]; - filter = mFilterBuilder.setManufacturerData(manufacturerId, emptyData).build(); - assertTrue("manufacturer data filter fails", filter.matches(mScanResult)); - - byte[] prefixData = new byte[] { - 0x02 }; - filter = mFilterBuilder.setManufacturerData(manufacturerId, prefixData).build(); - assertTrue("manufacturer data filter fails", filter.matches(mScanResult)); - - // Test data mask - byte[] nonMatchData = new byte[] { - 0x02, 0x14 }; - filter = mFilterBuilder.setManufacturerData(manufacturerId, nonMatchData).build(); - assertFalse("manufacturer data filter fails", filter.matches(mScanResult)); - byte[] mask = new byte[] { - (byte) 0xFF, (byte) 0x00 - }; - filter = mFilterBuilder.setManufacturerData(manufacturerId, nonMatchData, mask).build(); - assertTrue("partial setManufacturerData filter fails", filter.matches(mScanResult)); - } - - @SmallTest - public void testReadWriteParcel() { - ScanFilter filter = mFilterBuilder.build(); - testReadWriteParcelForFilter(filter); - - filter = mFilterBuilder.setDeviceName("Ped").build(); - testReadWriteParcelForFilter(filter); - - filter = mFilterBuilder.setDeviceAddress("11:22:33:44:55:66").build(); - testReadWriteParcelForFilter(filter); - - filter = mFilterBuilder.setServiceUuid( - ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB")).build(); - testReadWriteParcelForFilter(filter); - - filter = mFilterBuilder.setServiceUuid( - ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB"), - ParcelUuid.fromString("FFFFFFF0-FFFF-FFFF-FFFF-FFFFFFFFFFFF")).build(); - testReadWriteParcelForFilter(filter); - - byte[] serviceData = new byte[] { - 0x50, 0x64 }; - - ParcelUuid serviceDataUuid = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB"); - filter = mFilterBuilder.setServiceData(serviceDataUuid, serviceData).build(); - testReadWriteParcelForFilter(filter); - - filter = mFilterBuilder.setServiceData(serviceDataUuid, new byte[0]).build(); - testReadWriteParcelForFilter(filter); - - byte[] serviceDataMask = new byte[] { - (byte) 0xFF, (byte) 0xFF }; - filter = mFilterBuilder.setServiceData(serviceDataUuid, serviceData, serviceDataMask) - .build(); - testReadWriteParcelForFilter(filter); - - byte[] manufacturerData = new byte[] { - 0x02, 0x15 }; - int manufacturerId = 0xE0; - filter = mFilterBuilder.setManufacturerData(manufacturerId, manufacturerData).build(); - testReadWriteParcelForFilter(filter); - - filter = mFilterBuilder.setServiceData(serviceDataUuid, new byte[0]).build(); - testReadWriteParcelForFilter(filter); - - byte[] manufacturerDataMask = new byte[] { - (byte) 0xFF, (byte) 0xFF - }; - filter = mFilterBuilder.setManufacturerData(manufacturerId, manufacturerData, - manufacturerDataMask).build(); - testReadWriteParcelForFilter(filter); - } - - private void testReadWriteParcelForFilter(ScanFilter filter) { - Parcel parcel = Parcel.obtain(); - filter.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - ScanFilter filterFromParcel = - ScanFilter.CREATOR.createFromParcel(parcel); - assertEquals(filter, filterFromParcel); - } -} diff --git a/framework/tests/src/android/bluetooth/le/ScanResultTest.java b/framework/tests/src/android/bluetooth/le/ScanResultTest.java deleted file mode 100644 index 01d5c593bf..0000000000 --- a/framework/tests/src/android/bluetooth/le/ScanResultTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bluetooth.le; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.os.Parcel; -import android.test.suitebuilder.annotation.SmallTest; - -import junit.framework.TestCase; - -/** - * Unit test cases for Bluetooth LE scans. - * <p> - * To run this test, use adb shell am instrument -e class 'android.bluetooth.ScanResultTest' -w - * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner' - */ -public class ScanResultTest extends TestCase { - - /** - * Test read and write parcel of ScanResult - */ - @SmallTest - public void testScanResultParceling() { - BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice( - "01:02:03:04:05:06"); - byte[] scanRecord = new byte[] { - 1, 2, 3 }; - int rssi = -10; - long timestampMicros = 10000L; - - ScanResult result = new ScanResult(device, ScanRecord.parseFromBytes(scanRecord), rssi, - timestampMicros); - Parcel parcel = Parcel.obtain(); - result.writeToParcel(parcel, 0); - // Need to reset parcel data position to the beginning. - parcel.setDataPosition(0); - ScanResult resultFromParcel = ScanResult.CREATOR.createFromParcel(parcel); - assertEquals(result, resultFromParcel); - } - -} diff --git a/framework/tests/Android.bp b/framework/tests/stress/Android.bp index efec1dd521..f176be001c 100644 --- a/framework/tests/Android.bp +++ b/framework/tests/stress/Android.bp @@ -21,11 +21,12 @@ android_test { "android.test.base", ], static_libs: [ + "androidx.test.rules", "junit", "modules-utils-bytesmatcher", ], test_suites: [ "general-tests", - "mts-bluetooth", ], + certificate: ":com.android.bluetooth.certificate", } diff --git a/framework/tests/AndroidManifest.xml b/framework/tests/stress/AndroidManifest.xml index 75583d5298..e71b8763ec 100644 --- a/framework/tests/AndroidManifest.xml +++ b/framework/tests/stress/AndroidManifest.xml @@ -44,4 +44,4 @@ android:targetPackage="com.android.bluetooth.tests" android:label="Bluetooth Test Utils" /> -</manifest> +</manifest>
\ No newline at end of file diff --git a/framework/tests/AndroidTest.xml b/framework/tests/stress/AndroidTest.xml index ed89c16ece..f93c4ebf5b 100644 --- a/framework/tests/AndroidTest.xml +++ b/framework/tests/stress/AndroidTest.xml @@ -29,10 +29,4 @@ <option name="hidden-api-checks" value="false"/> <option name="runner" value="android.bluetooth.BluetoothTestRunner"/> </test> - - <!-- Only run BluetoothTests in MTS if the Bluetooth Mainline module is installed. --> - <object type="module_controller" - class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.google.android.bluetooth" /> - </object> </configuration> diff --git a/framework/tests/src/android/bluetooth/BluetoothInstrumentation.java b/framework/tests/stress/src/android/bluetooth/BluetoothInstrumentation.java index 37b2a50ed6..f438592a19 100644 --- a/framework/tests/src/android/bluetooth/BluetoothInstrumentation.java +++ b/framework/tests/stress/src/android/bluetooth/BluetoothInstrumentation.java @@ -20,8 +20,6 @@ import android.app.Instrumentation; import android.content.Context; import android.os.Bundle; -import junit.framework.Assert; - import java.util.Set; public class BluetoothInstrumentation extends Instrumentation { @@ -41,7 +39,7 @@ public class BluetoothInstrumentation extends Instrumentation { private BluetoothAdapter getBluetoothAdapter() { if (mAdapter == null) { - mAdapter = ((BluetoothManager)getContext().getSystemService( + mAdapter = ((BluetoothManager) getContext().getSystemService( Context.BLUETOOTH_SERVICE)).getAdapter(); } return mAdapter; diff --git a/framework/tests/src/android/bluetooth/BluetoothRebootStressTest.java b/framework/tests/stress/src/android/bluetooth/BluetoothRebootStressTest.java index 33e9dd7fab..33e9dd7fab 100644 --- a/framework/tests/src/android/bluetooth/BluetoothRebootStressTest.java +++ b/framework/tests/stress/src/android/bluetooth/BluetoothRebootStressTest.java diff --git a/framework/tests/src/android/bluetooth/BluetoothStressTest.java b/framework/tests/stress/src/android/bluetooth/BluetoothStressTest.java index 89dbe3f75b..89dbe3f75b 100644 --- a/framework/tests/src/android/bluetooth/BluetoothStressTest.java +++ b/framework/tests/stress/src/android/bluetooth/BluetoothStressTest.java diff --git a/framework/tests/src/android/bluetooth/BluetoothTestRunner.java b/framework/tests/stress/src/android/bluetooth/BluetoothTestRunner.java index d19c2c3e7e..905d6baf5b 100644 --- a/framework/tests/src/android/bluetooth/BluetoothTestRunner.java +++ b/framework/tests/stress/src/android/bluetooth/BluetoothTestRunner.java @@ -16,13 +16,13 @@ package android.bluetooth; -import junit.framework.TestSuite; - import android.os.Bundle; import android.test.InstrumentationTestRunner; import android.test.InstrumentationTestSuite; import android.util.Log; +import junit.framework.TestSuite; + /** * Instrumentation test runner for Bluetooth tests. * <p> diff --git a/framework/tests/src/android/bluetooth/BluetoothTestUtils.java b/framework/tests/stress/src/android/bluetooth/BluetoothTestUtils.java index 12183f8f02..41e1cd51a2 100644 --- a/framework/tests/src/android/bluetooth/BluetoothTestUtils.java +++ b/framework/tests/stress/src/android/bluetooth/BluetoothTestUtils.java @@ -16,8 +16,6 @@ package android.bluetooth; -import android.bluetooth.BluetoothPan; -import android.bluetooth.BluetoothProfile; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -69,7 +67,7 @@ public class BluetoothTestUtils extends Assert { private int mFiredFlags = 0; private long mCompletedTime = -1; - public FlagReceiver(int expectedFlags) { + FlagReceiver(int expectedFlags) { mExpectedFlags = expectedFlags; } @@ -108,7 +106,7 @@ public class BluetoothTestUtils extends Assert { private static final int STATE_GET_MESSAGE_FINISHED_FLAG = 1 << 9; private static final int STATE_SET_MESSAGE_STATUS_FINISHED_FLAG = 1 << 10; - public BluetoothReceiver(int expectedFlags) { + BluetoothReceiver(int expectedFlags) { super(expectedFlags); } @@ -162,7 +160,7 @@ public class BluetoothTestUtils extends Assert { private int mPasskey; private byte[] mPin; - public PairReceiver(BluetoothDevice device, int passkey, byte[] pin, int expectedFlags) { + PairReceiver(BluetoothDevice device, int passkey, byte[] pin, int expectedFlags) { super(expectedFlags); mDevice = device; @@ -221,7 +219,7 @@ public class BluetoothTestUtils extends Assert { private int mProfile; private String mConnectionAction; - public ConnectProfileReceiver(BluetoothDevice device, int profile, int expectedFlags) { + ConnectProfileReceiver(BluetoothDevice device, int profile, int expectedFlags) { super(expectedFlags); mDevice = device; @@ -278,7 +276,7 @@ public class BluetoothTestUtils extends Assert { private class ConnectPanReceiver extends ConnectProfileReceiver { private int mRole; - public ConnectPanReceiver(BluetoothDevice device, int role, int expectedFlags) { + ConnectPanReceiver(BluetoothDevice device, int role, int expectedFlags) { super(device, BluetoothProfile.PAN, expectedFlags); mRole = role; @@ -298,7 +296,7 @@ public class BluetoothTestUtils extends Assert { private static final int STATE_CONNECTED_FLAG = 1; private static final int STATE_DISCONNECTED_FLAG = 1 << 1; - public StartStopScoReceiver(int expectedFlags) { + StartStopScoReceiver(int expectedFlags) { super(expectedFlags); } @@ -325,7 +323,7 @@ public class BluetoothTestUtils extends Assert { private static final int MESSAGE_RECEIVED_FLAG = 1; private static final int STATUS_CHANGED_FLAG = 1 << 1; - public MceSetMessageStatusReceiver(int expectedFlags) { + MceSetMessageStatusReceiver(int expectedFlags) { super(expectedFlags); } @@ -336,12 +334,16 @@ public class BluetoothTestUtils extends Assert { assertNotNull(handle); setFiredFlag(MESSAGE_RECEIVED_FLAG); mMsgHandle = handle; - } else if (BluetoothMapClient.ACTION_MESSAGE_DELETED_STATUS_CHANGED.equals(intent.getAction())) { - int result = intent.getIntExtra(BluetoothMapClient.EXTRA_RESULT_CODE, BluetoothMapClient.RESULT_FAILURE); + } else if (BluetoothMapClient.ACTION_MESSAGE_DELETED_STATUS_CHANGED + .equals(intent.getAction())) { + int result = intent.getIntExtra(BluetoothMapClient.EXTRA_RESULT_CODE, + BluetoothMapClient.RESULT_FAILURE); assertEquals(result, BluetoothMapClient.RESULT_SUCCESS); setFiredFlag(STATUS_CHANGED_FLAG); - } else if (BluetoothMapClient.ACTION_MESSAGE_READ_STATUS_CHANGED.equals(intent.getAction())) { - int result = intent.getIntExtra(BluetoothMapClient.EXTRA_RESULT_CODE, BluetoothMapClient.RESULT_FAILURE); + } else if (BluetoothMapClient.ACTION_MESSAGE_READ_STATUS_CHANGED + .equals(intent.getAction())) { + int result = intent.getIntExtra(BluetoothMapClient.EXTRA_RESULT_CODE, + BluetoothMapClient.RESULT_FAILURE); assertEquals(result, BluetoothMapClient.RESULT_SUCCESS); setFiredFlag(STATUS_CHANGED_FLAG); } @@ -1001,13 +1003,13 @@ public class BluetoothTestUtils extends Assert { case BluetoothProfile.STATE_DISCONNECTING: start = System.currentTimeMillis(); if (profile == BluetoothProfile.A2DP) { - assertTrue(((BluetoothA2dp)proxy).connect(device)); + assertTrue(((BluetoothA2dp) proxy).connect(device)); } else if (profile == BluetoothProfile.HEADSET) { - assertTrue(((BluetoothHeadset)proxy).connect(device)); + assertTrue(((BluetoothHeadset) proxy).connect(device)); } else if (profile == BluetoothProfile.HID_HOST) { - assertTrue(((BluetoothHidHost)proxy).connect(device)); + assertTrue(((BluetoothHidHost) proxy).connect(device)); } else if (profile == BluetoothProfile.MAP_CLIENT) { - assertTrue(((BluetoothMapClient)proxy).connect(device)); + assertTrue(((BluetoothMapClient) proxy).connect(device)); } break; default: @@ -1078,13 +1080,13 @@ public class BluetoothTestUtils extends Assert { case BluetoothProfile.STATE_CONNECTING: start = System.currentTimeMillis(); if (profile == BluetoothProfile.A2DP) { - assertTrue(((BluetoothA2dp)proxy).disconnect(device)); + assertTrue(((BluetoothA2dp) proxy).disconnect(device)); } else if (profile == BluetoothProfile.HEADSET) { - assertTrue(((BluetoothHeadset)proxy).disconnect(device)); + assertTrue(((BluetoothHeadset) proxy).disconnect(device)); } else if (profile == BluetoothProfile.HID_HOST) { - assertTrue(((BluetoothHidHost)proxy).disconnect(device)); + assertTrue(((BluetoothHidHost) proxy).disconnect(device)); } else if (profile == BluetoothProfile.MAP_CLIENT) { - assertTrue(((BluetoothMapClient)proxy).disconnect(device)); + assertTrue(((BluetoothMapClient) proxy).disconnect(device)); } break; case BluetoothProfile.STATE_DISCONNECTED: @@ -1161,8 +1163,8 @@ public class BluetoothTestUtils extends Assert { if (connect) { methodName = String.format("connectPan(device=%s)", device); - mask = (ConnectProfileReceiver.STATE_CONNECTED_FLAG | - ConnectProfileReceiver.STATE_CONNECTING_FLAG); + mask = (ConnectProfileReceiver.STATE_CONNECTED_FLAG + | ConnectProfileReceiver.STATE_CONNECTING_FLAG); role = BluetoothPan.LOCAL_PANU_ROLE; } else { methodName = String.format("incomingPanConnection(device=%s)", device); @@ -1266,8 +1268,8 @@ public class BluetoothTestUtils extends Assert { if (disconnect) { methodName = String.format("disconnectPan(device=%s)", device); - mask = (ConnectProfileReceiver.STATE_DISCONNECTED_FLAG | - ConnectProfileReceiver.STATE_DISCONNECTING_FLAG); + mask = (ConnectProfileReceiver.STATE_DISCONNECTED_FLAG + | ConnectProfileReceiver.STATE_DISCONNECTING_FLAG); role = BluetoothPan.LOCAL_PANU_ROLE; } else { methodName = String.format("incomingPanDisconnection(device=%s)", device); @@ -1478,7 +1480,8 @@ public class BluetoothTestUtils extends Assert { int firedFlags = receiver.getFiredFlags(); removeReceiver(receiver); fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%s)", - methodName, mMce.getConnectionState(device), BluetoothMapClient.STATE_CONNECTED, firedFlags, mask)); + methodName, mMce.getConnectionState(device), BluetoothMapClient.STATE_CONNECTED, + firedFlags, mask)); } /** @@ -1522,7 +1525,8 @@ public class BluetoothTestUtils extends Assert { int firedFlags = receiver.getFiredFlags(); removeReceiver(receiver); fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%s)", - methodName, mMce.getConnectionState(device), BluetoothPan.STATE_CONNECTED, firedFlags, mask)); + methodName, mMce.getConnectionState(device), BluetoothPan.STATE_CONNECTED, + firedFlags, mask)); } private void addReceiver(BroadcastReceiver receiver, String[] actions) { @@ -1619,6 +1623,7 @@ public class BluetoothTestUtils extends Assert { if (mPan != null) { return mPan; } + break; case BluetoothProfile.MAP_CLIENT: if (mMce != null) { return mMce; diff --git a/framework/tests/unit/Android.bp b/framework/tests/unit/Android.bp new file mode 100644 index 0000000000..7791102395 --- /dev/null +++ b/framework/tests/unit/Android.bp @@ -0,0 +1,33 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +android_test { + name: "FrameworkBluetoothTests", + + defaults: ["framework-bluetooth-tests-defaults"], + + min_sdk_version: "current", + target_sdk_version: "current", + + // Include all test java files. + srcs: ["src/**/*.java"], + jacoco: { + include_filter: ["android.bluetooth.*"], + exclude_filter: [], + }, + libs: [ + "android.test.runner", + "android.test.base", + ], + static_libs: [ + "androidx.test.rules", + "junit", + "modules-utils-bytesmatcher", + ], + test_suites: [ + "general-tests", + "mts-bluetooth", + ], + certificate: ":com.android.bluetooth.certificate", +} diff --git a/framework/tests/unit/AndroidManifest.xml b/framework/tests/unit/AndroidManifest.xml new file mode 100644 index 0000000000..114ceeb9be --- /dev/null +++ b/framework/tests/unit/AndroidManifest.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.framework.bluetooth.tests"> + + <application > + <uses-library android:name="android.test.runner" /> + </application> + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.bluetooth" + android:label="Framework Bluetooth Tests"/> +</manifest> diff --git a/framework/tests/unit/AndroidTest.xml b/framework/tests/unit/AndroidTest.xml new file mode 100644 index 0000000000..b8ca07a289 --- /dev/null +++ b/framework/tests/unit/AndroidTest.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<configuration description="Config for Bluetooth test cases"> + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="cleanup-apks" value="true" /> + <option name="test-file-name" value="FrameworkBluetoothTests.apk" /> + </target_preparer> + + <option name="test-suite-tag" value="apct"/> + <option name="test-tag" value="FrameworkBluetoothTests"/> + + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="com.android.framework.bluetooth.tests" /> + <option name="hidden-api-checks" value="false"/> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/> + </test> + + <!-- Only run FrameworkBluetoothTests in MTS if the Bluetooth Mainline module is installed. --> + <object type="module_controller" + class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> + <option name="mainline-module-package-name" value="com.google.android.bluetooth" /> + </object> +</configuration> diff --git a/framework/tests/src/android/bluetooth/BluetoothCodecConfigTest.java b/framework/tests/unit/src/android/bluetooth/BluetoothCodecConfigTest.java index 53623b809c..cb059aeb43 100644 --- a/framework/tests/src/android/bluetooth/BluetoothCodecConfigTest.java +++ b/framework/tests/unit/src/android/bluetooth/BluetoothCodecConfigTest.java @@ -22,161 +22,160 @@ import junit.framework.TestCase; /** * Unit test cases for {@link BluetoothCodecConfig}. - * <p> - * To run this test, use: - * runtest --path core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java */ public class BluetoothCodecConfigTest extends TestCase { - private static final int[] kCodecTypeArray = new int[] { - BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, - BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, - BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, - BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, - BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, - BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3, - BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID, - }; - private static final int[] kCodecPriorityArray = new int[] { - BluetoothCodecConfig.CODEC_PRIORITY_DISABLED, - BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, - BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST, - }; - private static final int[] kSampleRateArray = new int[] { - BluetoothCodecConfig.SAMPLE_RATE_NONE, - BluetoothCodecConfig.SAMPLE_RATE_44100, - BluetoothCodecConfig.SAMPLE_RATE_48000, - BluetoothCodecConfig.SAMPLE_RATE_88200, - BluetoothCodecConfig.SAMPLE_RATE_96000, - BluetoothCodecConfig.SAMPLE_RATE_176400, - BluetoothCodecConfig.SAMPLE_RATE_192000, - }; - private static final int[] kBitsPerSampleArray = new int[] { - BluetoothCodecConfig.BITS_PER_SAMPLE_NONE, - BluetoothCodecConfig.BITS_PER_SAMPLE_16, - BluetoothCodecConfig.BITS_PER_SAMPLE_24, - BluetoothCodecConfig.BITS_PER_SAMPLE_32, - }; - private static final int[] kChannelModeArray = new int[] { - BluetoothCodecConfig.CHANNEL_MODE_NONE, - BluetoothCodecConfig.CHANNEL_MODE_MONO, - BluetoothCodecConfig.CHANNEL_MODE_STEREO, - }; - private static final long[] kCodecSpecific1Array = new long[] { - 1000, - 1001, - 1002, - 1003, - }; - private static final long[] kCodecSpecific2Array = new long[] { - 2000, - 2001, - 2002, - 2003, - }; - private static final long[] kCodecSpecific3Array = new long[] { - 3000, - 3001, - 3002, - 3003, - }; - private static final long[] kCodecSpecific4Array = new long[] { - 4000, - 4001, - 4002, - 4003, - }; - - private static final int kTotalConfigs = kCodecTypeArray.length * kCodecPriorityArray.length - * kSampleRateArray.length * kBitsPerSampleArray.length * kChannelModeArray.length - * kCodecSpecific1Array.length * kCodecSpecific2Array.length * kCodecSpecific3Array.length - * kCodecSpecific4Array.length; - - private int selectCodecType(int configId) { - int left = kCodecTypeArray.length; - int right = kTotalConfigs / left; - int index = configId / right; - index = index % kCodecTypeArray.length; - return kCodecTypeArray[index]; - } + private static final int[] sCodecTypeArray = new int[] { + BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, + BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, + BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, + BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, + BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, + BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3, + BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID, + }; + private static final int[] sCodecPriorityArray = new int[] { + BluetoothCodecConfig.CODEC_PRIORITY_DISABLED, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST, + }; + private static final int[] sSampleRateArray = new int[] { + BluetoothCodecConfig.SAMPLE_RATE_NONE, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.SAMPLE_RATE_48000, + BluetoothCodecConfig.SAMPLE_RATE_88200, + BluetoothCodecConfig.SAMPLE_RATE_96000, + BluetoothCodecConfig.SAMPLE_RATE_176400, + BluetoothCodecConfig.SAMPLE_RATE_192000, + }; + private static final int[] sBitsPerSampleArray = new int[] { + BluetoothCodecConfig.BITS_PER_SAMPLE_NONE, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.BITS_PER_SAMPLE_24, + BluetoothCodecConfig.BITS_PER_SAMPLE_32, + }; + private static final int[] sChannelModeArray = new int[] { + BluetoothCodecConfig.CHANNEL_MODE_NONE, + BluetoothCodecConfig.CHANNEL_MODE_MONO, + BluetoothCodecConfig.CHANNEL_MODE_STEREO, + }; + private static final long[] sCodecSpecific1Array = new long[] { + 1000, + 1001, + 1002, + 1003, + }; + private static final long[] sCodecSpecific2Array = new long[] { + 2000, + 2001, + 2002, + 2003, + }; + private static final long[] sCodecSpecific3Array = new long[] { + 3000, + 3001, + 3002, + 3003, + }; + private static final long[] sCodecSpecific4Array = new long[] { + 4000, + 4001, + 4002, + 4003, + }; + + private static final int sTotalConfigs = sCodecTypeArray.length * sCodecPriorityArray.length + * sSampleRateArray.length * sBitsPerSampleArray.length * sChannelModeArray.length + * sCodecSpecific1Array.length * sCodecSpecific2Array.length + * sCodecSpecific3Array.length * sCodecSpecific4Array.length; + + private int selectCodecType(int configId) { + int left = sCodecTypeArray.length; + int right = sTotalConfigs / left; + int index = configId / right; + index = index % sCodecTypeArray.length; + return sCodecTypeArray[index]; + } private int selectCodecPriority(int configId) { - int left = kCodecTypeArray.length * kCodecPriorityArray.length; - int right = kTotalConfigs / left; + int left = sCodecTypeArray.length * sCodecPriorityArray.length; + int right = sTotalConfigs / left; int index = configId / right; - index = index % kCodecPriorityArray.length; - return kCodecPriorityArray[index]; + index = index % sCodecPriorityArray.length; + return sCodecPriorityArray[index]; } private int selectSampleRate(int configId) { - int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length; - int right = kTotalConfigs / left; + int left = sCodecTypeArray.length * sCodecPriorityArray.length * sSampleRateArray.length; + int right = sTotalConfigs / left; int index = configId / right; - index = index % kSampleRateArray.length; - return kSampleRateArray[index]; + index = index % sSampleRateArray.length; + return sSampleRateArray[index]; } private int selectBitsPerSample(int configId) { - int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length * - kBitsPerSampleArray.length; - int right = kTotalConfigs / left; + int left = sCodecTypeArray.length * sCodecPriorityArray.length * sSampleRateArray.length + * sBitsPerSampleArray.length; + int right = sTotalConfigs / left; int index = configId / right; - index = index % kBitsPerSampleArray.length; - return kBitsPerSampleArray[index]; + index = index % sBitsPerSampleArray.length; + return sBitsPerSampleArray[index]; } private int selectChannelMode(int configId) { - int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length * - kBitsPerSampleArray.length * kChannelModeArray.length; - int right = kTotalConfigs / left; + int left = sCodecTypeArray.length * sCodecPriorityArray.length * sSampleRateArray.length + * sBitsPerSampleArray.length * sChannelModeArray.length; + int right = sTotalConfigs / left; int index = configId / right; - index = index % kChannelModeArray.length; - return kChannelModeArray[index]; + index = index % sChannelModeArray.length; + return sChannelModeArray[index]; } private long selectCodecSpecific1(int configId) { - int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length * - kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length; - int right = kTotalConfigs / left; + int left = sCodecTypeArray.length * sCodecPriorityArray.length * sSampleRateArray.length + * sBitsPerSampleArray.length * sChannelModeArray.length + * sCodecSpecific1Array.length; + int right = sTotalConfigs / left; int index = configId / right; - index = index % kCodecSpecific1Array.length; - return kCodecSpecific1Array[index]; + index = index % sCodecSpecific1Array.length; + return sCodecSpecific1Array[index]; } private long selectCodecSpecific2(int configId) { - int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length * - kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length * - kCodecSpecific2Array.length; - int right = kTotalConfigs / left; + int left = sCodecTypeArray.length * sCodecPriorityArray.length * sSampleRateArray.length + * sBitsPerSampleArray.length * sChannelModeArray.length + * sCodecSpecific1Array.length * sCodecSpecific2Array.length; + int right = sTotalConfigs / left; int index = configId / right; - index = index % kCodecSpecific2Array.length; - return kCodecSpecific2Array[index]; + index = index % sCodecSpecific2Array.length; + return sCodecSpecific2Array[index]; } private long selectCodecSpecific3(int configId) { - int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length * - kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length * - kCodecSpecific2Array.length * kCodecSpecific3Array.length; - int right = kTotalConfigs / left; + int left = sCodecTypeArray.length * sCodecPriorityArray.length * sSampleRateArray.length + * sBitsPerSampleArray.length * sChannelModeArray.length + * sCodecSpecific1Array.length * sCodecSpecific2Array.length + * sCodecSpecific3Array.length; + int right = sTotalConfigs / left; int index = configId / right; - index = index % kCodecSpecific3Array.length; - return kCodecSpecific3Array[index]; + index = index % sCodecSpecific3Array.length; + return sCodecSpecific3Array[index]; } private long selectCodecSpecific4(int configId) { - int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length * - kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length * - kCodecSpecific2Array.length * kCodecSpecific3Array.length * - kCodecSpecific4Array.length; - int right = kTotalConfigs / left; + int left = sCodecTypeArray.length * sCodecPriorityArray.length * sSampleRateArray.length + * sBitsPerSampleArray.length * sChannelModeArray.length + * sCodecSpecific1Array.length * sCodecSpecific2Array.length + * sCodecSpecific3Array.length * sCodecSpecific4Array.length; + int right = sTotalConfigs / left; int index = configId / right; - index = index % kCodecSpecific4Array.length; - return kCodecSpecific4Array[index]; + index = index % sCodecSpecific4Array.length; + return sCodecSpecific4Array[index]; } @SmallTest public void testBluetoothCodecConfig_valid_get_methods() { - for (int config_id = 0; config_id < kTotalConfigs; config_id++) { + for (int config_id = 0; config_id < sTotalConfigs; config_id++) { int codec_type = selectCodecType(config_id); int codec_priority = selectCodecPriority(config_id); int sample_rate = selectSampleRate(config_id); diff --git a/framework/tests/unit/src/android/bluetooth/BluetoothCodecStatusTest.java b/framework/tests/unit/src/android/bluetooth/BluetoothCodecStatusTest.java new file mode 100644 index 0000000000..9c6674e136 --- /dev/null +++ b/framework/tests/unit/src/android/bluetooth/BluetoothCodecStatusTest.java @@ -0,0 +1,490 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; + +import android.test.suitebuilder.annotation.SmallTest; + +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Unit test cases for {@link BluetoothCodecStatus}. + */ +public class BluetoothCodecStatusTest extends TestCase { + + // Codec configs: A and B are same; C is different + private static final BluetoothCodecConfig CONFIG_A = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig CONFIG_B = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig CONFIG_C = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO, + 1000, 2000, 3000, 4000); + + // Local capabilities: A and B are same; C is different + private static final BluetoothCodecConfig LOCAL_CAPABILITY_1_A = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig LOCAL_CAPABILITY_1_B = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig LOCAL_CAPABILITY_1_C = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO, + 1000, 2000, 3000, 4000); + + + private static final BluetoothCodecConfig LOCAL_CAPABILITY_2_A = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig LOCAL_CAPABILITY_2_B = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig LOCAL_CAPABILITY_2_C = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig LOCAL_CAPABILITY_3_A = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig LOCAL_CAPABILITY_3_B = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig LOCAL_CAPABILITY_3_C = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig LOCAL_CAPABILITY_4_A = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000, + BluetoothCodecConfig.BITS_PER_SAMPLE_24, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig LOCAL_CAPABILITY_4_B = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000, + BluetoothCodecConfig.BITS_PER_SAMPLE_24, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig LOCAL_CAPABILITY_4_C = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000, + BluetoothCodecConfig.BITS_PER_SAMPLE_24, + BluetoothCodecConfig.CHANNEL_MODE_STEREO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig LOCAL_CAPABILITY_5_A = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000 + | BluetoothCodecConfig.SAMPLE_RATE_88200 + | BluetoothCodecConfig.SAMPLE_RATE_96000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16 + | BluetoothCodecConfig.BITS_PER_SAMPLE_24 + | BluetoothCodecConfig.BITS_PER_SAMPLE_32, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig LOCAL_CAPABILITY_5_B = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000 + | BluetoothCodecConfig.SAMPLE_RATE_88200 + | BluetoothCodecConfig.SAMPLE_RATE_96000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16 + | BluetoothCodecConfig.BITS_PER_SAMPLE_24 + | BluetoothCodecConfig.BITS_PER_SAMPLE_32, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig LOCAL_CAPABILITY_5_C = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000 + | BluetoothCodecConfig.SAMPLE_RATE_88200 + | BluetoothCodecConfig.SAMPLE_RATE_96000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16 + | BluetoothCodecConfig.BITS_PER_SAMPLE_24 + | BluetoothCodecConfig.BITS_PER_SAMPLE_32, + BluetoothCodecConfig.CHANNEL_MODE_STEREO, + 1000, 2000, 3000, 4000); + + + // Selectable capabilities: A and B are same; C is different + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_1_A = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_1_B = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_1_C = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_2_A = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_2_B = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_2_C = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_3_A = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_3_B = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_3_C = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_16, + BluetoothCodecConfig.CHANNEL_MODE_STEREO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_4_A = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_24, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_4_B = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_24, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_4_C = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100, + BluetoothCodecConfig.BITS_PER_SAMPLE_24, + BluetoothCodecConfig.CHANNEL_MODE_STEREO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_5_A = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000 + | BluetoothCodecConfig.SAMPLE_RATE_88200 + | BluetoothCodecConfig.SAMPLE_RATE_96000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16 + | BluetoothCodecConfig.BITS_PER_SAMPLE_24 + | BluetoothCodecConfig.BITS_PER_SAMPLE_32, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_5_B = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000 + | BluetoothCodecConfig.SAMPLE_RATE_88200 + | BluetoothCodecConfig.SAMPLE_RATE_96000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16 + | BluetoothCodecConfig.BITS_PER_SAMPLE_24 + | BluetoothCodecConfig.BITS_PER_SAMPLE_32, + BluetoothCodecConfig.CHANNEL_MODE_STEREO + | BluetoothCodecConfig.CHANNEL_MODE_MONO, + 1000, 2000, 3000, 4000); + + private static final BluetoothCodecConfig SELECTABE_CAPABILITY_5_C = + buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, + BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, + BluetoothCodecConfig.SAMPLE_RATE_44100 + | BluetoothCodecConfig.SAMPLE_RATE_48000 + | BluetoothCodecConfig.SAMPLE_RATE_88200 + | BluetoothCodecConfig.SAMPLE_RATE_96000, + BluetoothCodecConfig.BITS_PER_SAMPLE_16 + | BluetoothCodecConfig.BITS_PER_SAMPLE_24 + | BluetoothCodecConfig.BITS_PER_SAMPLE_32, + BluetoothCodecConfig.CHANNEL_MODE_STEREO, + 1000, 2000, 3000, 4000); + + private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_A = + new ArrayList() {{ + add(LOCAL_CAPABILITY_1_A); + add(LOCAL_CAPABILITY_2_A); + add(LOCAL_CAPABILITY_3_A); + add(LOCAL_CAPABILITY_4_A); + add(LOCAL_CAPABILITY_5_A); + }}; + + private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_B = + new ArrayList() {{ + add(LOCAL_CAPABILITY_1_B); + add(LOCAL_CAPABILITY_2_B); + add(LOCAL_CAPABILITY_3_B); + add(LOCAL_CAPABILITY_4_B); + add(LOCAL_CAPABILITY_5_B); + }}; + + private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_B_REORDERED = + new ArrayList() {{ + add(LOCAL_CAPABILITY_5_B); + add(LOCAL_CAPABILITY_4_B); + add(LOCAL_CAPABILITY_2_B); + add(LOCAL_CAPABILITY_3_B); + add(LOCAL_CAPABILITY_1_B); + }}; + + private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_C = + new ArrayList() {{ + add(LOCAL_CAPABILITY_1_C); + add(LOCAL_CAPABILITY_2_C); + add(LOCAL_CAPABILITY_3_C); + add(LOCAL_CAPABILITY_4_C); + add(LOCAL_CAPABILITY_5_C); + }}; + + private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_A = + new ArrayList() {{ + add(SELECTABE_CAPABILITY_1_A); + add(SELECTABE_CAPABILITY_2_A); + add(SELECTABE_CAPABILITY_3_A); + add(SELECTABE_CAPABILITY_4_A); + add(SELECTABE_CAPABILITY_5_A); + }}; + + private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_B = + new ArrayList() {{ + add(SELECTABE_CAPABILITY_1_B); + add(SELECTABE_CAPABILITY_2_B); + add(SELECTABE_CAPABILITY_3_B); + add(SELECTABE_CAPABILITY_4_B); + add(SELECTABE_CAPABILITY_5_B); + }}; + + private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_B_REORDERED = + new ArrayList() {{ + add(SELECTABE_CAPABILITY_5_B); + add(SELECTABE_CAPABILITY_4_B); + add(SELECTABE_CAPABILITY_2_B); + add(SELECTABE_CAPABILITY_3_B); + add(SELECTABE_CAPABILITY_1_B); + }}; + + private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_C = + new ArrayList() {{ + add(SELECTABE_CAPABILITY_1_C); + add(SELECTABE_CAPABILITY_2_C); + add(SELECTABE_CAPABILITY_3_C); + add(SELECTABE_CAPABILITY_4_C); + add(SELECTABE_CAPABILITY_5_C); + }}; + + private static final BluetoothCodecStatus BCS_A = + new BluetoothCodecStatus(CONFIG_A, LOCAL_CAPABILITY_A, SELECTABLE_CAPABILITY_A); + private static final BluetoothCodecStatus BCS_B = + new BluetoothCodecStatus(CONFIG_B, LOCAL_CAPABILITY_B, SELECTABLE_CAPABILITY_B); + private static final BluetoothCodecStatus BCS_B_REORDERED = + new BluetoothCodecStatus(CONFIG_B, LOCAL_CAPABILITY_B_REORDERED, + SELECTABLE_CAPABILITY_B_REORDERED); + private static final BluetoothCodecStatus BCS_C = + new BluetoothCodecStatus(CONFIG_C, LOCAL_CAPABILITY_C, SELECTABLE_CAPABILITY_C); + + @SmallTest + public void testBluetoothCodecStatus_get_methods() { + + assertTrue(Objects.equals(BCS_A.getCodecConfig(), CONFIG_A)); + assertTrue(Objects.equals(BCS_A.getCodecConfig(), CONFIG_B)); + assertFalse(Objects.equals(BCS_A.getCodecConfig(), CONFIG_C)); + + assertTrue(BCS_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_A)); + assertTrue(BCS_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_B)); + assertFalse(BCS_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_C)); + + assertTrue(BCS_A.getCodecsSelectableCapabilities() + .equals(SELECTABLE_CAPABILITY_A)); + assertTrue(BCS_A.getCodecsSelectableCapabilities() + .equals(SELECTABLE_CAPABILITY_B)); + assertFalse(BCS_A.getCodecsSelectableCapabilities() + .equals(SELECTABLE_CAPABILITY_C)); + } + + @SmallTest + public void testBluetoothCodecStatus_equals() { + assertTrue(BCS_A.equals(BCS_B)); + assertTrue(BCS_B.equals(BCS_A)); + assertTrue(BCS_A.equals(BCS_B_REORDERED)); + assertTrue(BCS_B_REORDERED.equals(BCS_A)); + assertFalse(BCS_A.equals(BCS_C)); + assertFalse(BCS_C.equals(BCS_A)); + } + + private static BluetoothCodecConfig buildBluetoothCodecConfig(int sourceCodecType, + int codecPriority, int sampleRate, int bitsPerSample, int channelMode, + long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4) { + return new BluetoothCodecConfig.Builder() + .setCodecType(sourceCodecType) + .setCodecPriority(codecPriority) + .setSampleRate(sampleRate) + .setBitsPerSample(bitsPerSample) + .setChannelMode(channelMode) + .setCodecSpecific1(codecSpecific1) + .setCodecSpecific2(codecSpecific2) + .setCodecSpecific3(codecSpecific3) + .setCodecSpecific4(codecSpecific4) + .build(); + + } +} diff --git a/framework/tests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java b/framework/tests/unit/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java index c3d707cd75..c3d707cd75 100644 --- a/framework/tests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java +++ b/framework/tests/unit/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java diff --git a/framework/tests/src/android/bluetooth/BluetoothUuidTest.java b/framework/tests/unit/src/android/bluetooth/BluetoothUuidTest.java index 536d722679..514a5845f1 100644 --- a/framework/tests/src/android/bluetooth/BluetoothUuidTest.java +++ b/framework/tests/unit/src/android/bluetooth/BluetoothUuidTest.java @@ -23,9 +23,6 @@ import junit.framework.TestCase; /** * Unit test cases for {@link BluetoothUuid}. - * <p> - * To run this test, use adb shell am instrument -e class 'android.bluetooth.BluetoothUuidTest' -w - * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner' */ public class BluetoothUuidTest extends TestCase { diff --git a/framework/tests/src/android/bluetooth/le/ScanRecordTest.java b/framework/tests/unit/src/android/bluetooth/le/ScanRecordTest.java index 76f5615647..b37f80593a 100644 --- a/framework/tests/src/android/bluetooth/le/ScanRecordTest.java +++ b/framework/tests/unit/src/android/bluetooth/le/ScanRecordTest.java @@ -39,15 +39,24 @@ public class ScanRecordTest extends TestCase { /** * Example raw beacons captured from a Blue Charm BC011 */ - private static final String RECORD_URL = "0201060303AAFE1716AAFE10EE01626C7565636861726D626561636F6E730009168020691E0EFE13551109426C7565436861726D5F313639363835000000"; - private static final String RECORD_UUID = "0201060303AAFE1716AAFE00EE626C7565636861726D31000000000001000009168020691E0EFE13551109426C7565436861726D5F313639363835000000"; - private static final String RECORD_TLM = "0201060303AAFE1116AAFE20000BF017000008874803FB93540916802069080EFE13551109426C7565436861726D5F313639363835000000000000000000"; - private static final String RECORD_IBEACON = "0201061AFF4C000215426C7565436861726D426561636F6E730EFE1355C509168020691E0EFE13551109426C7565436861726D5F31363936383500000000"; + private static final String RECORD_URL = + "0201060303AAFE1716AAFE10EE01626C7565636861726D626561636F6E730" + + "009168020691E0EFE13551109426C7565436861726D5F313639363835000000"; + private static final String RECORD_UUID = + "0201060303AAFE1716AAFE00EE626C7565636861726D3100000000000100000" + + "9168020691E0EFE13551109426C7565436861726D5F313639363835000000"; + private static final String RECORD_TLM = + "0201060303AAFE1116AAFE20000BF017000008874803FB93540916802069080" + + "EFE13551109426C7565436861726D5F313639363835000000000000000000"; + private static final String RECORD_IBEACON = + "0201061AFF4C000215426C7565436861726D426561636F6E730EFE1355C5091" + + "68020691E0EFE13551109426C7565436861726D5F31363936383500000000"; /** * Example Eddystone E2EE-EID beacon from design doc */ - private static final String RECORD_E2EE_EID = "0201061816AAFE400000000000000000000000000000000000000000"; + private static final String RECORD_E2EE_EID = + "0201061816AAFE400000000000000000000000000000000000000000"; @SmallTest public void testMatchesAnyField_Eddystone_Parser() { @@ -148,8 +157,8 @@ public class ScanRecordTest extends TestCase { // Assert two byte arrays are equal. private static void assertArrayEquals(byte[] expected, byte[] actual) { if (!Arrays.equals(expected, actual)) { - fail("expected:<" + Arrays.toString(expected) + - "> but was:<" + Arrays.toString(actual) + ">"); + fail("expected:<" + Arrays.toString(expected) + + "> but was:<" + Arrays.toString(actual) + ">"); } } diff --git a/framework/tests/src/android/bluetooth/le/ScanSettingsTest.java b/framework/tests/unit/src/android/bluetooth/le/ScanSettingsTest.java index 7c42c3b467..180c3be419 100644 --- a/framework/tests/src/android/bluetooth/le/ScanSettingsTest.java +++ b/framework/tests/unit/src/android/bluetooth/le/ScanSettingsTest.java @@ -43,8 +43,8 @@ public class ScanSettingsTest extends TestCase { try { builder.setCallbackType( - ScanSettings.CALLBACK_TYPE_ALL_MATCHES | - ScanSettings.CALLBACK_TYPE_FIRST_MATCH); + ScanSettings.CALLBACK_TYPE_ALL_MATCHES + | ScanSettings.CALLBACK_TYPE_FIRST_MATCH); fail("should have thrown IllegalArgumentException!"); } catch (IllegalArgumentException e) { // nothing to do @@ -52,9 +52,9 @@ public class ScanSettingsTest extends TestCase { try { builder.setCallbackType( - ScanSettings.CALLBACK_TYPE_ALL_MATCHES | - ScanSettings.CALLBACK_TYPE_FIRST_MATCH | - ScanSettings.CALLBACK_TYPE_MATCH_LOST); + ScanSettings.CALLBACK_TYPE_ALL_MATCHES + | ScanSettings.CALLBACK_TYPE_FIRST_MATCH + | ScanSettings.CALLBACK_TYPE_MATCH_LOST); fail("should have thrown IllegalArgumentException!"); } catch (IllegalArgumentException e) { // nothing to do diff --git a/service/Android.bp b/service/Android.bp index bee002da7a..2a5e1adef4 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -71,7 +71,7 @@ java_library { ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "Tiramisu" } @@ -104,7 +104,7 @@ java_library { "//packages/modules/Bluetooth/apex", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "Tiramisu" } @@ -123,7 +123,7 @@ java_library { ], sdk_version: "system_server_current", apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "Tiramisu" } diff --git a/service/tests/Android.bp b/service/tests/Android.bp index c26df884bf..3b5e866262 100644 --- a/service/tests/Android.bp +++ b/service/tests/Android.bp @@ -17,18 +17,6 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } -filegroup { - name: "service-bluetooth-tests-sources", - srcs: [ - "src/**/*.java", - ], - visibility: [ - "//frameworks/base", - "//frameworks/base/services", - "//frameworks/base/services/tests/servicestests", - ], -} - android_test { name: "ServiceBluetoothTests", @@ -42,12 +30,8 @@ android_test { static_libs: [ "androidx.test.rules", - "collector-device-lib", - "hamcrest-library", "mockito-target-extended-minus-junit4", "platform-test-annotations", - "frameworks-base-testutils", - "truth-prebuilt", // Statically link service-bluetooth-pre-jarjar since we want to test the working copy of // service-uwb, not the on-device copy. @@ -68,9 +52,12 @@ android_test { jni_libs: [ // these are needed for Extended Mockito + "libdexmakerjvmtiagent", + "libstaticjvmtiagent", "libbluetooth_jni", ], compile_multilib: "both", + certificate: ":com.android.bluetooth.certificate", min_sdk_version: "current", diff --git a/service/tests/AndroidManifest.xml b/service/tests/AndroidManifest.xml index afecc067ed..72e2ca0c00 100644 --- a/service/tests/AndroidManifest.xml +++ b/service/tests/AndroidManifest.xml @@ -31,10 +31,9 @@ </activity> </application> - <instrumentation android:name="com.android.server.bluetooth.CustomTestRunner" + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" android:targetPackage="com.android.server.bluetooth.test" - android:label="Service Bluetooth Tests"> - </instrumentation> + android:label="Service Bluetooth Tests"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.INTERNET"/> diff --git a/service/tests/AndroidTest.xml b/service/tests/AndroidTest.xml index c31c6cb068..1befc15fd5 100644 --- a/service/tests/AndroidTest.xml +++ b/service/tests/AndroidTest.xml @@ -24,7 +24,7 @@ value="com.google.android.bluetooth.apex" /> <test class="com.android.tradefed.testtype.AndroidJUnitTest" > <option name="package" value="com.android.server.bluetooth.test" /> - <option name="runner" value="com.android.server.bluetooth.CustomTestRunner" /> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> <option name="hidden-api-checks" value="false"/> </test> diff --git a/service/tests/src/com/android/server/BluetoothAirplaneModeListenerTest.java b/service/tests/src/com/android/server/BluetoothAirplaneModeListenerTest.java index 8c7ec8ec7f..92c98511e9 100644 --- a/service/tests/src/com/android/server/BluetoothAirplaneModeListenerTest.java +++ b/service/tests/src/com/android/server/BluetoothAirplaneModeListenerTest.java @@ -16,14 +16,25 @@ package com.android.server.bluetooth; +import static com.android.server.bluetooth.BluetoothAirplaneModeListener.APM_BT_NOTIFICATION; +import static com.android.server.bluetooth.BluetoothAirplaneModeListener.APM_ENHANCEMENT; +import static com.android.server.bluetooth.BluetoothAirplaneModeListener.APM_USER_TOGGLED_BLUETOOTH; +import static com.android.server.bluetooth.BluetoothAirplaneModeListener.APM_WIFI_BT_NOTIFICATION; +import static com.android.server.bluetooth.BluetoothAirplaneModeListener.NOTIFICATION_NOT_SHOWN; +import static com.android.server.bluetooth.BluetoothAirplaneModeListener.NOTIFICATION_SHOWN; +import static com.android.server.bluetooth.BluetoothAirplaneModeListener.UNUSED; +import static com.android.server.bluetooth.BluetoothAirplaneModeListener.USED; +import static com.android.server.bluetooth.BluetoothAirplaneModeListener.WIFI_APM_STATE; + import static org.mockito.Mockito.*; -import android.bluetooth.BluetoothAdapter; +import android.content.ContentResolver; import android.content.Context; +import android.content.pm.PackageManager; +import android.content.res.Resources; import android.os.Looper; import android.provider.Settings; -import androidx.test.InstrumentationRegistry; import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; @@ -32,23 +43,27 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.MockitoAnnotations; @MediumTest @RunWith(AndroidJUnit4.class) public class BluetoothAirplaneModeListenerTest { - private Context mContext; + private static final String PACKAGE_NAME = "TestPackage"; + private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener; - private BluetoothAdapter mBluetoothAdapter; - private BluetoothModeChangeHelper mHelper; - private BluetoothNotificationManager mBluetoothNotificationManager; - @Mock BluetoothManagerService mBluetoothManagerService; + @Mock private Context mContext; + @Mock private ContentResolver mContentResolver; + @Mock private BluetoothManagerService mBluetoothManagerService; + @Mock private BluetoothModeChangeHelper mHelper; + @Mock private BluetoothNotificationManager mBluetoothNotificationManager; + @Mock private PackageManager mPackageManager; + @Mock private Resources mResources; @Before public void setUp() throws Exception { - mContext = InstrumentationRegistry.getTargetContext(); - - mHelper = mock(BluetoothModeChangeHelper.class); + MockitoAnnotations.initMocks(this); + when(mContext.getContentResolver()).thenReturn(mContentResolver); when(mHelper.getSettingsInt(BluetoothAirplaneModeListener.TOAST_COUNT)) .thenReturn(BluetoothAirplaneModeListener.MAX_TOAST_COUNT); doNothing().when(mHelper).setSettingsInt(anyString(), anyInt()); @@ -76,6 +91,59 @@ public class BluetoothAirplaneModeListenerTest { } @Test + public void testIgnoreOnAirplanModeChangeApmEnhancement() { + when(mHelper.isAirplaneModeOn()).thenReturn(true); + when(mHelper.isBluetoothOn()).thenReturn(true); + + // When APM enhancement is disabled, BT remains on when connected to a media profile + when(mHelper.getSettingsInt(APM_ENHANCEMENT)).thenReturn(0); + when(mHelper.isMediaProfileConnected()).thenReturn(true); + Assert.assertTrue(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); + + // When APM enhancement is disabled, BT turns off when not connected to a media profile + when(mHelper.isMediaProfileConnected()).thenReturn(false); + Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); + + // When APM enhancement is enabled but not activated by toggling BT in APM, + // BT remains on when connected to a media profile + when(mHelper.getSettingsInt(APM_ENHANCEMENT)).thenReturn(1); + when(mHelper.getSettingsSecureInt(APM_USER_TOGGLED_BLUETOOTH, UNUSED)).thenReturn(UNUSED); + when(mHelper.isMediaProfileConnected()).thenReturn(true); + Assert.assertTrue(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); + + // When APM enhancement is enabled but not activated by toggling BT in APM, + // BT turns off when not connected to a media profile + when(mHelper.isMediaProfileConnected()).thenReturn(false); + Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); + + // When APM enhancement is enabled but not activated by toggling BT in APM, + // BT remains on when the default value for BT in APM is on + when(mHelper.isBluetoothOnAPM()).thenReturn(true); + Assert.assertTrue(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); + + // When APM enhancement is enabled but not activated by toggling BT in APM, + // BT remains off when the default value for BT in APM is off + when(mHelper.isBluetoothOnAPM()).thenReturn(false); + Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); + + // When APM enhancement is enabled and activated by toggling BT in APM, + // BT remains on if user's last choice in APM was on + when(mHelper.getSettingsSecureInt(APM_USER_TOGGLED_BLUETOOTH, UNUSED)).thenReturn(USED); + when(mHelper.isBluetoothOnAPM()).thenReturn(true); + Assert.assertTrue(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); + + // When APM enhancement is enabled and activated by toggling BT in APM, + // BT turns off if user's last choice in APM was off + when(mHelper.isBluetoothOnAPM()).thenReturn(false); + Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); + + // When APM enhancement is enabled and activated by toggling BT in APM, + // BT turns off if user's last choice in APM was off even when connected to a media profile + when(mHelper.isMediaProfileConnected()).thenReturn(true); + Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); + } + + @Test public void testHandleAirplaneModeChange_InvokeAirplaneModeChanged() { mBluetoothAirplaneModeListener.handleAirplaneModeChange(); verify(mHelper).onAirplaneModeChanged(mBluetoothManagerService); @@ -109,6 +177,81 @@ public class BluetoothAirplaneModeListenerTest { verify(mHelper, times(0)).onAirplaneModeChanged(mBluetoothManagerService); } + private void setUpApmNotificationTests() throws Exception { + when(mHelper.isBluetoothOn()).thenReturn(true); + when(mHelper.isAirplaneModeOn()).thenReturn(true); + when(mHelper.isBluetoothOnAPM()).thenReturn(true); + when(mHelper.getSettingsInt(APM_ENHANCEMENT)).thenReturn(1); + when(mHelper.getSettingsSecureInt(APM_USER_TOGGLED_BLUETOOTH, UNUSED)).thenReturn(USED); + when(mHelper.getBluetoothPackageName()).thenReturn(PACKAGE_NAME); + when(mContext.getPackageManager()).thenReturn(mPackageManager); + when(mPackageManager.getResourcesForApplication(PACKAGE_NAME)).thenReturn(mResources); + } + + @Test + public void testHandleAirplaneModeChange_ShowBtAndWifiApmNotification() throws Exception { + setUpApmNotificationTests(); + when(mHelper.getSettingsInt(Settings.Global.WIFI_ON)).thenReturn(1); + when(mHelper.getSettingsSecureInt(WIFI_APM_STATE, 0)).thenReturn(1); + when(mHelper.getSettingsSecureInt(APM_WIFI_BT_NOTIFICATION, NOTIFICATION_NOT_SHOWN)) + .thenReturn(NOTIFICATION_NOT_SHOWN); + + mBluetoothAirplaneModeListener.handleAirplaneModeChange(); + + verify(mHelper).setSettingsInt(Settings.Global.BLUETOOTH_ON, + BluetoothManagerService.BLUETOOTH_ON_AIRPLANE); + verify(mBluetoothNotificationManager).sendApmNotification(any(), any()); + verify(mHelper).setSettingsSecureInt(APM_WIFI_BT_NOTIFICATION, NOTIFICATION_SHOWN); + } + + @Test + public void testHandleAirplaneModeChange_NotShowBtAndWifiApmNotification() throws Exception { + setUpApmNotificationTests(); + when(mHelper.getSettingsInt(Settings.Global.WIFI_ON)).thenReturn(1); + when(mHelper.getSettingsSecureInt(WIFI_APM_STATE, 0)).thenReturn(1); + when(mHelper.getSettingsSecureInt(APM_WIFI_BT_NOTIFICATION, NOTIFICATION_NOT_SHOWN)) + .thenReturn(NOTIFICATION_SHOWN); + + mBluetoothAirplaneModeListener.handleAirplaneModeChange(); + + verify(mHelper).setSettingsInt(Settings.Global.BLUETOOTH_ON, + BluetoothManagerService.BLUETOOTH_ON_AIRPLANE); + verify(mBluetoothNotificationManager, never()).sendApmNotification(any(), any()); + verify(mHelper, never()).setSettingsSecureInt(APM_WIFI_BT_NOTIFICATION, NOTIFICATION_SHOWN); + } + + @Test + public void testHandleAirplaneModeChange_ShowBtApmNotification() throws Exception { + setUpApmNotificationTests(); + when(mHelper.getSettingsInt(Settings.Global.WIFI_ON)).thenReturn(1); + when(mHelper.getSettingsSecureInt(WIFI_APM_STATE, 0)).thenReturn(0); + when(mHelper.getSettingsSecureInt(APM_BT_NOTIFICATION, NOTIFICATION_NOT_SHOWN)) + .thenReturn(NOTIFICATION_NOT_SHOWN); + + mBluetoothAirplaneModeListener.handleAirplaneModeChange(); + + verify(mHelper).setSettingsInt(Settings.Global.BLUETOOTH_ON, + BluetoothManagerService.BLUETOOTH_ON_AIRPLANE); + verify(mBluetoothNotificationManager).sendApmNotification(any(), any()); + verify(mHelper).setSettingsSecureInt(APM_BT_NOTIFICATION, NOTIFICATION_SHOWN); + } + + @Test + public void testHandleAirplaneModeChange_NotShowBtApmNotification() throws Exception { + setUpApmNotificationTests(); + when(mHelper.getSettingsInt(Settings.Global.WIFI_ON)).thenReturn(1); + when(mHelper.getSettingsSecureInt(WIFI_APM_STATE, 0)).thenReturn(0); + when(mHelper.getSettingsSecureInt(APM_BT_NOTIFICATION, NOTIFICATION_NOT_SHOWN)) + .thenReturn(NOTIFICATION_SHOWN); + + mBluetoothAirplaneModeListener.handleAirplaneModeChange(); + + verify(mHelper).setSettingsInt(Settings.Global.BLUETOOTH_ON, + BluetoothManagerService.BLUETOOTH_ON_AIRPLANE); + verify(mBluetoothNotificationManager, never()).sendApmNotification(any(), any()); + verify(mHelper, never()).setSettingsSecureInt(APM_BT_NOTIFICATION, NOTIFICATION_SHOWN); + } + @Test public void testIsPopToast_PopToast() { mBluetoothAirplaneModeListener.mToastCount = 0; diff --git a/system/Android.bp b/system/Android.bp index dbb3ebc9a5..d1afd9162e 100644 --- a/system/Android.bp +++ b/system/Android.bp @@ -155,7 +155,7 @@ rust_protobuf { source_stem: "facade", host_supported: true, apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } diff --git a/system/audio_a2dp_hw/Android.bp b/system/audio_a2dp_hw/Android.bp index d0cc1ef08b..9f8e3d4d6d 100644 --- a/system/audio_a2dp_hw/Android.bp +++ b/system/audio_a2dp_hw/Android.bp @@ -29,7 +29,7 @@ cc_library { "src/audio_a2dp_hw_utils.cc", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], shared_libs: [ "liblog", diff --git a/system/audio_hearing_aid_hw/Android.bp b/system/audio_hearing_aid_hw/Android.bp index cb5f110f23..65174da008 100644 --- a/system/audio_hearing_aid_hw/Android.bp +++ b/system/audio_hearing_aid_hw/Android.bp @@ -28,7 +28,7 @@ cc_library { "src/audio_hearing_aid_hw_utils.cc", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], shared_libs: [ "liblog", diff --git a/system/blueberry/tests/topshim/adapter/adapter_test.py b/system/blueberry/tests/topshim/adapter/adapter_test.py index c5fdd6d242..cc05e174da 100644 --- a/system/blueberry/tests/topshim/adapter/adapter_test.py +++ b/system/blueberry/tests/topshim/adapter/adapter_test.py @@ -25,9 +25,16 @@ from mobly import test_runner class AdapterTest(TopshimBaseTest): + async def __verify_enable_page_scan(self): + await self.dut_adapter.set_enable_page_scan() + return await self.dut_adapter.le_rand() + def test_verify_adapter_started(self): print("Adapter is verified when test starts") + def test_enable_page_scan(self): + asyncio.get_event_loop().run_until_complete(self.__verify_enable_page_scan()) + if __name__ == "__main__": test_runner.main() diff --git a/system/bta/ag/bta_ag_sco.cc b/system/bta/ag/bta_ag_sco.cc index a0a9d0097a..e0134f744e 100644 --- a/system/bta/ag/bta_ag_sco.cc +++ b/system/bta/ag/bta_ag_sco.cc @@ -34,12 +34,16 @@ #include "main/shim/dumpsys.h" #include "osi/include/log.h" #include "osi/include/osi.h" // UNUSED_ATTR +#include "stack/btm/btm_int_types.h" #include "stack/btm/btm_sco.h" #include "stack/btm/btm_sco_hfp_hal.h" +#include "stack/include/acl_api.h" #include "stack/include/btm_api.h" #include "stack/include/btu.h" // do_in_main_thread #include "types/raw_address.h" +extern tBTM_CB btm_cb; + /* Codec negotiation timeout */ #ifndef BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS #define BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS (3 * 1000) /* 3 seconds */ @@ -512,6 +516,15 @@ static void bta_ag_create_pending_sco(tBTA_AG_SCB* p_scb, bool is_local) { params = esco_parameters_for_codec(ESCO_CODEC_CVSD_S3, offload); } + // HFP v1.8 5.7.3 CVSD coding + tSCO_CONN* p_sco = NULL; + if (p_scb->sco_idx < BTM_MAX_SCO_LINKS) + p_sco = &btm_cb.sco_cb.sco_db[p_scb->sco_idx]; + if (p_sco && (p_sco->esco.data.link_type == BTM_LINK_TYPE_SCO || + !sco_peer_supports_esco_ev3(p_sco->esco.data.bd_addr))) { + params = esco_parameters_for_codec(SCO_CODEC_CVSD_D1, offload); + } + BTM_EScoConnRsp(p_scb->sco_idx, HCI_SUCCESS, ¶ms); APPL_TRACE_DEBUG("%s: listening for SCO connection", __func__); } diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc index a05e242ffd..713be3ac68 100644 --- a/system/bta/le_audio/state_machine.cc +++ b/system/bta/le_audio/state_machine.cc @@ -718,12 +718,13 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { uint8_t value = 0; if (ases_pair.sink && ases_pair.sink->data_path_state == - AudioStreamDataPathState::CIS_ESTABLISHED) { + AudioStreamDataPathState::DATA_PATH_ESTABLISHED) { value |= bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput; } - if (ases_pair.source && ases_pair.source->data_path_state == - AudioStreamDataPathState::CIS_ESTABLISHED) { + if (ases_pair.source && + ases_pair.source->data_path_state == + AudioStreamDataPathState::DATA_PATH_ESTABLISHED) { value |= bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionOutput; } IsoManager::GetInstance()->RemoveIsoDataPath(cis_conn_hdl, value); diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc index 822c602a74..2fd0e7865a 100644 --- a/system/bta/le_audio/state_machine_test.cc +++ b/system/bta/le_audio/state_machine_test.cc @@ -1574,7 +1574,11 @@ TEST_F(StateMachineTest, testDisableSingle) { EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1); EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1); EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1); - EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1); + EXPECT_CALL( + *mock_iso_manager_, + RemoveIsoDataPath( + _, bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput)) + .Times(1); EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1); EXPECT_CALL(*mock_iso_manager_, RemoveCig(_)).Times(0); @@ -1637,7 +1641,11 @@ TEST_F(StateMachineTest, testDisableMultiple) { EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1); EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1); EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2); - EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2); + EXPECT_CALL( + *mock_iso_manager_, + RemoveIsoDataPath( + _, bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput)) + .Times(2); EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2); EXPECT_CALL(*mock_iso_manager_, RemoveCig(_)).Times(0); @@ -1695,7 +1703,13 @@ TEST_F(StateMachineTest, testDisableBidirectional) { EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1); EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1); EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2); - EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1); + EXPECT_CALL( + *mock_iso_manager_, + RemoveIsoDataPath( + _, + bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput | + bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionOutput)) + .Times(1); EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1); EXPECT_CALL(*mock_iso_manager_, RemoveCig(_)).Times(0); diff --git a/system/btcore/Android.bp b/system/btcore/Android.bp index 82ca35b658..cae1c37948 100644 --- a/system/btcore/Android.bp +++ b/system/btcore/Android.bp @@ -26,7 +26,7 @@ cc_defaults { header_libs: ["libbluetooth_headers"], host_supported: true, apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], target: { host_linux: { @@ -53,7 +53,7 @@ cc_library_headers { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } diff --git a/system/btif/Android.bp b/system/btif/Android.bp index c42679f7bd..5075c7ac18 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -47,7 +47,7 @@ cc_library { "libcutils", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", target: { diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 1a35830252..0d5a11b952 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -70,6 +70,7 @@ #include "common/metrics.h" #include "device/include/controller.h" #include "device/include/interop.h" +#include "gd/common/lru_cache.h" #include "internal_include/stack_config.h" #include "main/shim/dumpsys.h" #include "main/shim/shim.h" @@ -156,9 +157,6 @@ typedef struct { bool is_le_nc; /* LE Numeric comparison */ btif_dm_ble_cb_t ble; uint8_t fail_reason; - Uuid::UUID128Bit eir_uuids[32]; - uint8_t num_eir_uuids; - std::set<Uuid::UUID128Bit> uuids; } btif_dm_pairing_cb_t; // TODO(jpawlowski): unify ? @@ -206,6 +204,11 @@ typedef struct { #define MAX_BTIF_BOND_EVENT_ENTRIES 15 +#define MAX_NUM_DEVICES_IN_EIR_UUID_CACHE 128 + +static bluetooth::common::LruCache<RawAddress, std::set<Uuid>> eir_uuids_cache( + MAX_NUM_DEVICES_IN_EIR_UUID_CACHE); + static skip_sdp_entry_t sdp_rejectlist[] = {{76}}; // Apple Mouse and Keyboard /* This flag will be true if HCI_Inquiry is in progress */ @@ -1298,13 +1301,16 @@ static void btif_dm_search_devices_evt(tBTA_DM_SEARCH_EVT event, /* Cache EIR queried services */ if (num_uuids > 0) { uint16_t* p_uuid16 = (uint16_t*)uuid_list; - pairing_cb.num_eir_uuids = 0; - LOG_INFO("EIR UUIDS:"); + auto uuid_iter = eir_uuids_cache.find(bdaddr); + if (uuid_iter == eir_uuids_cache.end()) { + auto triple = eir_uuids_cache.try_emplace(bdaddr, std::set<Uuid>{}); + uuid_iter = std::get<0>(triple); + } + LOG_INFO("EIR UUIDs for %s:", bdaddr.ToString().c_str()); for (int i = 0; i < num_uuids; ++i) { Uuid uuid = Uuid::From16Bit(p_uuid16[i]); LOG_INFO(" %s", uuid.ToString().c_str()); - pairing_cb.eir_uuids[i] = uuid.To128BitBE(); - pairing_cb.num_eir_uuids++; + uuid_iter->second.insert(uuid); } #if TARGET_FLOSS @@ -1372,6 +1378,10 @@ static void btif_get_existing_uuids(RawAddress* bd_addr, Uuid* existing_uuids) { btif_storage_get_remote_device_property(bd_addr, &tmp_prop); } +static bool btif_should_ignore_uuid(const Uuid& uuid) { + return uuid.IsEmpty() || uuid.IsBase(); +} + /******************************************************************************* * * Function btif_dm_search_services_evt @@ -1414,7 +1424,7 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, LOG_INFO("New UUIDs for %s:", bd_addr.ToString().c_str()); for (i = 0; i < p_data->disc_res.num_uuids; i++) { auto uuid = p_data->disc_res.p_uuid_list + i; - if (uuid->IsEmpty()) { + if (btif_should_ignore_uuid(*uuid)) { continue; } LOG_INFO("index:%d uuid:%s", i, uuid->ToString().c_str()); @@ -1426,7 +1436,7 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, for (int i = 0; i < BT_MAX_NUM_UUIDS; i++) { Uuid uuid = existing_uuids[i]; - if (uuid.IsEmpty()) { + if (btif_should_ignore_uuid(uuid)) { continue; } if (btif_is_interesting_le_service(uuid)) { @@ -1447,6 +1457,8 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, /* onUuidChanged requires getBondedDevices to be populated. ** bond_state_changed needs to be sent prior to remote_device_property */ + auto num_eir_uuids = 0; + Uuid uuid = {}; if (pairing_cb.state == BT_BOND_STATE_BONDED && pairing_cb.sdp_attempts && (p_data->disc_res.bd_addr == pairing_cb.bd_addr || p_data->disc_res.bd_addr == pairing_cb.static_bdaddr)) { @@ -1457,33 +1469,33 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, // when SDP failed or no UUID is discovered if (p_data->disc_res.result != BTA_SUCCESS || p_data->disc_res.num_uuids == 0) { - LOG_INFO("SDP failed, send %d EIR UUIDs to unblock bonding %s", - pairing_cb.num_eir_uuids, bd_addr.ToString().c_str()); - bt_property_t prop_uuids; - Uuid uuid = {}; - prop_uuids.type = BT_PROPERTY_UUIDS; - if (pairing_cb.num_eir_uuids > 0) { - prop_uuids.val = pairing_cb.eir_uuids; - prop_uuids.len = pairing_cb.num_eir_uuids * Uuid::kNumBytes128; + auto uuids_iter = eir_uuids_cache.find(bd_addr); + if (uuids_iter != eir_uuids_cache.end()) { + num_eir_uuids = static_cast<int>(uuids_iter->second.size()); + LOG_INFO("SDP failed, send %d EIR UUIDs to unblock bonding %s", + num_eir_uuids, bd_addr.ToString().c_str()); + for (auto eir_uuid : uuids_iter->second) { + auto uuid_128bit = eir_uuid.To128BitBE(); + property_value.insert(property_value.end(), uuid_128bit.begin(), + uuid_128bit.end()); + } + } + if (num_eir_uuids > 0) { + prop.val = (void*)property_value.data(); + prop.len = num_eir_uuids * Uuid::kNumBytes128; } else { - prop_uuids.val = &uuid; - prop_uuids.len = Uuid::kNumBytes128; + LOG_WARN("SDP failed and we have no EIR UUIDs to report either"); + prop.val = &uuid; + prop.len = Uuid::kNumBytes128; } - - /* Send the event to the BTIF - * prop_uuids will be deep copied by this call - */ - invoke_remote_device_properties_cb(BT_STATUS_SUCCESS, bd_addr, 1, - &prop_uuids); - pairing_cb = {}; - break; + eir_uuids_cache.erase(uuids_iter); } // Both SDP and bonding are done, clear pairing control block in case // it is not already cleared pairing_cb = {}; } - if (p_data->disc_res.num_uuids != 0) { + if (p_data->disc_res.num_uuids != 0 || num_eir_uuids != 0) { /* Also write this to the NVRAM */ ret = btif_storage_set_remote_device_property(&bd_addr, &prop); ASSERTC(ret == BT_STATUS_SUCCESS, "storing remote services failed", @@ -1512,7 +1524,7 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, LOG_INFO("New BLE UUIDs for %s:", bd_addr.ToString().c_str()); for (Uuid uuid : *p_data->disc_ble_res.services) { if (btif_is_interesting_le_service(uuid)) { - if (uuid.IsEmpty()) { + if (btif_should_ignore_uuid(uuid)) { continue; } LOG_INFO("index:%d uuid:%s", static_cast<int>(uuids.size()), diff --git a/system/build/Android.bp b/system/build/Android.bp index 52e3821b19..706488b727 100644 --- a/system/build/Android.bp +++ b/system/build/Android.bp @@ -185,7 +185,7 @@ fluoride_defaults { defaults: ["fluoride_test_prod_shared_defaults", "libchrome_support_defaults"], apex_available: [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", ], shared_libs: [ "libcrypto", diff --git a/system/embdrv/g722/Android.bp b/system/embdrv/g722/Android.bp index 6df0f31889..f90d90985d 100644 --- a/system/embdrv/g722/Android.bp +++ b/system/embdrv/g722/Android.bp @@ -22,7 +22,7 @@ cc_library_static { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "Tiramisu" } diff --git a/system/embdrv/lc3/Android.bp b/system/embdrv/lc3/Android.bp index fed3052c1c..a16f30ed48 100644 --- a/system/embdrv/lc3/Android.bp +++ b/system/embdrv/lc3/Android.bp @@ -12,7 +12,7 @@ cc_library_static { host_supported: true, apex_available: [ - "com.android.bluetooth" + "com.android.btservices" ], defaults: ["fluoride_defaults"], srcs: [ diff --git a/system/gd/Android.bp b/system/gd/Android.bp index 6aee1482f3..1c6573aba9 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -613,7 +613,25 @@ rust_library { "liblog_rust", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", + ], + min_sdk_version: "30", +} + +rust_library { + name: "libbt_packets_nonapex", + defaults: ["gd_rust_defaults"], + crate_name: "bt_packets", + srcs: ["rust/packets/lib.rs", ":BluetoothGeneratedPackets_rust"], + edition: "2018", + vendor_available : true, + host_supported: true, + proc_macros: ["libnum_derive"], + rustlibs: [ + "libbytes", + "libnum_traits", + "libthiserror", + "liblog_rust", ], min_sdk_version: "30", } diff --git a/system/gd/dumpsys/Android.bp b/system/gd/dumpsys/Android.bp index 0241b008cc..22456518e0 100644 --- a/system/gd/dumpsys/Android.bp +++ b/system/gd/dumpsys/Android.bp @@ -143,7 +143,7 @@ cc_library { "BluetoothGeneratedDumpsysBundledSchema_cc", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } diff --git a/system/gd/proto/Android.bp b/system/gd/proto/Android.bp index 1e256e671c..19e95daa63 100644 --- a/system/gd/proto/Android.bp +++ b/system/gd/proto/Android.bp @@ -18,7 +18,7 @@ java_library_static { "bluetooth/bluetoothKeystore/keystore.proto", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", sdk_version: "current", @@ -36,7 +36,7 @@ cc_library_static { "bluetooth/bluetoothKeystore/keystore.proto", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } @@ -54,7 +54,7 @@ cc_library_static { "bluetooth/bluetoothKeystore/keystore.proto", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } diff --git a/system/gd/rust/common/Android.bp b/system/gd/rust/common/Android.bp index e196acead8..e60f145f0e 100644 --- a/system/gd/rust/common/Android.bp +++ b/system/gd/rust/common/Android.bp @@ -37,7 +37,7 @@ rust_library { }, apex_available: [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "Tiramisu", } @@ -82,7 +82,7 @@ rust_ffi_static { }, }, apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } @@ -113,7 +113,7 @@ cc_library_static { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", ], shared_libs: [ "libchrome", @@ -135,7 +135,7 @@ cc_library_static { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } @@ -146,7 +146,7 @@ cc_library_headers { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } @@ -161,7 +161,7 @@ cc_library_static { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } diff --git a/system/gd/rust/facade/Android.bp b/system/gd/rust/facade/Android.bp index 82b79567d0..aa1965b5aa 100644 --- a/system/gd/rust/facade/Android.bp +++ b/system/gd/rust/facade/Android.bp @@ -59,7 +59,7 @@ rust_library { "libcxx", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } diff --git a/system/gd/rust/gddi/Android.bp b/system/gd/rust/gddi/Android.bp index b6cff426fc..ac8ed8b475 100644 --- a/system/gd/rust/gddi/Android.bp +++ b/system/gd/rust/gddi/Android.bp @@ -16,7 +16,7 @@ rust_library { proc_macros: ["libgddi_macros"], rustlibs: ["libtokio"], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } diff --git a/system/gd/rust/linux/client/src/command_handler.rs b/system/gd/rust/linux/client/src/command_handler.rs index 307eeedb84..cf9a8a3276 100644 --- a/system/gd/rust/linux/client/src/command_handler.rs +++ b/system/gd/rust/linux/client/src/command_handler.rs @@ -5,7 +5,7 @@ use std::sync::{Arc, Mutex}; use crate::callbacks::BtGattCallback; use crate::ClientContext; use crate::{console_red, console_yellow, print_error, print_info}; -use bt_topshim::btif::BtTransport; +use bt_topshim::btif::{BtConnectionState, BtTransport}; use btstack::bluetooth::{BluetoothDevice, IBluetooth, IBluetoothQA}; use btstack::bluetooth_gatt::IBluetoothGatt; use btstack::uuid::{Profile, UuidHelper, UuidWrapper}; @@ -171,7 +171,7 @@ fn build_commands() -> HashMap<String, CommandOption> { command_options.insert( String::from("list"), CommandOption { - rules: vec![String::from("list <bonded|found>")], + rules: vec![String::from("list <bonded|found|connected>")], description: String::from( "List bonded or found remote devices. Use: list <bonded|found>", ), @@ -552,7 +552,7 @@ impl CommandHandler { name: String::from("Classic Device"), }; - let (name, alias, device_type, class, bonded, connected, uuids) = { + let (name, alias, device_type, class, bonded, connection_state, uuids) = { let ctx = self.context.lock().unwrap(); let adapter = ctx.adapter_dbus.as_ref().unwrap(); @@ -561,10 +561,14 @@ impl CommandHandler { let alias = adapter.get_remote_alias(device.clone()); let class = adapter.get_remote_class(device.clone()); let bonded = adapter.get_bond_state(device.clone()); - let connected = adapter.get_connection_state(device.clone()); + let connection_state = match adapter.get_connection_state(device.clone()) { + BtConnectionState::NotConnected => "Not Connected", + BtConnectionState::ConnectedOnly => "Connected", + _ => "Connected and Paired", + }; let uuids = adapter.get_remote_uuids(device.clone()); - (name, alias, device_type, class, bonded, connected, uuids) + (name, alias, device_type, class, bonded, connection_state, uuids) }; let uuid_helper = UuidHelper::new(); @@ -573,8 +577,8 @@ impl CommandHandler { print_info!("Alias: {}", alias); print_info!("Type: {:?}", device_type); print_info!("Class: {}", class); - print_info!("Bonded: {}", bonded); - print_info!("Connected: {}", connected); + print_info!("Bond State: {:?}", bonded); + print_info!("Connection State: {}", connection_state); print_info!( "Uuids: {}", DisplayList( @@ -828,7 +832,7 @@ impl CommandHandler { return; } - enforce_arg_len(args, 1, "list <bonded|found>", || match &args[0][0..] { + enforce_arg_len(args, 1, "list <bonded|found|connected>", || match &args[0][0..] { "bonded" => { print_info!("Known bonded devices:"); let devices = self @@ -849,6 +853,20 @@ impl CommandHandler { print_info!("[{:17}] {}", key, val.name); } } + "connected" => { + print_info!("Connected devices:"); + let devices = self + .context + .lock() + .unwrap() + .adapter_dbus + .as_ref() + .unwrap() + .get_connected_devices(); + for device in devices.iter() { + print_info!("[{:17}] {}", device.address, device.name); + } + } _ => { println!("Invalid argument '{}'", args[0]); } diff --git a/system/gd/rust/linux/client/src/dbus_iface.rs b/system/gd/rust/linux/client/src/dbus_iface.rs index 16ec9a1d04..8cfff0c4f8 100644 --- a/system/gd/rust/linux/client/src/dbus_iface.rs +++ b/system/gd/rust/linux/client/src/dbus_iface.rs @@ -1,7 +1,8 @@ //! D-Bus proxy implementations of the APIs. use bt_topshim::btif::{ - BtDeviceType, BtPropertyType, BtSspVariant, BtStatus, BtTransport, Uuid, Uuid128Bit, + BtBondState, BtConnectionState, BtDeviceType, BtPropertyType, BtSspVariant, BtStatus, + BtTransport, Uuid, Uuid128Bit, }; use bt_topshim::profiles::gatt::GattStatus; use bt_topshim::profiles::socket::SocketType; @@ -49,6 +50,8 @@ fn make_object_path(idx: i32, name: &str) -> dbus::Path { dbus::Path::new(format!("/org/chromium/bluetooth/hci{}/{}", idx, name)).unwrap() } +impl_dbus_arg_enum!(BtBondState); +impl_dbus_arg_enum!(BtConnectionState); impl_dbus_arg_enum!(BtDeviceType); impl_dbus_arg_enum!(BtPropertyType); impl_dbus_arg_enum!(BtSspVariant); @@ -353,7 +356,7 @@ impl IBluetooth for BluetoothDBus { } #[dbus_method("GetBondState")] - fn get_bond_state(&self, device: BluetoothDevice) -> u32 { + fn get_bond_state(&self, device: BluetoothDevice) -> BtBondState { dbus_generated!() } @@ -397,8 +400,18 @@ impl IBluetooth for BluetoothDBus { dbus_generated!() } + #[dbus_method("GetRemoteConnected")] + fn get_remote_connected(&self, device: BluetoothDevice) -> bool { + dbus_generated!() + } + + #[dbus_method("GetConnectedDevices")] + fn get_connected_devices(&self) -> Vec<BluetoothDevice> { + dbus_generated!() + } + #[dbus_method("GetConnectionState")] - fn get_connection_state(&self, device: BluetoothDevice) -> u32 { + fn get_connection_state(&self, device: BluetoothDevice) -> BtConnectionState { dbus_generated!() } diff --git a/system/gd/rust/linux/service/src/iface_bluetooth.rs b/system/gd/rust/linux/service/src/iface_bluetooth.rs index 842dfbb0ea..86b087b992 100644 --- a/system/gd/rust/linux/service/src/iface_bluetooth.rs +++ b/system/gd/rust/linux/service/src/iface_bluetooth.rs @@ -1,7 +1,8 @@ extern crate bt_shim; use bt_topshim::btif::{ - BtDeviceType, BtPropertyType, BtSspVariant, BtStatus, BtTransport, Uuid, Uuid128Bit, + BtBondState, BtConnectionState, BtDeviceType, BtPropertyType, BtSspVariant, BtStatus, + BtTransport, Uuid, Uuid128Bit, }; use bt_topshim::profiles::socket::SocketType; @@ -112,6 +113,8 @@ impl IBluetoothCallback for BluetoothCallbackDBus { } } +impl_dbus_arg_enum!(BtBondState); +impl_dbus_arg_enum!(BtConnectionState); impl_dbus_arg_enum!(BtDeviceType); impl_dbus_arg_enum!(BtPropertyType); impl_dbus_arg_enum!(BtSspVariant); @@ -269,7 +272,7 @@ impl IBluetooth for IBluetoothDBus { } #[dbus_method("GetBondState")] - fn get_bond_state(&self, device: BluetoothDevice) -> u32 { + fn get_bond_state(&self, device: BluetoothDevice) -> BtBondState { dbus_generated!() } @@ -313,8 +316,18 @@ impl IBluetooth for IBluetoothDBus { dbus_generated!() } + #[dbus_method("GetRemoteConnected")] + fn get_remote_connected(&self, _device: BluetoothDevice) -> bool { + dbus_generated!() + } + + #[dbus_method("GetConnectedDevices")] + fn get_connected_devices(&self) -> Vec<BluetoothDevice> { + dbus_generated!() + } + #[dbus_method("GetConnectionState")] - fn get_connection_state(&self, device: BluetoothDevice) -> u32 { + fn get_connection_state(&self, device: BluetoothDevice) -> BtConnectionState { dbus_generated!() } diff --git a/system/gd/rust/linux/service/src/iface_bluetooth_media.rs b/system/gd/rust/linux/service/src/iface_bluetooth_media.rs index 4e3d4e6c02..249ff3d821 100644 --- a/system/gd/rust/linux/service/src/iface_bluetooth_media.rs +++ b/system/gd/rust/linux/service/src/iface_bluetooth_media.rs @@ -141,7 +141,7 @@ impl IBluetoothMedia for IBluetoothMediaDBus { } #[dbus_method("GetA2dpAudioStarted")] - fn get_a2dp_audio_started(&mut self) -> bool { + fn get_a2dp_audio_started(&mut self, address: String) -> u8 { dbus_generated!() } @@ -156,7 +156,7 @@ impl IBluetoothMedia for IBluetoothMediaDBus { } #[dbus_method("GetHfpAudioStarted")] - fn get_hfp_audio_started(&mut self) -> bool { + fn get_hfp_audio_started(&mut self, address: String) -> u8 { dbus_generated!() } diff --git a/system/gd/rust/linux/service/src/main.rs b/system/gd/rust/linux/service/src/main.rs index 8a6f95ec65..8258437ca4 100644 --- a/system/gd/rust/linux/service/src/main.rs +++ b/system/gd/rust/linux/service/src/main.rs @@ -114,8 +114,7 @@ fn main() -> Result<(), Box<dyn Error>> { tx.clone(), )))); - let bt_sock_mgr = - Arc::new(Mutex::new(Box::new(BluetoothSocketManager::new(intf.clone(), tx.clone())))); + let bt_sock_mgr = Arc::new(Mutex::new(Box::new(BluetoothSocketManager::new(tx.clone())))); topstack::get_runtime().block_on(async { // Connect to D-Bus system bus. @@ -244,6 +243,7 @@ fn main() -> Result<(), Box<dyn Error>> { bluetooth.enable(); bluetooth_gatt.lock().unwrap().init_profiles(tx.clone()); + bt_sock_mgr.lock().unwrap().initialize(intf.clone()); } // Serve clients forever. diff --git a/system/gd/rust/linux/stack/src/bluetooth.rs b/system/gd/rust/linux/stack/src/bluetooth.rs index 06ecaf6d4d..6e2eb01b7e 100644 --- a/system/gd/rust/linux/stack/src/bluetooth.rs +++ b/system/gd/rust/linux/stack/src/bluetooth.rs @@ -2,8 +2,9 @@ use bt_topshim::btif::{ BaseCallbacks, BaseCallbacksDispatcher, BluetoothInterface, BluetoothProperty, BtAclState, - BtBondState, BtDeviceType, BtDiscoveryState, BtHciErrorCode, BtPinCode, BtPropertyType, - BtScanMode, BtSspVariant, BtState, BtStatus, BtTransport, RawAddress, Uuid, Uuid128Bit, + BtBondState, BtConnectionState, BtDeviceType, BtDiscoveryState, BtHciErrorCode, BtPinCode, + BtPropertyType, BtScanMode, BtSspVariant, BtState, BtStatus, BtTransport, RawAddress, Uuid, + Uuid128Bit, }; use bt_topshim::{ metrics, @@ -127,7 +128,7 @@ pub trait IBluetooth { fn get_bonded_devices(&self) -> Vec<BluetoothDevice>; /// Gets the bond state of a single device. - fn get_bond_state(&self, device: BluetoothDevice) -> u32; + fn get_bond_state(&self, device: BluetoothDevice) -> BtBondState; /// Set pin on bonding device. fn set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool; @@ -153,8 +154,14 @@ pub trait IBluetooth { /// Gets the class of the remote device. fn get_remote_class(&self, device: BluetoothDevice) -> u32; + /// Gets whether the remote device is connected. + fn get_remote_connected(&self, device: BluetoothDevice) -> bool; + + /// Returns a list of connected devices. + fn get_connected_devices(&self) -> Vec<BluetoothDevice>; + /// Gets the connection state of a single device. - fn get_connection_state(&self, device: BluetoothDevice) -> u32; + fn get_connection_state(&self, device: BluetoothDevice) -> BtConnectionState; /// Gets the connection state of a specific profile. fn get_profile_connection_state(&self, profile: Profile) -> u32; @@ -1181,10 +1188,10 @@ impl IBluetooth for Bluetooth { devices } - fn get_bond_state(&self, device: BluetoothDevice) -> u32 { + fn get_bond_state(&self, device: BluetoothDevice) -> BtBondState { match self.bonded_devices.get(&device.address) { - Some(device) => device.bond_state.to_u32().unwrap(), - None => BtBondState::NotBonded.to_u32().unwrap(), + Some(device) => device.bond_state.clone(), + None => BtBondState::NotBonded, } } @@ -1309,14 +1316,44 @@ impl IBluetooth for Bluetooth { } } - fn get_connection_state(&self, device: BluetoothDevice) -> u32 { + fn get_remote_connected(&self, device: BluetoothDevice) -> bool { + self.get_connection_state(device) != BtConnectionState::NotConnected + } + + fn get_connected_devices(&self) -> Vec<BluetoothDevice> { + let bonded_connected: HashMap<String, BluetoothDevice> = self + .bonded_devices + .iter() + .filter(|(_, v)| v.acl_state == BtAclState::Connected) + .map(|(k, v)| (k.clone(), v.info.clone())) + .collect(); + let mut found_connected: Vec<BluetoothDevice> = self + .found_devices + .iter() + .filter(|(k, v)| { + v.acl_state == BtAclState::Connected + && !bonded_connected.contains_key(&k.to_string()) + }) + .map(|(_, v)| v.info.clone()) + .collect(); + + let mut all = + bonded_connected.iter().map(|(_, v)| v.clone()).collect::<Vec<BluetoothDevice>>(); + all.append(&mut found_connected); + + all + } + + fn get_connection_state(&self, device: BluetoothDevice) -> BtConnectionState { let addr = RawAddress::from_string(device.address.clone()); if addr.is_none() { warn!("Can't check connection state. Address {} is not valid.", device.address); - return 0; + return BtConnectionState::NotConnected; } + // The underlying api adds whether this is ENCRYPTED_BREDR or ENCRYPTED_LE. + // As long as it is non-zero, it is connected. self.intf.lock().unwrap().get_connection_state(&addr.unwrap()) } diff --git a/system/gd/rust/linux/stack/src/bluetooth_media.rs b/system/gd/rust/linux/stack/src/bluetooth_media.rs index 8e43bd2591..f25fea4573 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_media.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_media.rs @@ -60,8 +60,14 @@ pub trait IBluetoothMedia { fn set_hfp_volume(&mut self, volume: u8, address: String); fn start_audio_request(&mut self); fn stop_audio_request(&mut self); - fn get_a2dp_audio_started(&mut self) -> bool; - fn get_hfp_audio_started(&mut self) -> bool; + + /// Returns non-zero value iff A2DP audio has started. + fn get_a2dp_audio_started(&mut self, address: String) -> u8; + + /// Returns the negotiated codec (CVSD=1, mSBC=2) to use if HFP audio has started. + /// Returns 0 if HFP audio hasn't started. + fn get_hfp_audio_started(&mut self, address: String) -> u8; + fn get_presentation_position(&mut self) -> PresentationPosition; fn start_sco_call(&mut self, address: String); @@ -129,10 +135,10 @@ pub struct BluetoothMedia { a2dp: Option<A2dp>, avrcp: Option<Avrcp>, a2dp_states: HashMap<RawAddress, BtavConnectionState>, - a2dp_audio_state: BtavAudioState, + a2dp_audio_state: HashMap<RawAddress, BtavAudioState>, hfp: Option<Hfp>, hfp_states: HashMap<RawAddress, BthfConnectionState>, - hfp_audio_state: BthfAudioState, + hfp_audio_state: HashMap<RawAddress, BthfAudioState>, selectable_caps: HashMap<RawAddress, Vec<A2dpCodecConfig>>, hfp_caps: HashMap<RawAddress, HfpCodecCapability>, device_added_tasks: Arc<Mutex<HashMap<RawAddress, Option<JoinHandle<()>>>>>, @@ -153,10 +159,10 @@ impl BluetoothMedia { a2dp: None, avrcp: None, a2dp_states: HashMap::new(), - a2dp_audio_state: BtavAudioState::RemoteSuspend, + a2dp_audio_state: HashMap::new(), hfp: None, hfp_states: HashMap::new(), - hfp_audio_state: BthfAudioState::Disconnected, + hfp_audio_state: HashMap::new(), selectable_caps: HashMap::new(), hfp_caps: HashMap::new(), device_added_tasks: Arc::new(Mutex::new(HashMap::new())), @@ -183,7 +189,7 @@ impl BluetoothMedia { self.a2dp_states.insert(addr, state); } BtavConnectionState::Disconnected => { - self.a2dp_audio_state = BtavAudioState::RemoteSuspend; + self.a2dp_audio_state.remove(&addr); match self.a2dp_states.remove(&addr) { Some(_) => self.notify_media_capability_removed(addr), None => { @@ -196,8 +202,8 @@ impl BluetoothMedia { } } } - A2dpCallbacks::AudioState(_addr, state) => { - self.a2dp_audio_state = state; + A2dpCallbacks::AudioState(addr, state) => { + self.a2dp_audio_state.insert(addr, state); } A2dpCallbacks::AudioConfig(addr, _config, _local_caps, selectable_caps) => { self.selectable_caps.insert(addr, selectable_caps); @@ -253,6 +259,7 @@ impl BluetoothMedia { BthfConnectionState::Disconnected => { info!("[{}]: hfp disconnected.", addr.to_string()); self.hfp_caps.remove(&addr); + self.hfp_audio_state.remove(&addr); match self.hfp_states.remove(&addr) { Some(_) => self.notify_media_capability_removed(addr), None => { @@ -294,7 +301,7 @@ impl BluetoothMedia { } } - self.hfp_audio_state = state; + self.hfp_audio_state.insert(addr, state); } HfpCallbacks::VolumeUpdate(volume, addr) => { self.callbacks.lock().unwrap().for_all_callbacks(|callback| { @@ -631,17 +638,42 @@ impl IBluetoothMedia for BluetoothMedia { } } - fn get_a2dp_audio_started(&mut self) -> bool { - match self.a2dp_audio_state { - BtavAudioState::Started => true, - _ => false, + fn get_a2dp_audio_started(&mut self, address: String) -> u8 { + if let Some(addr) = RawAddress::from_string(address.clone()) { + match self.a2dp_audio_state.get(&addr) { + Some(BtavAudioState::Started) => 1, + _ => 0, + } + } else { + warn!("Invalid device string {}", address); + 0 } } - fn get_hfp_audio_started(&mut self) -> bool { - match self.hfp_audio_state { - BthfAudioState::Connected => true, - _ => false, + fn get_hfp_audio_started(&mut self, address: String) -> u8 { + if let Some(addr) = RawAddress::from_string(address.clone()) { + match self.hfp_audio_state.get(&addr) { + Some(BthfAudioState::Connected) => match self.hfp_caps.get(&addr) { + Some(caps) + if (*caps & HfpCodecCapability::MSBC) == HfpCodecCapability::MSBC => + { + 2 + } + Some(caps) + if (*caps & HfpCodecCapability::CVSD) == HfpCodecCapability::CVSD => + { + 1 + } + _ => { + warn!("hfp_caps not found, fallback to CVSD."); + 1 + } + }, + _ => 0, + } + } else { + warn!("Invalid device string {}", address); + 0 } } diff --git a/system/gd/rust/linux/stack/src/socket_manager.rs b/system/gd/rust/linux/stack/src/socket_manager.rs index 0e053afcda..49bb869837 100644 --- a/system/gd/rust/linux/stack/src/socket_manager.rs +++ b/system/gd/rust/linux/stack/src/socket_manager.rs @@ -423,8 +423,8 @@ pub struct BluetoothSocketManager { /// same runtime as RPC). runtime: Arc<Runtime>, - /// Topshim interface for socket. - sock: socket::BtSocket, + /// Topshim interface for socket. Must call initialize for this to be valid. + sock: Option<socket::BtSocket>, /// Monotonically increasing counter for socket id. Always access using /// `next_socket_id`. @@ -436,8 +436,7 @@ pub struct BluetoothSocketManager { impl BluetoothSocketManager { /// Constructs the IBluetooth implementation. - pub fn new(intf: Arc<Mutex<BluetoothInterface>>, tx: Sender<Message>) -> Self { - let sock = socket::BtSocket::new(&intf.lock().unwrap()); + pub fn new(tx: Sender<Message>) -> Self { let callbacks = Callbacks::new(tx.clone(), Message::SocketManagerCallbackDisconnected); let socket_counter: u64 = 1000; let futures = HashMap::new(); @@ -451,7 +450,22 @@ impl BluetoothSocketManager { .expect("Failed to make socket runtime."), ); - BluetoothSocketManager { callbacks, futures, listening, runtime, sock, socket_counter, tx } + BluetoothSocketManager { + callbacks, + futures, + listening, + runtime, + sock: None, + socket_counter, + tx, + } + } + + /// In order to access the underlying socket apis, we must initialize after + /// the btif layer has initialized. Thus, this must be called after intf is + /// init. + pub fn initialize(&mut self, intf: Arc<Mutex<BluetoothInterface>>) { + self.sock = Some(socket::BtSocket::new(&intf.lock().unwrap())); } // TODO(abps) - We need to save information about who the caller is so that @@ -476,23 +490,24 @@ impl BluetoothSocketManager { cbid: CallbackId, ) -> SocketResult { // Create listener socket pair - let (mut status, result) = self.sock.listen( - socket_info.sock_type.clone(), - socket_info.name.as_ref().unwrap_or(&String::new()).clone(), - match socket_info.uuid { - Some(u) => Some(u.uu.clone()), - None => None, - }, - match socket_info.sock_type { - SocketType::Rfcomm => socket_info.channel.unwrap_or(DYNAMIC_CHANNEL), - SocketType::L2cap | SocketType::L2capLe => { - socket_info.psm.unwrap_or(DYNAMIC_PSM_NO_SDP) - } - _ => 0, - }, - socket_info.flags, - self.get_caller_uid(), - ); + let (mut status, result) = + self.sock.as_ref().expect("Socket Manager not initialized").listen( + socket_info.sock_type.clone(), + socket_info.name.as_ref().unwrap_or(&String::new()).clone(), + match socket_info.uuid { + Some(u) => Some(u.uu.clone()), + None => None, + }, + match socket_info.sock_type { + SocketType::Rfcomm => socket_info.channel.unwrap_or(DYNAMIC_CHANNEL), + SocketType::L2cap | SocketType::L2capLe => { + socket_info.psm.unwrap_or(DYNAMIC_PSM_NO_SDP) + } + _ => 0, + }, + socket_info.flags, + self.get_caller_uid(), + ); // Put socket into listening list and return result. match result { @@ -582,17 +597,18 @@ impl BluetoothSocketManager { }; // Create connecting socket pair. - let (mut status, result) = self.sock.connect( - addr, - socket_info.sock_type.clone(), - match socket_info.uuid { - Some(u) => Some(u.uu.clone()), - None => None, - }, - socket_info.port, - socket_info.flags, - self.get_caller_uid(), - ); + let (mut status, result) = + self.sock.as_ref().expect("Socket manager not initialized").connect( + addr, + socket_info.sock_type.clone(), + match socket_info.uuid { + Some(u) => Some(u.uu.clone()), + None => None, + }, + socket_info.port, + socket_info.flags, + self.get_caller_uid(), + ); // Put socket into connecting list and return result. Connecting sockets // need to be listening for a completion event at which point they will diff --git a/system/gd/rust/linux/stack/src/suspend.rs b/system/gd/rust/linux/stack/src/suspend.rs index d27a04d77a..d1e4329bfd 100644 --- a/system/gd/rust/linux/stack/src/suspend.rs +++ b/system/gd/rust/linux/stack/src/suspend.rs @@ -158,8 +158,8 @@ impl ISuspend for Suspend { fn resume(&self) -> bool { self.intf.lock().unwrap().set_default_event_mask(); - // self.intf.lock().unwrap().set_event_filter_inquiry_result_all_devices(); - // self.intf.lock().unwrap().set_event_filter_connection_setup_all_devices(); + self.intf.lock().unwrap().set_event_filter_inquiry_result_all_devices(); + self.intf.lock().unwrap().set_event_filter_connection_setup_all_devices(); if self.is_connected_suspend { if self.was_a2dp_connected { // TODO(230604670): self.intf.lock().unwrap().restore_filter_accept_list(); diff --git a/system/gd/rust/shim/Android.bp b/system/gd/rust/shim/Android.bp index 7521f45792..b10cec8e73 100644 --- a/system/gd/rust/shim/Android.bp +++ b/system/gd/rust/shim/Android.bp @@ -60,7 +60,7 @@ rust_ffi_static { name: "libbt_shim_ffi", defaults: ["libbt_shim_defaults"], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } @@ -98,7 +98,7 @@ cc_library_static { ], host_supported: true, apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } @@ -115,7 +115,7 @@ cc_library_static { ], host_supported: true, apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } @@ -131,7 +131,7 @@ cc_library_static { generated_headers: ["libbt_shim_bridge_header", "cxx-bridge-header"], host_supported: true, apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } @@ -141,7 +141,7 @@ cc_library_headers { local_include_dirs: ["callbacks"], host_supported: true, apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } diff --git a/system/gd/rust/stack/Android.bp b/system/gd/rust/stack/Android.bp index 29ef4c1fea..77059d1c8f 100644 --- a/system/gd/rust/stack/Android.bp +++ b/system/gd/rust/stack/Android.bp @@ -36,7 +36,7 @@ rust_library { "libnum_derive", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", target: { @@ -116,7 +116,7 @@ cc_library_static { "libutils", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs index 80285799f6..e0469fbb2e 100644 --- a/system/gd/rust/topshim/src/btif.rs +++ b/system/gd/rust/topshim/src/btif.rs @@ -90,6 +90,7 @@ pub enum BtConnectionState { ConnectedOnly = 1, EncryptedBredr = 3, EncryptedLe = 5, + EncryptedBoth = 7, } impl From<i32> for BtConnectionState { @@ -1053,9 +1054,9 @@ impl BluetoothInterface { ccall!(self, cancel_bond, ffi_addr) } - pub fn get_connection_state(&self, addr: &RawAddress) -> u32 { + pub fn get_connection_state(&self, addr: &RawAddress) -> BtConnectionState { let ffi_addr = cast_to_const_ffi_address!(addr as *const RawAddress); - ccall!(self, get_connection_state, ffi_addr).to_u32().unwrap() + ccall!(self, get_connection_state, ffi_addr).into() } pub fn pin_reply( diff --git a/system/gd/storage/adapter_config.h b/system/gd/storage/adapter_config.h index 228a394867..97c8ee81e7 100644 --- a/system/gd/storage/adapter_config.h +++ b/system/gd/storage/adapter_config.h @@ -45,7 +45,13 @@ class AdapterConfig { return !(*this == other); } bool operator<(const AdapterConfig& other) const { - return config_ < other.config_ && memory_only_config_ < other.memory_only_config_ && section_ < other.section_; + if (config_ != other.config_) { + return config_ < other.config_; + } + if (memory_only_config_ != other.memory_only_config_) { + return memory_only_config_ < other.memory_only_config_; + } + return section_ < other.section_; } bool operator>(const AdapterConfig& rhs) const { return (rhs < *this); diff --git a/system/gd/storage/adapter_config_test.cc b/system/gd/storage/adapter_config_test.cc index e3c3791c67..eede771b39 100644 --- a/system/gd/storage/adapter_config_test.cc +++ b/system/gd/storage/adapter_config_test.cc @@ -61,3 +61,99 @@ TEST(AdapterConfigTest, equality_test) { ASSERT_NE(adapter_config_1, adapter_config_3); } +TEST(AdapterConfigTest, operator_less_than) { + ConfigCache config1(10, Device::kLinkKeyProperties); + ConfigCache config2(10, Device::kLinkKeyProperties); + ASSERT_NE(&config1, &config2); + ConfigCache* smaller_config_ptr = &config1; + ConfigCache* larger_config_ptr = &config2; + if (&config2 < &config1) { + smaller_config_ptr = &config2; + larger_config_ptr = &config1; + } + + ConfigCache memory_only_config1(10, {}); + ConfigCache memory_only_config2(10, {}); + ASSERT_NE(&memory_only_config1, &memory_only_config2); + ConfigCache* smaller_memory_only_config_ptr = &memory_only_config1; + ConfigCache* larger_memory_only_config_ptr = &memory_only_config2; + if (&memory_only_config2 < &memory_only_config1) { + smaller_memory_only_config_ptr = &memory_only_config2; + larger_memory_only_config_ptr = &memory_only_config1; + } + + bluetooth::hci::Address smaller_address = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}; + bluetooth::hci::Address larger_address = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x07}}; + + { + AdapterConfig adapter_config1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + AdapterConfig adapter_config2(larger_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(adapter_config1 < adapter_config2); + } + + { + AdapterConfig adapter_config1(larger_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + AdapterConfig adapter_config2(smaller_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + ASSERT_FALSE(adapter_config1 < adapter_config2); + } + + { + AdapterConfig adapter_config1(smaller_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + AdapterConfig adapter_config2(larger_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(adapter_config1 < adapter_config2); + } + + { + AdapterConfig adapter_config1(smaller_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + AdapterConfig adapter_config2(larger_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(adapter_config1 < adapter_config2); + } + + { + AdapterConfig adapter_config1(larger_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + AdapterConfig adapter_config2(smaller_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + ASSERT_FALSE(adapter_config1 < adapter_config2); + } + + { + AdapterConfig adapter_config1(larger_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + AdapterConfig adapter_config2(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_FALSE(adapter_config1 < adapter_config2); + } + + { + AdapterConfig adapter_config1(smaller_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + AdapterConfig adapter_config2(larger_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(adapter_config1 < adapter_config2); + } + + { + AdapterConfig adapter_config1(larger_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + AdapterConfig adapter_config2(smaller_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_FALSE(adapter_config1 < adapter_config2); + } + + { + AdapterConfig adapter_config1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + AdapterConfig adapter_config2(smaller_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(adapter_config1 < adapter_config2); + } + + { + AdapterConfig adapter_config1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + AdapterConfig adapter_config2(smaller_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(adapter_config1 < adapter_config2); + } + + { + AdapterConfig adapter_config1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + AdapterConfig adapter_config2(larger_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(adapter_config1 < adapter_config2); + } + + { + AdapterConfig adapter_config1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + AdapterConfig adapter_config2(smaller_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(adapter_config1 < adapter_config2); + } +} diff --git a/system/gd/storage/classic_device.h b/system/gd/storage/classic_device.h index 3e9874350b..e0fad9f3ae 100644 --- a/system/gd/storage/classic_device.h +++ b/system/gd/storage/classic_device.h @@ -49,7 +49,13 @@ class ClassicDevice { return !(*this == other); } bool operator<(const ClassicDevice& other) const { - return config_ < other.config_ && memory_only_config_ < other.memory_only_config_ && section_ < other.section_; + if (config_ != other.config_) { + return config_ < other.config_; + } + if (memory_only_config_ != other.memory_only_config_) { + return memory_only_config_ < other.memory_only_config_; + } + return section_ < other.section_; } bool operator>(const ClassicDevice& rhs) const { return (rhs < *this); diff --git a/system/gd/storage/classic_device_test.cc b/system/gd/storage/classic_device_test.cc index 751ee79c59..fd5654aa93 100644 --- a/system/gd/storage/classic_device_test.cc +++ b/system/gd/storage/classic_device_test.cc @@ -65,3 +65,99 @@ TEST(ClassicDeviceTest, equality_test) { ASSERT_NE(device1, device3); } +TEST(ClassicDeviceTest, operator_less_than) { + ConfigCache config1(10, Device::kLinkKeyProperties); + ConfigCache config2(10, Device::kLinkKeyProperties); + ASSERT_NE(&config1, &config2); + ConfigCache* smaller_config_ptr = &config1; + ConfigCache* larger_config_ptr = &config2; + if (&config2 < &config1) { + smaller_config_ptr = &config2; + larger_config_ptr = &config1; + } + + ConfigCache memory_only_config1(10, {}); + ConfigCache memory_only_config2(10, {}); + ASSERT_NE(&memory_only_config1, &memory_only_config2); + ConfigCache* smaller_memory_only_config_ptr = &memory_only_config1; + ConfigCache* larger_memory_only_config_ptr = &memory_only_config2; + if (&memory_only_config2 < &memory_only_config1) { + smaller_memory_only_config_ptr = &memory_only_config2; + larger_memory_only_config_ptr = &memory_only_config1; + } + + bluetooth::hci::Address smaller_address = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}; + bluetooth::hci::Address larger_address = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x07}}; + + { + ClassicDevice device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ClassicDevice device2(larger_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + ClassicDevice device1(larger_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ClassicDevice device2(smaller_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + ASSERT_FALSE(device1 < device2); + } + + { + ClassicDevice device1(smaller_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + ClassicDevice device2(larger_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + ClassicDevice device1(smaller_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + ClassicDevice device2(larger_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + ClassicDevice device1(larger_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + ClassicDevice device2(smaller_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + ASSERT_FALSE(device1 < device2); + } + + { + ClassicDevice device1(larger_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + ClassicDevice device2(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_FALSE(device1 < device2); + } + + { + ClassicDevice device1(smaller_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + ClassicDevice device2(larger_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + ClassicDevice device1(larger_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + ClassicDevice device2(smaller_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_FALSE(device1 < device2); + } + + { + ClassicDevice device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ClassicDevice device2(smaller_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + ClassicDevice device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ClassicDevice device2(smaller_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + ClassicDevice device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ClassicDevice device2(larger_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + ClassicDevice device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ClassicDevice device2(smaller_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(device1 < device2); + } +} diff --git a/system/gd/storage/device.h b/system/gd/storage/device.h index e610f57e28..e1b5fd97b7 100644 --- a/system/gd/storage/device.h +++ b/system/gd/storage/device.h @@ -132,7 +132,13 @@ class Device { return !(*this == other); } bool operator<(const Device& other) const { - return config_ < other.config_ && memory_only_config_ < other.memory_only_config_ && section_ < other.section_; + if (config_ != other.config_) { + return config_ < other.config_; + } + if (memory_only_config_ != other.memory_only_config_) { + return memory_only_config_ < other.memory_only_config_; + } + return section_ < other.section_; } bool operator>(const Device& rhs) const { return (rhs < *this); diff --git a/system/gd/storage/device_test.cc b/system/gd/storage/device_test.cc index 0706403ad4..307f403e97 100644 --- a/system/gd/storage/device_test.cc +++ b/system/gd/storage/device_test.cc @@ -237,3 +237,99 @@ TEST(DeviceTest, remove_config_test) { ASSERT_FALSE(config.GetProperty(address.ToString(), "Name")); } +TEST(DeviceTest, operator_less_than) { + ConfigCache config1(10, Device::kLinkKeyProperties); + ConfigCache config2(10, Device::kLinkKeyProperties); + ASSERT_NE(&config1, &config2); + ConfigCache* smaller_config_ptr = &config1; + ConfigCache* larger_config_ptr = &config2; + if (&config2 < &config1) { + smaller_config_ptr = &config2; + larger_config_ptr = &config1; + } + + ConfigCache memory_only_config1(10, {}); + ConfigCache memory_only_config2(10, {}); + ASSERT_NE(&memory_only_config1, &memory_only_config2); + ConfigCache* smaller_memory_only_config_ptr = &memory_only_config1; + ConfigCache* larger_memory_only_config_ptr = &memory_only_config2; + if (&memory_only_config2 < &memory_only_config1) { + smaller_memory_only_config_ptr = &memory_only_config2; + larger_memory_only_config_ptr = &memory_only_config1; + } + + bluetooth::hci::Address smaller_address = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}; + bluetooth::hci::Address larger_address = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x07}}; + + { + Device device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + Device device2(larger_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + Device device1(larger_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + Device device2(smaller_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + ASSERT_FALSE(device1 < device2); + } + + { + Device device1(smaller_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + Device device2(larger_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + Device device1(smaller_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + Device device2(larger_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + Device device1(larger_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + Device device2(smaller_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + ASSERT_FALSE(device1 < device2); + } + + { + Device device1(larger_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + Device device2(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_FALSE(device1 < device2); + } + + { + Device device1(smaller_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + Device device2(larger_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + Device device1(larger_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + Device device2(smaller_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_FALSE(device1 < device2); + } + + { + Device device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + Device device2(smaller_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + Device device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + Device device2(smaller_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + Device device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + Device device2(larger_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + Device device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + Device device2(smaller_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(device1 < device2); + } +} diff --git a/system/gd/storage/le_device.h b/system/gd/storage/le_device.h index 79e3045c5f..aec4f301e8 100644 --- a/system/gd/storage/le_device.h +++ b/system/gd/storage/le_device.h @@ -48,7 +48,13 @@ class LeDevice { return !(*this == other); } bool operator<(const LeDevice& other) const { - return config_ < other.config_ && memory_only_config_ < other.memory_only_config_ && section_ < other.section_; + if (config_ != other.config_) { + return config_ < other.config_; + } + if (memory_only_config_ != other.memory_only_config_) { + return memory_only_config_ < other.memory_only_config_; + } + return section_ < other.section_; } bool operator>(const LeDevice& rhs) const { return (rhs < *this); diff --git a/system/gd/storage/le_device_test.cc b/system/gd/storage/le_device_test.cc index 407f489ec2..26413568e7 100644 --- a/system/gd/storage/le_device_test.cc +++ b/system/gd/storage/le_device_test.cc @@ -65,3 +65,99 @@ TEST(LeDeviceTest, equality_test) { ASSERT_NE(device1, device3); } +TEST(LeDeviceTest, operator_less_than) { + ConfigCache config1(10, Device::kLinkKeyProperties); + ConfigCache config2(10, Device::kLinkKeyProperties); + ASSERT_NE(&config1, &config2); + ConfigCache* smaller_config_ptr = &config1; + ConfigCache* larger_config_ptr = &config2; + if (&config2 < &config1) { + smaller_config_ptr = &config2; + larger_config_ptr = &config1; + } + + ConfigCache memory_only_config1(10, {}); + ConfigCache memory_only_config2(10, {}); + ASSERT_NE(&memory_only_config1, &memory_only_config2); + ConfigCache* smaller_memory_only_config_ptr = &memory_only_config1; + ConfigCache* larger_memory_only_config_ptr = &memory_only_config2; + if (&memory_only_config2 < &memory_only_config1) { + smaller_memory_only_config_ptr = &memory_only_config2; + larger_memory_only_config_ptr = &memory_only_config1; + } + + bluetooth::hci::Address smaller_address = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}; + bluetooth::hci::Address larger_address = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x07}}; + + { + LeDevice device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + LeDevice device2(larger_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + LeDevice device1(larger_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + LeDevice device2(smaller_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + ASSERT_FALSE(device1 < device2); + } + + { + LeDevice device1(smaller_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + LeDevice device2(larger_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + LeDevice device1(smaller_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + LeDevice device2(larger_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + LeDevice device1(larger_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + LeDevice device2(smaller_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + ASSERT_FALSE(device1 < device2); + } + + { + LeDevice device1(larger_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + LeDevice device2(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_FALSE(device1 < device2); + } + + { + LeDevice device1(smaller_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + LeDevice device2(larger_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + LeDevice device1(larger_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + LeDevice device2(smaller_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_FALSE(device1 < device2); + } + + { + LeDevice device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + LeDevice device2(smaller_config_ptr, larger_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + LeDevice device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + LeDevice device2(smaller_config_ptr, smaller_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + LeDevice device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + LeDevice device2(larger_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + ASSERT_TRUE(device1 < device2); + } + + { + LeDevice device1(smaller_config_ptr, smaller_memory_only_config_ptr, smaller_address.ToString()); + LeDevice device2(smaller_config_ptr, larger_memory_only_config_ptr, larger_address.ToString()); + ASSERT_TRUE(device1 < device2); + } +} diff --git a/system/include/Android.bp b/system/include/Android.bp index cfe5897f33..7c8337109d 100644 --- a/system/include/Android.bp +++ b/system/include/Android.bp @@ -22,7 +22,7 @@ cc_library_headers { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } @@ -50,7 +50,7 @@ cc_library_headers { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } diff --git a/system/main/Android.bp b/system/main/Android.bp index 2e8cdcba18..295f21caa1 100644 --- a/system/main/Android.bp +++ b/system/main/Android.bp @@ -104,7 +104,7 @@ cc_library { scs: true, }, apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], host_supported: true, min_sdk_version: "30", diff --git a/system/osi/Android.bp b/system/osi/Android.bp index bcbac81bb1..9a3bf1c916 100644 --- a/system/osi/Android.bp +++ b/system/osi/Android.bp @@ -101,7 +101,7 @@ cc_library_static { }, min_sdk_version: "Tiramisu", apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], } diff --git a/system/packet/Android.bp b/system/packet/Android.bp index 1033fc6a42..cb70539fdf 100644 --- a/system/packet/Android.bp +++ b/system/packet/Android.bp @@ -20,7 +20,7 @@ cc_library_static { "lib-bt-packets-avrcp", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } diff --git a/system/packet/avrcp/Android.bp b/system/packet/avrcp/Android.bp index 2b52a75398..ba57362fcd 100644 --- a/system/packet/avrcp/Android.bp +++ b/system/packet/avrcp/Android.bp @@ -42,7 +42,7 @@ cc_library_static { "lib-bt-packets-base", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } diff --git a/system/packet/base/Android.bp b/system/packet/base/Android.bp index 268f47be03..f2b65dce27 100644 --- a/system/packet/base/Android.bp +++ b/system/packet/base/Android.bp @@ -19,7 +19,7 @@ cc_library_static { "packet_builder.cc", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "30", } diff --git a/system/profile/avrcp/Android.bp b/system/profile/avrcp/Android.bp index 72e9b1bb62..592101cabc 100644 --- a/system/profile/avrcp/Android.bp +++ b/system/profile/avrcp/Android.bp @@ -36,7 +36,7 @@ cc_library_static { "liblog", ], apex_available: [ - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "Tiramisu" } diff --git a/system/stack/btm/btm_sco.cc b/system/stack/btm/btm_sco.cc index e001441941..41be40c0c6 100644 --- a/system/stack/btm/btm_sco.cc +++ b/system/stack/btm/btm_sco.cc @@ -143,10 +143,6 @@ static void btm_esco_conn_rsp(uint16_t sco_inx, uint8_t hci_status, /* If parameters not specified use the default */ if (p_parms) { *p_setup = *p_parms; - } else if (p_sco->esco.data.link_type == BTM_LINK_TYPE_SCO || - !sco_peer_supports_esco_ev3(bda)) { - *p_setup = esco_parameters_for_codec( - SCO_CODEC_CVSD_D1, hfp_hal_interface::get_offload_enabled()); } else { /* Use the last setup passed thru BTM_SetEscoMode (or defaults) */ *p_setup = btm_cb.sco_cb.def_esco_parms; diff --git a/system/types/Android.bp b/system/types/Android.bp index 2009df6f15..b54c3f3cd1 100644 --- a/system/types/Android.bp +++ b/system/types/Android.bp @@ -20,7 +20,7 @@ cc_library_headers { "//apex_available:platform", "com.android.media", "com.android.media.swcodec", - "com.android.bluetooth" + "com.android.btservices" ], // As part of updatable mainline modules(media, swcodec), it should support at least 29(Q) min_sdk_version: "29", diff --git a/system/types/bluetooth/uuid.cc b/system/types/bluetooth/uuid.cc index d05f4370f0..40186ae5c4 100644 --- a/system/types/bluetooth/uuid.cc +++ b/system/types/bluetooth/uuid.cc @@ -155,6 +155,8 @@ Uuid Uuid::GetRandom() { bool Uuid::IsEmpty() const { return *this == kEmpty; } +bool Uuid::IsBase() const { return *this == kBase; } + void Uuid::UpdateUuid(const Uuid& uuid) { uu = uuid.uu; } diff --git a/system/types/bluetooth/uuid.h b/system/types/bluetooth/uuid.h index 893f5d2049..f3e6ec2f1f 100644 --- a/system/types/bluetooth/uuid.h +++ b/system/types/bluetooth/uuid.h @@ -106,6 +106,9 @@ class Uuid final { // Returns true if this UUID is equal to kEmpty bool IsEmpty() const; + // Returns true if this UUID is equal to kBase + bool IsBase() const; + // Update UUID with new value void UpdateUuid(const Uuid& uuid); diff --git a/system/udrv/Android.bp b/system/udrv/Android.bp index cf3011c71c..8ce6d71840 100644 --- a/system/udrv/Android.bp +++ b/system/udrv/Android.bp @@ -26,7 +26,7 @@ cc_library_static { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", ], min_sdk_version: "Tiramisu" } diff --git a/tools/rootcanal/Android.bp b/tools/rootcanal/Android.bp index 16a6f5b56b..e37c8dd256 100644 --- a/tools/rootcanal/Android.bp +++ b/tools/rootcanal/Android.bp @@ -97,6 +97,9 @@ cc_library_static { "include", ".", ], + export_generated_headers: [ + "BluetoothGeneratedPackets_h" + ], shared_libs: [ "liblog", ], diff --git a/tools/rootcanal/lmp/Android.bp b/tools/rootcanal/lmp/Android.bp index 78a60a07cd..e438e6a54c 100644 --- a/tools/rootcanal/lmp/Android.bp +++ b/tools/rootcanal/lmp/Android.bp @@ -19,7 +19,7 @@ rust_ffi { edition: "2018", proc_macros: ["libnum_derive"], rustlibs: [ - "libbt_packets", + "libbt_packets_nonapex", "libbytes", "libnum_bigint", "libnum_integer", diff --git a/tools/rootcanal/model/controller/dual_mode_controller.cc b/tools/rootcanal/model/controller/dual_mode_controller.cc index 4e67077879..a7615f7b33 100644 --- a/tools/rootcanal/model/controller/dual_mode_controller.cc +++ b/tools/rootcanal/model/controller/dual_mode_controller.cc @@ -790,7 +790,7 @@ void DualModeController::EnhancedSetupSynchronousConnection( auto receive_bandwidth = command_view.GetReceiveBandwidth(); if (transmit_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && - transmit_coding_format.coding_format_ == + input_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && transmit_bandwidth != input_bandwidth) { LOG_INFO( @@ -805,7 +805,7 @@ void DualModeController::EnhancedSetupSynchronousConnection( } if ((transmit_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT) != - (transmit_coding_format.coding_format_ == + (input_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT)) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Transmit_Coding_Format " @@ -821,7 +821,7 @@ void DualModeController::EnhancedSetupSynchronousConnection( // Controller shall not modify the data sent to the Host. if (receive_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && - receive_coding_format.coding_format_ == + output_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && receive_bandwidth != output_bandwidth) { LOG_INFO( @@ -836,7 +836,7 @@ void DualModeController::EnhancedSetupSynchronousConnection( } if ((receive_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT) != - (receive_coding_format.coding_format_ == + (output_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT)) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Receive_Coding_Format " @@ -935,7 +935,7 @@ void DualModeController::EnhancedAcceptSynchronousConnection( auto receive_bandwidth = command_view.GetReceiveBandwidth(); if (transmit_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && - transmit_coding_format.coding_format_ == + input_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && transmit_bandwidth != input_bandwidth) { LOG_INFO( @@ -950,7 +950,7 @@ void DualModeController::EnhancedAcceptSynchronousConnection( } if ((transmit_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT) != - (transmit_coding_format.coding_format_ == + (input_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT)) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Transmit_Coding_Format " @@ -966,7 +966,7 @@ void DualModeController::EnhancedAcceptSynchronousConnection( // Controller shall not modify the data sent to the Host. if (receive_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && - receive_coding_format.coding_format_ == + output_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && receive_bandwidth != output_bandwidth) { LOG_INFO( @@ -981,7 +981,7 @@ void DualModeController::EnhancedAcceptSynchronousConnection( } if ((receive_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT) != - (receive_coding_format.coding_format_ == + (output_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT)) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Receive_Coding_Format " diff --git a/tools/rootcanal/model/devices/device_properties.h b/tools/rootcanal/model/devices/device_properties.h index 3f61c3bc90..efe67f0583 100644 --- a/tools/rootcanal/model/devices/device_properties.h +++ b/tools/rootcanal/model/devices/device_properties.h @@ -33,6 +33,7 @@ using ::bluetooth::hci::EventCode; using ::bluetooth::hci::LLFeaturesBits; using ::bluetooth::hci::LMPFeaturesPage0Bits; using ::bluetooth::hci::LMPFeaturesPage1Bits; +using ::bluetooth::hci::LMPFeaturesPage2Bits; static constexpr uint64_t Page0LmpFeatures() { LMPFeaturesPage0Bits features[] = { @@ -103,6 +104,17 @@ static constexpr uint64_t Page1LmpFeatures() { return value; } +static constexpr uint64_t Page2LmpFeatures() { + LMPFeaturesPage2Bits features[] = { + LMPFeaturesPage2Bits::SECURE_CONNECTIONS_CONTROLLER_SUPPORT, + }; + + uint64_t value = 0; + for (unsigned i = 0; i < sizeof(features) / sizeof(*features); i++) + value |= static_cast<uint64_t>(features[i]); + return value; +} + static constexpr uint64_t LlFeatures() { LLFeaturesBits features[] = { LLFeaturesBits::LE_ENCRYPTION, @@ -452,8 +464,8 @@ class DeviceProperties { std::vector<uint8_t> supported_codecs_; std::vector<uint32_t> vendor_specific_codecs_; std::array<uint8_t, 64> supported_commands_; - std::array<uint64_t, 2> extended_features_{ - {Page0LmpFeatures(), Page1LmpFeatures()}}; + std::array<uint64_t, 3> extended_features_{ + {Page0LmpFeatures(), Page1LmpFeatures(), Page2LmpFeatures()}}; ClassOfDevice class_of_device_{{0, 0, 0}}; std::vector<uint8_t> extended_inquiry_data_; std::array<uint8_t, 248> name_{}; |