Loading android/app/src/com/android/bluetooth/Utils.java +23 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.Charset; Loading Loading @@ -1121,4 +1122,26 @@ public final class Utils { } return false; } /** * CCC descriptor short integer value to string. * @param cccValue the short value of CCC descriptor * @return String value representing CCC state */ public static String cccIntToStr(Short cccValue) { String string = ""; if (cccValue == 0) { return string += "NO SUBSCRIPTION"; } if (BigInteger.valueOf(cccValue).testBit(0)) { string += "NOTIFICATION"; } if (BigInteger.valueOf(cccValue).testBit(1)) { string += string.isEmpty() ? "INDICATION" : "|INDICATION"; } return string; } } android/app/src/com/android/bluetooth/mcp/McpService.java +14 −1 Original line number Diff line number Diff line Loading @@ -175,6 +175,18 @@ public class McpService extends ProfileService { gmcs.dump(sb); } } for (Map.Entry<BluetoothDevice, Integer> entry : mDeviceAuthorizations.entrySet()) { String accessString; if (entry.getValue() == BluetoothDevice.ACCESS_REJECTED) { accessString = "ACCESS_REJECTED"; } else if (entry.getValue() == BluetoothDevice.ACCESS_ALLOWED) { accessString = "ACCESS_ALLOWED"; } else { accessString = "ACCESS_UNKNOWN"; } sb.append("\n\t\tDevice: " + entry.getKey() + ", access: " + accessString); } } public void onDeviceUnauthorized(BluetoothDevice device) { Loading @@ -188,7 +200,8 @@ public class McpService extends ProfileService { } public void setDeviceAuthorized(BluetoothDevice device, boolean isAuthorized) { Log.i(TAG, "setDeviceAuthorized(): device: " + device + ", isAuthorized: " + isAuthorized); Log.i(TAG, "\tsetDeviceAuthorized(): device: " + device + ", isAuthorized: " + isAuthorized); int authorization = isAuthorized ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED; mDeviceAuthorizations.put(device, authorization); Loading android/app/src/com/android/bluetooth/mcp/MediaControlGattService.java +69 −1 Original line number Diff line number Diff line Loading @@ -147,6 +147,56 @@ public class MediaControlGattService implements MediaControlGattServiceInterface private LeAudioService mLeAudioService; private AdapterService mAdapterService; private static String mcsUuidToString(UUID uuid) { if (uuid.equals(UUID_PLAYER_NAME)) { return "PLAYER_NAME"; } else if (uuid.equals(UUID_PLAYER_ICON_OBJ_ID)) { return "PLAYER_ICON_OBJ_ID"; } else if (uuid.equals(UUID_PLAYER_ICON_URL)) { return "PLAYER_ICON_URL"; } else if (uuid.equals(UUID_TRACK_CHANGED)) { return "TRACK_CHANGED"; } else if (uuid.equals(UUID_TRACK_TITLE)) { return "TRACK_TITLE"; } else if (uuid.equals(UUID_TRACK_DURATION)) { return "TRACK_DURATION"; } else if (uuid.equals(UUID_TRACK_POSITION)) { return "TRACK_POSITION"; } else if (uuid.equals(UUID_PLAYBACK_SPEED)) { return "PLAYBACK_SPEED"; } else if (uuid.equals(UUID_SEEKING_SPEED)) { return "SEEKING_SPEED"; } else if (uuid.equals(UUID_CURRENT_TRACK_SEGMENT_OBJ_ID)) { return "CURRENT_TRACK_SEGMENT_OBJ_ID"; } else if (uuid.equals(UUID_CURRENT_TRACK_OBJ_ID)) { return "CURRENT_TRACK_OBJ_ID"; } else if (uuid.equals(UUID_NEXT_TRACK_OBJ_ID)) { return "NEXT_TRACK_OBJ_ID"; } else if (uuid.equals(UUID_CURRENT_GROUP_OBJ_ID)) { return "CURRENT_GROUP_OBJ_ID"; } else if (uuid.equals(UUID_PARENT_GROUP_OBJ_ID)) { return "PARENT_GROUP_OBJ_ID"; } else if (uuid.equals(UUID_PLAYING_ORDER)) { return "PLAYING_ORDER"; } else if (uuid.equals(UUID_PLAYING_ORDER_SUPPORTED)) { return "PLAYING_ORDER_SUPPORTED"; } else if (uuid.equals(UUID_MEDIA_STATE)) { return "MEDIA_STATE"; } else if (uuid.equals(UUID_MEDIA_CONTROL_POINT)) { return "MEDIA_CONTROL_POINT"; } else if (uuid.equals(UUID_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED)) { return "MEDIA_CONTROL_POINT_OPCODES_SUPPORTED"; } else if (uuid.equals(UUID_SEARCH_RESULT_OBJ_ID)) { return "SEARCH_RESULT_OBJ_ID"; } else if (uuid.equals(UUID_SEARCH_CONTROL_POINT)) { return "SEARCH_CONTROL_POINT"; } else if (uuid.equals(UUID_CONTENT_CONTROL_ID)) { return "CONTENT_CONTROL_ID"; } else { return "UNKNOWN(" + uuid + ")"; } } private static class GattOpContext { public enum Operation { READ_CHARACTERISTIC, Loading Loading @@ -1960,7 +2010,25 @@ public class MediaControlGattService implements MediaControlGattServiceInterface public void dump(StringBuilder sb) { sb.append("\tMediaControlService instance:"); sb.append("\n\t\tCcid = " + mCcid); sb.append("\n\t\tFeatures = " + String.format("0x%08X", mFeatures)); sb.append("\n\t\tFeatures:" + ServiceFeature.featuresToString(mFeatures, "\n\t\t\t")); BluetoothGattCharacteristic characteristic = mCharacteristics.get(CharId.PLAYER_NAME); if (characteristic == null) { sb.append("\n\t\tPlayer name: <No Player>"); } else { sb.append("\n\t\tPlayer name: " + characteristic.getStringValue(0)); } sb.append("\n\t\tCurrentPlaybackState = " + mCurrentMediaState); for (Map.Entry<String, HashMap<UUID, Short>> deviceEntry : mCccDescriptorValues.entrySet()) { sb.append("\n\t\tCCC states for device: " + "xx:xx:xx:xx:" + deviceEntry.getKey().substring(12)); for (Map.Entry<UUID, Short> entry : deviceEntry.getValue().entrySet()) { sb.append("\n\t\t\tCharacteristic: " + mcsUuidToString(entry.getKey()) + ", value: " + Utils.cccIntToStr(entry.getValue())); } } } } android/app/src/com/android/bluetooth/mcp/ServiceFeature.java +17 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package com.android.bluetooth.mcp; import java.util.BitSet; /** * Service features definition */ Loading Loading @@ -103,4 +105,19 @@ public final class ServiceFeature { return "UNKNOWN(0x" + Long.toHexString(serviceFeature) + ")"; } static String featuresToString(long serviceFeatures, String indent) { BitSet bs = BitSet.valueOf(new long[] {serviceFeatures}); String string = ""; for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { if (i == Integer.MAX_VALUE) { break; } else { string += indent + toString(1 << i); } } return string; } } Loading
android/app/src/com/android/bluetooth/Utils.java +23 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.Charset; Loading Loading @@ -1121,4 +1122,26 @@ public final class Utils { } return false; } /** * CCC descriptor short integer value to string. * @param cccValue the short value of CCC descriptor * @return String value representing CCC state */ public static String cccIntToStr(Short cccValue) { String string = ""; if (cccValue == 0) { return string += "NO SUBSCRIPTION"; } if (BigInteger.valueOf(cccValue).testBit(0)) { string += "NOTIFICATION"; } if (BigInteger.valueOf(cccValue).testBit(1)) { string += string.isEmpty() ? "INDICATION" : "|INDICATION"; } return string; } }
android/app/src/com/android/bluetooth/mcp/McpService.java +14 −1 Original line number Diff line number Diff line Loading @@ -175,6 +175,18 @@ public class McpService extends ProfileService { gmcs.dump(sb); } } for (Map.Entry<BluetoothDevice, Integer> entry : mDeviceAuthorizations.entrySet()) { String accessString; if (entry.getValue() == BluetoothDevice.ACCESS_REJECTED) { accessString = "ACCESS_REJECTED"; } else if (entry.getValue() == BluetoothDevice.ACCESS_ALLOWED) { accessString = "ACCESS_ALLOWED"; } else { accessString = "ACCESS_UNKNOWN"; } sb.append("\n\t\tDevice: " + entry.getKey() + ", access: " + accessString); } } public void onDeviceUnauthorized(BluetoothDevice device) { Loading @@ -188,7 +200,8 @@ public class McpService extends ProfileService { } public void setDeviceAuthorized(BluetoothDevice device, boolean isAuthorized) { Log.i(TAG, "setDeviceAuthorized(): device: " + device + ", isAuthorized: " + isAuthorized); Log.i(TAG, "\tsetDeviceAuthorized(): device: " + device + ", isAuthorized: " + isAuthorized); int authorization = isAuthorized ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED; mDeviceAuthorizations.put(device, authorization); Loading
android/app/src/com/android/bluetooth/mcp/MediaControlGattService.java +69 −1 Original line number Diff line number Diff line Loading @@ -147,6 +147,56 @@ public class MediaControlGattService implements MediaControlGattServiceInterface private LeAudioService mLeAudioService; private AdapterService mAdapterService; private static String mcsUuidToString(UUID uuid) { if (uuid.equals(UUID_PLAYER_NAME)) { return "PLAYER_NAME"; } else if (uuid.equals(UUID_PLAYER_ICON_OBJ_ID)) { return "PLAYER_ICON_OBJ_ID"; } else if (uuid.equals(UUID_PLAYER_ICON_URL)) { return "PLAYER_ICON_URL"; } else if (uuid.equals(UUID_TRACK_CHANGED)) { return "TRACK_CHANGED"; } else if (uuid.equals(UUID_TRACK_TITLE)) { return "TRACK_TITLE"; } else if (uuid.equals(UUID_TRACK_DURATION)) { return "TRACK_DURATION"; } else if (uuid.equals(UUID_TRACK_POSITION)) { return "TRACK_POSITION"; } else if (uuid.equals(UUID_PLAYBACK_SPEED)) { return "PLAYBACK_SPEED"; } else if (uuid.equals(UUID_SEEKING_SPEED)) { return "SEEKING_SPEED"; } else if (uuid.equals(UUID_CURRENT_TRACK_SEGMENT_OBJ_ID)) { return "CURRENT_TRACK_SEGMENT_OBJ_ID"; } else if (uuid.equals(UUID_CURRENT_TRACK_OBJ_ID)) { return "CURRENT_TRACK_OBJ_ID"; } else if (uuid.equals(UUID_NEXT_TRACK_OBJ_ID)) { return "NEXT_TRACK_OBJ_ID"; } else if (uuid.equals(UUID_CURRENT_GROUP_OBJ_ID)) { return "CURRENT_GROUP_OBJ_ID"; } else if (uuid.equals(UUID_PARENT_GROUP_OBJ_ID)) { return "PARENT_GROUP_OBJ_ID"; } else if (uuid.equals(UUID_PLAYING_ORDER)) { return "PLAYING_ORDER"; } else if (uuid.equals(UUID_PLAYING_ORDER_SUPPORTED)) { return "PLAYING_ORDER_SUPPORTED"; } else if (uuid.equals(UUID_MEDIA_STATE)) { return "MEDIA_STATE"; } else if (uuid.equals(UUID_MEDIA_CONTROL_POINT)) { return "MEDIA_CONTROL_POINT"; } else if (uuid.equals(UUID_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED)) { return "MEDIA_CONTROL_POINT_OPCODES_SUPPORTED"; } else if (uuid.equals(UUID_SEARCH_RESULT_OBJ_ID)) { return "SEARCH_RESULT_OBJ_ID"; } else if (uuid.equals(UUID_SEARCH_CONTROL_POINT)) { return "SEARCH_CONTROL_POINT"; } else if (uuid.equals(UUID_CONTENT_CONTROL_ID)) { return "CONTENT_CONTROL_ID"; } else { return "UNKNOWN(" + uuid + ")"; } } private static class GattOpContext { public enum Operation { READ_CHARACTERISTIC, Loading Loading @@ -1960,7 +2010,25 @@ public class MediaControlGattService implements MediaControlGattServiceInterface public void dump(StringBuilder sb) { sb.append("\tMediaControlService instance:"); sb.append("\n\t\tCcid = " + mCcid); sb.append("\n\t\tFeatures = " + String.format("0x%08X", mFeatures)); sb.append("\n\t\tFeatures:" + ServiceFeature.featuresToString(mFeatures, "\n\t\t\t")); BluetoothGattCharacteristic characteristic = mCharacteristics.get(CharId.PLAYER_NAME); if (characteristic == null) { sb.append("\n\t\tPlayer name: <No Player>"); } else { sb.append("\n\t\tPlayer name: " + characteristic.getStringValue(0)); } sb.append("\n\t\tCurrentPlaybackState = " + mCurrentMediaState); for (Map.Entry<String, HashMap<UUID, Short>> deviceEntry : mCccDescriptorValues.entrySet()) { sb.append("\n\t\tCCC states for device: " + "xx:xx:xx:xx:" + deviceEntry.getKey().substring(12)); for (Map.Entry<UUID, Short> entry : deviceEntry.getValue().entrySet()) { sb.append("\n\t\t\tCharacteristic: " + mcsUuidToString(entry.getKey()) + ", value: " + Utils.cccIntToStr(entry.getValue())); } } } }
android/app/src/com/android/bluetooth/mcp/ServiceFeature.java +17 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package com.android.bluetooth.mcp; import java.util.BitSet; /** * Service features definition */ Loading Loading @@ -103,4 +105,19 @@ public final class ServiceFeature { return "UNKNOWN(0x" + Long.toHexString(serviceFeature) + ")"; } static String featuresToString(long serviceFeatures, String indent) { BitSet bs = BitSet.valueOf(new long[] {serviceFeatures}); String string = ""; for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { if (i == Integer.MAX_VALUE) { break; } else { string += indent + toString(1 << i); } } return string; } }