From 37a10c6f8e4b7f92acdeb0602c0396146df35095 Mon Sep 17 00:00:00 2001 From: changbetty Date: Wed, 11 Jan 2023 16:57:46 +0000 Subject: [LE Audio] To fix the QR Code parse error Bug: 242023882 Test: manual test CRs-Fixed: 3558573 Change-Id: I4dcfb72a038289a480bff21f2ec4756edb441eb2 (cherry picked from commit 429c14f3051450a94e58bcd310218123748159a6) --- .../bluetooth/BluetoothBroadcastUtils.java | 4 +- .../LocalBluetoothLeBroadcastMetadata.java | 199 ++++++++++++++------- 2 files changed, 138 insertions(+), 65 deletions(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java index 1f7260972f24..a80061efb19a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java @@ -53,8 +53,8 @@ public final class BluetoothBroadcastUtils { static final String PREFIX_BT_SYNC_INTERVAL = "SI:"; static final String PREFIX_BT_IS_ENCRYPTED = "E:"; static final String PREFIX_BT_BROADCAST_CODE = "C:"; - static final String PREFIX_BT_PRESENTATION_DELAY = "D:"; - static final String PREFIX_BT_SUBGROUPS = "G:"; + static final String PREFIX_BT_PRESENTATION_DELAY = "PD:"; + static final String PREFIX_BT_SUBGROUPS = "SG:"; static final String PREFIX_BT_ANDROID_VERSION = "V:"; // BluetoothLeBroadcastSubgroup diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java index d2329c5f8f24..a65648c38d42 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java @@ -29,7 +29,9 @@ import java.io.ByteArrayOutputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -39,6 +41,43 @@ public class LocalBluetoothLeBroadcastMetadata { private static final String METADATA_START = "<"; private static final String METADATA_END = ">"; private static final String PATTERN_REGEX = "<(.*?)>"; + private static final String PATTERN_BT_BROADCAST_METADATA = + "T:<(.*?)>;+D:<(.*?)>;+AS:<(.*?)>;+B:<(.*?)>;+SI:<(.*?)>;+E:<(.*?)>;+C:<(.*?)>;" + + "+PD:<(.*?)>;+SG:(.*)"; + private static final String PATTERN_BT_SUBGROUP = + "CID:<(.*?)>;+CC:<(.*?);>;+AC:<(.*?);>;+CP:<(.*?)>;+BC:<(.*)>;>;"; + private static final String PATTERN_BT_CHANNEL = "CI:<(.*?)>;+BCCM:<(.*?);>;"; + + /* Index for BluetoothLeBroadcastMetadata */ + private static int MATCH_INDEX_ADDRESS_TYPE = 1; + private static int MATCH_INDEX_DEVICE = 2; + private static int MATCH_INDEX_ADVERTISING_SID = 3; + private static int MATCH_INDEX_BROADCAST_ID = 4; + private static int MATCH_INDEX_SYNC_INTERVAL = 5; + private static int MATCH_INDEX_IS_ENCRYPTED = 6; + private static int MATCH_INDEX_BROADCAST_CODE = 7; + private static int MATCH_INDEX_PRESENTATION_DELAY = 8; + private static int MATCH_INDEX_SUBGROUPS = 9; + + /* Index for BluetoothLeBroadcastSubgroup */ + private static int MATCH_INDEX_CODEC_ID = 1; + private static int MATCH_INDEX_CODEC_CONFIG = 2; + private static int MATCH_INDEX_AUDIO_CONTENT = 3; + private static int MATCH_INDEX_CHANNEL_PREF = 4; + private static int MATCH_INDEX_BROADCAST_CHANNEL = 5; + + /* Index for BluetoothLeAudioCodecConfigMetadata */ + private static int LIST_INDEX_AUDIO_LOCATION = 0; + private static int LIST_INDEX_CODEC_CONFIG_RAW_METADATA = 1; + + /* Index for BluetoothLeAudioContentMetadata */ + private static int LIST_INDEX_PROGRAM_INFO = 0; + private static int LIST_INDEX_LANGUAGE = 1; + private static int LIST_INDEX_AUDIO_CONTENT_RAW_METADATA = 2; + + /* Index for BluetoothLeBroadcastChannel */ + private static int MATCH_INDEX_CHANNEL_INDEX = 1; + private static int MATCH_INDEX_CHANNEL_CODEC_CONFIG = 2; private BluetoothLeBroadcastSubgroup mSubgroup; private List mSubgroupList; @@ -56,17 +95,20 @@ public class LocalBluetoothLeBroadcastMetadata { private byte[] mBroadcastCode; // BluetoothLeBroadcastSubgroup - private long mCodecId; + private int mCodecId; private BluetoothLeAudioContentMetadata mContentMetadata; private BluetoothLeAudioCodecConfigMetadata mConfigMetadata; - private BluetoothLeBroadcastChannel mChannel; + private Boolean mNoChannelPreference; + private List mChannel; // BluetoothLeAudioCodecConfigMetadata private long mAudioLocation; + private byte[] mCodecConfigMetadata; // BluetoothLeAudioContentMetadata private String mLanguage; private String mProgramInfo; + private byte[] mAudioContentMetadata; // BluetoothLeBroadcastChannel private boolean mIsSelected; @@ -136,6 +178,7 @@ public class LocalBluetoothLeBroadcastMetadata { for (BluetoothLeBroadcastSubgroup subgroup: subgroupList) { String audioCodec = convertAudioCodecConfigToString(subgroup.getCodecSpecificConfig()); String audioContent = convertAudioContentToString(subgroup.getContentMetadata()); + boolean hasChannelPreference = subgroup.hasChannelPreference(); String channels = convertChannelToString(subgroup.getChannels()); subgroupString = new StringBuilder() .append(BluetoothBroadcastUtils.PREFIX_BTSG_CODEC_ID) @@ -147,6 +190,9 @@ public class LocalBluetoothLeBroadcastMetadata { .append(BluetoothBroadcastUtils.PREFIX_BTSG_AUDIO_CONTENT) .append(METADATA_START).append(audioContent).append(METADATA_END) .append(BluetoothBroadcastUtils.DELIMITER_QR_CODE) + .append(BluetoothBroadcastUtils.PREFIX_BTSG_CHANNEL_PREF) + .append(METADATA_START).append(hasChannelPreference).append(METADATA_END) + .append(BluetoothBroadcastUtils.DELIMITER_QR_CODE) .append(BluetoothBroadcastUtils.PREFIX_BTSG_BROADCAST_CHANNEL) .append(METADATA_START).append(channels).append(METADATA_END) .append(BluetoothBroadcastUtils.DELIMITER_QR_CODE) @@ -212,19 +258,18 @@ public class LocalBluetoothLeBroadcastMetadata { if (DEBUG) { Log.d(TAG, "Convert " + qrCodeString + "to BluetoothLeBroadcastMetadata"); } - Pattern pattern = Pattern.compile(PATTERN_REGEX); + + Pattern pattern = Pattern.compile(PATTERN_BT_BROADCAST_METADATA); Matcher match = pattern.matcher(qrCodeString); if (match.find()) { - ArrayList resultList = new ArrayList<>(); - resultList.add(match.group(1)); - mSourceAddressType = Integer.parseInt(resultList.get(0)); + mSourceAddressType = Integer.parseInt(match.group(MATCH_INDEX_ADDRESS_TYPE)); mSourceDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice( - resultList.get(1)); - mSourceAdvertisingSid = Integer.parseInt(resultList.get(2)); - mBroadcastId = Integer.parseInt(resultList.get(3)); - mPaSyncInterval = Integer.parseInt(resultList.get(4)); - mIsEncrypted = Boolean.valueOf(resultList.get(5)); - String bcode = resultList.get(6); + match.group(MATCH_INDEX_DEVICE)); + mSourceAdvertisingSid = Integer.parseInt(match.group(MATCH_INDEX_ADVERTISING_SID)); + mBroadcastId = Integer.parseInt(match.group(MATCH_INDEX_BROADCAST_ID)); + mPaSyncInterval = Integer.parseInt(match.group(MATCH_INDEX_SYNC_INTERVAL)); + mIsEncrypted = Boolean.valueOf(match.group(MATCH_INDEX_IS_ENCRYPTED)); + String bcode = match.group(MATCH_INDEX_BROADCAST_CODE); mBroadcastCode = null; if (!bcode.equals("[]")) { mBroadcastCode = Arrays.stream(bcode.substring(1, bcode.length()-1).split(",")) @@ -235,13 +280,22 @@ public class LocalBluetoothLeBroadcastMetadata { (b1, b2)->b1.write(b2.toByteArray(), 0, b2.size())) .toByteArray(); } - mPresentationDelayMicros = Integer.parseInt(resultList.get(7)); - mSubgroup = convertToSubgroup(resultList.get(8)); - + mPresentationDelayMicros = + Integer.parseInt(match.group(MATCH_INDEX_PRESENTATION_DELAY)); if (DEBUG) { - Log.d(TAG, "Converted qrCodeString result: " + match.group()); + Log.d(TAG, "Converted qrCodeString result: " + + " ,Type = " + mSourceAddressType + + " ,Device = " + mSourceDevice + + " ,AdSid = " + mSourceAdvertisingSid + + " ,BroadcastId = " + mBroadcastId + + " ,paSync = " + mPaSyncInterval + + " ,encrypted = " + mIsEncrypted + + " ,BroadcastCode = " + Arrays.toString(mBroadcastCode) + + " ,delay = " + mPresentationDelayMicros); } + mSubgroup = convertToSubgroup(match.group(MATCH_INDEX_SUBGROUPS)); + return new BluetoothLeBroadcastMetadata.Builder() .setSourceDevice(mSourceDevice, mSourceAddressType) .setSourceAdvertisingSid(mSourceAdvertisingSid) @@ -265,26 +319,26 @@ public class LocalBluetoothLeBroadcastMetadata { if (DEBUG) { Log.d(TAG, "Convert " + subgroupString + "to BluetoothLeBroadcastSubgroup"); } - Pattern pattern = Pattern.compile(PATTERN_REGEX); + Pattern pattern = Pattern.compile(PATTERN_BT_SUBGROUP); Matcher match = pattern.matcher(subgroupString); if (match.find()) { - ArrayList resultList = new ArrayList<>(); - resultList.add(match.group(1)); - mCodecId = Long.getLong(resultList.get(0)); - mConfigMetadata = convertToConfigMetadata(resultList.get(1)); - mContentMetadata = convertToContentMetadata(resultList.get(2)); - mChannel = convertToChannel(resultList.get(3), mConfigMetadata); - - if (DEBUG) { - Log.d(TAG, "Converted subgroupString result: " + match.group()); + mCodecId = Integer.parseInt(match.group(MATCH_INDEX_CODEC_ID)); + mConfigMetadata = convertToConfigMetadata(match.group(MATCH_INDEX_CODEC_CONFIG)); + mContentMetadata = convertToContentMetadata(match.group(MATCH_INDEX_AUDIO_CONTENT)); + mNoChannelPreference = Boolean.valueOf(match.group(MATCH_INDEX_CHANNEL_PREF)); + mChannel = + convertToChannel(match.group(MATCH_INDEX_BROADCAST_CHANNEL), mConfigMetadata); + + BluetoothLeBroadcastSubgroup.Builder subgroupBuilder = + new BluetoothLeBroadcastSubgroup.Builder(); + subgroupBuilder.setCodecId(mCodecId); + subgroupBuilder.setCodecSpecificConfig(mConfigMetadata); + subgroupBuilder.setContentMetadata(mContentMetadata); + + for (BluetoothLeBroadcastChannel channel : mChannel) { + subgroupBuilder.addChannel(channel); } - - return new BluetoothLeBroadcastSubgroup.Builder() - .setCodecId(mCodecId) - .setCodecSpecificConfig(mConfigMetadata) - .setContentMetadata(mContentMetadata) - .addChannel(mChannel) - .build(); + return subgroupBuilder.build(); } else { if (DEBUG) { Log.d(TAG, @@ -302,15 +356,17 @@ public class LocalBluetoothLeBroadcastMetadata { } Pattern pattern = Pattern.compile(PATTERN_REGEX); Matcher match = pattern.matcher(configMetadataString); - if (match.find()) { - ArrayList resultList = new ArrayList<>(); + ArrayList resultList = new ArrayList<>(); + while (match.find()) { resultList.add(match.group(1)); - mAudioLocation = Long.getLong(resultList.get(0)); - - if (DEBUG) { - Log.d(TAG, "Converted configMetadataString result: " + match.group()); - } - + Log.d(TAG, "Codec Config match : " + match.group(1)); + } + if (DEBUG) { + Log.d(TAG, "Converted configMetadataString result: " + resultList.size()); + } + if (resultList.size() > 0) { + mAudioLocation = Long.parseLong(resultList.get(LIST_INDEX_AUDIO_LOCATION)); + mCodecConfigMetadata = resultList.get(LIST_INDEX_CODEC_CONFIG_RAW_METADATA).getBytes(); return new BluetoothLeAudioCodecConfigMetadata.Builder() .setAudioLocation(mAudioLocation) .build(); @@ -330,14 +386,25 @@ public class LocalBluetoothLeBroadcastMetadata { } Pattern pattern = Pattern.compile(PATTERN_REGEX); Matcher match = pattern.matcher(contentMetadataString); - if (match.find()) { - ArrayList resultList = new ArrayList<>(); + ArrayList resultList = new ArrayList<>(); + while (match.find()) { + Log.d(TAG, "Audio Content match : " + match.group(1)); resultList.add(match.group(1)); - mProgramInfo = resultList.get(0); - mLanguage = resultList.get(1); - - if (DEBUG) { - Log.d(TAG, "Converted contentMetadataString result: " + match.group()); + } + if (DEBUG) { + Log.d(TAG, "Converted contentMetadataString result: " + resultList.size()); + } + if (resultList.size() > 0) { + mProgramInfo = resultList.get(LIST_INDEX_PROGRAM_INFO); + mLanguage = resultList.get(LIST_INDEX_LANGUAGE); + mAudioContentMetadata = + resultList.get(LIST_INDEX_AUDIO_CONTENT_RAW_METADATA).getBytes(); + + /* TODO(b/265253566) : Need to set the default value for language when the user starts + * the broadcast. + */ + if (mLanguage.equals("null")) { + mLanguage = "eng"; } return new BluetoothLeAudioContentMetadata.Builder() @@ -353,28 +420,34 @@ public class LocalBluetoothLeBroadcastMetadata { } } - private BluetoothLeBroadcastChannel convertToChannel(String channelString, + private List convertToChannel(String channelString, BluetoothLeAudioCodecConfigMetadata configMetadata) { if (DEBUG) { Log.d(TAG, "Convert " + channelString + "to BluetoothLeBroadcastChannel"); } - Pattern pattern = Pattern.compile(PATTERN_REGEX); + Pattern pattern = Pattern.compile(PATTERN_BT_CHANNEL); Matcher match = pattern.matcher(channelString); - if (match.find()) { - ArrayList resultList = new ArrayList<>(); - resultList.add(match.group(1)); - mIsSelected = Boolean.valueOf(resultList.get(0)); - mChannelIndex = Integer.parseInt(resultList.get(1)); + Map channel = + new HashMap(); + while (match.find()) { + channel.put(Integer.parseInt(match.group(MATCH_INDEX_CHANNEL_INDEX)), + convertToConfigMetadata(match.group(MATCH_INDEX_CHANNEL_CODEC_CONFIG))); + } - if (DEBUG) { - Log.d(TAG, "Converted channelString result: " + match.group()); + if (channel.size() > 0) { + mIsSelected = false; + ArrayList broadcastChannelList = new ArrayList<>(); + for (Map.Entry entry : + channel.entrySet()) { + + broadcastChannelList.add( + new BluetoothLeBroadcastChannel.Builder() + .setSelected(mIsSelected) + .setChannelIndex(entry.getKey()) + .setCodecMetadata(entry.getValue()) + .build()); } - - return new BluetoothLeBroadcastChannel.Builder() - .setSelected(mIsSelected) - .setChannelIndex(mChannelIndex) - .setCodecMetadata(configMetadata) - .build(); + return broadcastChannelList; } else { if (DEBUG) { Log.d(TAG, -- cgit v1.2.3 From b20e149697948ed1a2cb642183d87c012dd8db3a Mon Sep 17 00:00:00 2001 From: xiaowang Date: Wed, 19 Jul 2023 17:07:15 +0800 Subject: [LeAudio] Enable regex dotall mode for Metadata CRs-Fixed: 3558573 Change-Id: I55668c1602b56596091a30d4e8faa68b8c72f1c9 --- .../bluetooth/LocalBluetoothLeBroadcastMetadata.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java index a65648c38d42..d7393abdafa5 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java @@ -259,7 +259,7 @@ public class LocalBluetoothLeBroadcastMetadata { Log.d(TAG, "Convert " + qrCodeString + "to BluetoothLeBroadcastMetadata"); } - Pattern pattern = Pattern.compile(PATTERN_BT_BROADCAST_METADATA); + Pattern pattern = Pattern.compile(PATTERN_BT_BROADCAST_METADATA, Pattern.DOTALL); Matcher match = pattern.matcher(qrCodeString); if (match.find()) { mSourceAddressType = Integer.parseInt(match.group(MATCH_INDEX_ADDRESS_TYPE)); @@ -319,7 +319,7 @@ public class LocalBluetoothLeBroadcastMetadata { if (DEBUG) { Log.d(TAG, "Convert " + subgroupString + "to BluetoothLeBroadcastSubgroup"); } - Pattern pattern = Pattern.compile(PATTERN_BT_SUBGROUP); + Pattern pattern = Pattern.compile(PATTERN_BT_SUBGROUP, Pattern.DOTALL); Matcher match = pattern.matcher(subgroupString); if (match.find()) { mCodecId = Integer.parseInt(match.group(MATCH_INDEX_CODEC_ID)); @@ -354,7 +354,7 @@ public class LocalBluetoothLeBroadcastMetadata { Log.d(TAG, "Convert " + configMetadataString + "to BluetoothLeAudioCodecConfigMetadata"); } - Pattern pattern = Pattern.compile(PATTERN_REGEX); + Pattern pattern = Pattern.compile(PATTERN_REGEX, Pattern.DOTALL); Matcher match = pattern.matcher(configMetadataString); ArrayList resultList = new ArrayList<>(); while (match.find()) { @@ -384,7 +384,7 @@ public class LocalBluetoothLeBroadcastMetadata { if (DEBUG) { Log.d(TAG, "Convert " + contentMetadataString + "to BluetoothLeAudioContentMetadata"); } - Pattern pattern = Pattern.compile(PATTERN_REGEX); + Pattern pattern = Pattern.compile(PATTERN_REGEX, Pattern.DOTALL); Matcher match = pattern.matcher(contentMetadataString); ArrayList resultList = new ArrayList<>(); while (match.find()) { @@ -425,7 +425,7 @@ public class LocalBluetoothLeBroadcastMetadata { if (DEBUG) { Log.d(TAG, "Convert " + channelString + "to BluetoothLeBroadcastChannel"); } - Pattern pattern = Pattern.compile(PATTERN_BT_CHANNEL); + Pattern pattern = Pattern.compile(PATTERN_BT_CHANNEL, Pattern.DOTALL); Matcher match = pattern.matcher(channelString); Map channel = new HashMap(); -- cgit v1.2.3