Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d0158456 authored by Grzegorz Kołodziejczyk's avatar Grzegorz Kołodziejczyk
Browse files

mcs: Add dump of authorization state and CCC values

This extends dumping of MCS data. Authorization state and CCC values for
each characteristic is dump.

Current dump of McpService:
Profile: McpService
Media Control Service  instance list:
	MediaControlService instance:
		Ccid = 2
		Features:
			PLAYER_NAME(BIT 1)
			TRACK_CHANGED(BIT 4)
			TRACK_TITLE(BIT 5)
			TRACK_DURATION(BIT 6)
			TRACK_POSITION(BIT 7)
			PLAYBACK_SPEED(BIT 8)
			SEEKING_SPEED(BIT 9)
			PLAYING_ORDER(BIT 15)
			PLAYING_ORDER_SUPPORTED(BIT 16)
			MEDIA_STATE(BIT 17)
			MEDIA_CONTROL_POINT(BIT 18)
			MEDIA_CONTROL_POINT_OPCODES_SUPPORTED(BIT 19)
			CONTENT_CONTROL_ID(BIT 22)
			PLAYER_NAME(BIT 1)
			TRACK_TITLE(BIT 5)
			TRACK_DURATION(BIT 6)
			TRACK_POSITION(BIT 7)
			PLAYBACK_SPEED(BIT 8)
			SEEKING_SPEED(BIT 9)
			PLAYING_ORDER(BIT 15)
			MEDIA_CONTROL_POINT_OPCODES_SUPPORTED(BIT 19)
		Player name: YouTube Music
		CurrentPlaybackState = PLAYING
		CCC states for device: xx:xx:xx:xx:2C:08
			Characteristic: MEDIA_STATE, value: NOTIFICATION
			Characteristic: PLAYER_NAME, value: NOTIFICATION
			Characteristic: MEDIA_CONTROL_POINT, value: NOTIFICATION
			Characteristic: MEDIA_CONTROL_POINT_OPCODES_SUPPORTED, value: NOTIFICATION
			Characteristic: TRACK_CHANGED, value: NOTIFICATION
		CCC states for device: xx:xx:xx:xx:0F:2E
			Characteristic: MEDIA_STATE, value: NOTIFICATION
			Characteristic: PLAYER_NAME, value: NOTIFICATION
			Characteristic: MEDIA_CONTROL_POINT, value: NOTIFICATION
			Characteristic: MEDIA_CONTROL_POINT_OPCODES_SUPPORTED, value: NOTIFICATION
			Characteristic: TRACK_CHANGED, value: NOTIFICATION
		Device: XX:XX:XX:XX:2C:08, access: ACCESS_ALLOWED
		Device: XX:XX:XX:XX:0F:2E, access: ACCESS_ALLOWED

Tag: #feature
Bug: 273530115
Test: atest GoogleBluetoothInstrumentationTests
Change-Id: Id373bf39defac11f345e9ef585cd77de6a0763a6
parent 289d3327
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;
    }
}
+14 −1
Original line number Diff line number Diff line
@@ -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) {
@@ -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);
+69 −1
Original line number Diff line number Diff line
@@ -149,6 +149,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,
@@ -1955,7 +2005,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()));
            }
        }
    }
}
+17 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@

package com.android.bluetooth.mcp;

import java.util.BitSet;

/**
 * Service features definition
 */
@@ -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;
    }
}