1 /* 2 * Copyright 2021 HIMSA II K/S - www.himsa.com. 3 * Represented by EHIMA - www.ehima.com 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.bluetooth.mcp; 19 20 import java.util.BitSet; 21 22 /** Service features definition */ 23 public final class ServiceFeature { 24 // LS word is used for the characteristic support bits 25 public static final long PLAYER_NAME = 0x00000001; 26 public static final long PLAYER_ICON_OBJ_ID = 0x00000002; 27 public static final long PLAYER_ICON_URL = 0x00000004; 28 public static final long TRACK_CHANGED = 0x00000008; 29 public static final long TRACK_TITLE = 0x00000010; 30 public static final long TRACK_DURATION = 0x00000020; 31 public static final long TRACK_POSITION = 0x00000040; 32 public static final long PLAYBACK_SPEED = 0x00000080; 33 public static final long SEEKING_SPEED = 0x00000100; 34 public static final long CURRENT_TRACK_SEGMENT_OBJ_ID = 0x00000200; 35 public static final long CURRENT_TRACK_OBJ_ID = 0x00000400; 36 public static final long NEXT_TRACK_OBJ_ID = 0x00000800; 37 public static final long CURRENT_GROUP_OBJ_ID = 0x00001000; 38 public static final long PARENT_GROUP_OBJ_ID = 0x00002000; 39 public static final long PLAYING_ORDER = 0x00004000; 40 public static final long PLAYING_ORDER_SUPPORTED = 0x00008000; 41 public static final long MEDIA_STATE = 0x00010000; 42 public static final long MEDIA_CONTROL_POINT = 0x00020000; 43 public static final long MEDIA_CONTROL_POINT_OPCODES_SUPPORTED = 0x00040000; 44 public static final long SEARCH_RESULT_OBJ_ID = 0x00080000; 45 public static final long SEARCH_CONTROL_POINT = 0x00100000; 46 public static final long CONTENT_CONTROL_ID = 0x00200000; 47 48 // MS word is used for the optional notification support bits 49 public static final long PLAYER_NAME_NOTIFY = PLAYER_NAME << 32; 50 public static final long TRACK_TITLE_NOTIFY = TRACK_TITLE << 32; 51 public static final long TRACK_DURATION_NOTIFY = TRACK_DURATION << 32; 52 public static final long TRACK_POSITION_NOTIFY = TRACK_POSITION << 32; 53 public static final long PLAYBACK_SPEED_NOTIFY = PLAYBACK_SPEED << 32; 54 public static final long SEEKING_SPEED_NOTIFY = SEEKING_SPEED << 32; 55 public static final long CURRENT_TRACK_OBJ_ID_NOTIFY = CURRENT_TRACK_OBJ_ID << 32; 56 public static final long NEXT_TRACK_OBJ_ID_NOTIFY = NEXT_TRACK_OBJ_ID << 32; 57 public static final long CURRENT_GROUP_OBJ_ID_NOTIFY = CURRENT_GROUP_OBJ_ID << 32; 58 public static final long PARENT_GROUP_OBJ_ID_NOTIFY = PARENT_GROUP_OBJ_ID << 32; 59 public static final long PLAYING_ORDER_NOTIFY = PLAYING_ORDER << 32; 60 public static final long MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_NOTIFY = 61 MEDIA_CONTROL_POINT_OPCODES_SUPPORTED << 32; 62 63 // This is set according to the Media Control Service Specification, v1.0, Section 3, 64 // Table 3.1. 65 public static final long ALL_MANDATORY_SERVICE_FEATURES = 66 PLAYER_NAME 67 | TRACK_CHANGED 68 | TRACK_TITLE 69 | TRACK_DURATION 70 | TRACK_POSITION 71 | MEDIA_STATE 72 | CONTENT_CONTROL_ID; 73 toString(long serviceFeature)74 static String toString(long serviceFeature) { 75 if (serviceFeature == PLAYER_NAME) return "PLAYER_NAME(BIT 1)"; 76 if (serviceFeature == PLAYER_ICON_OBJ_ID) return "PLAYER_ICON_OBJ_ID(BIT 2)"; 77 if (serviceFeature == PLAYER_ICON_URL) return "PLAYER_ICON_URL(BIT 3)"; 78 if (serviceFeature == TRACK_CHANGED) return "TRACK_CHANGED(BIT 4)"; 79 if (serviceFeature == TRACK_TITLE) return "TRACK_TITLE(BIT 5)"; 80 if (serviceFeature == TRACK_DURATION) return "TRACK_DURATION(BIT 6)"; 81 if (serviceFeature == TRACK_POSITION) return "TRACK_POSITION(BIT 7)"; 82 if (serviceFeature == PLAYBACK_SPEED) return "PLAYBACK_SPEED(BIT 8)"; 83 if (serviceFeature == SEEKING_SPEED) return "SEEKING_SPEED(BIT 9)"; 84 if (serviceFeature == CURRENT_TRACK_SEGMENT_OBJ_ID) 85 return "CURRENT_TRACK_SEGMENT_OBJ_ID(BIT 10)"; 86 if (serviceFeature == CURRENT_TRACK_OBJ_ID) return "CURRENT_TRACK_OBJ_ID(BIT 11)"; 87 if (serviceFeature == NEXT_TRACK_OBJ_ID) return "NEXT_TRACK_OBJ_ID(BIT 12)"; 88 if (serviceFeature == CURRENT_GROUP_OBJ_ID) return "CURRENT_GROUP_OBJ_ID(BIT 13)"; 89 if (serviceFeature == PARENT_GROUP_OBJ_ID) return "PARENT_GROUP_OBJ_ID(BIT 14)"; 90 if (serviceFeature == PLAYING_ORDER) return "PLAYING_ORDER(BIT 15)"; 91 if (serviceFeature == PLAYING_ORDER_SUPPORTED) return "PLAYING_ORDER_SUPPORTED(BIT 16)"; 92 if (serviceFeature == MEDIA_STATE) return "MEDIA_STATE(BIT 17)"; 93 if (serviceFeature == MEDIA_CONTROL_POINT) return "MEDIA_CONTROL_POINT(BIT 18)"; 94 if (serviceFeature == MEDIA_CONTROL_POINT_OPCODES_SUPPORTED) 95 return "MEDIA_CONTROL_POINT_OPCODES_SUPPORTED(BIT 19)"; 96 if (serviceFeature == SEARCH_RESULT_OBJ_ID) return "SEARCH_RESULT_OBJ_ID(BIT 20)"; 97 if (serviceFeature == SEARCH_CONTROL_POINT) return "SEARCH_CONTROL_POINT(BIT 21)"; 98 if (serviceFeature == CONTENT_CONTROL_ID) return "CONTENT_CONTROL_ID(BIT 22)"; 99 if (serviceFeature == PLAYER_NAME_NOTIFY) return "PLAYER_NAME_NOTIFY"; 100 if (serviceFeature == TRACK_TITLE_NOTIFY) return "TRACK_TITLE_NOTIFY"; 101 if (serviceFeature == TRACK_DURATION_NOTIFY) return "TRACK_DURATION_NOTIFY"; 102 if (serviceFeature == TRACK_POSITION_NOTIFY) return "TRACK_POSITION_NOTIFY"; 103 if (serviceFeature == PLAYBACK_SPEED_NOTIFY) return "PLAYBACK_SPEED_NOTIFY"; 104 if (serviceFeature == SEEKING_SPEED_NOTIFY) return "SEEKING_SPEED_NOTIFY"; 105 if (serviceFeature == CURRENT_TRACK_OBJ_ID_NOTIFY) return "CURRENT_TRACK_OBJ_ID_NOTIFY"; 106 if (serviceFeature == NEXT_TRACK_OBJ_ID_NOTIFY) return "NEXT_TRACK_OBJ_ID_NOTIFY"; 107 if (serviceFeature == CURRENT_GROUP_OBJ_ID_NOTIFY) return "CURRENT_GROUP_OBJ_ID_NOTIFY"; 108 if (serviceFeature == PARENT_GROUP_OBJ_ID_NOTIFY) return "PARENT_GROUP_OBJ_ID_NOTIFY"; 109 if (serviceFeature == PLAYING_ORDER_NOTIFY) return "PLAYING_ORDER_NOTIFY"; 110 if (serviceFeature == MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_NOTIFY) 111 return "MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_NOTIFY"; 112 113 return "UNKNOWN(0x" + Long.toHexString(serviceFeature) + ")"; 114 } 115 featuresToString(long serviceFeatures, String indent)116 static String featuresToString(long serviceFeatures, String indent) { 117 BitSet bs = BitSet.valueOf(new long[] {serviceFeatures}); 118 String string = ""; 119 120 for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { 121 if (i == Integer.MAX_VALUE) { 122 break; 123 } else { 124 string += indent + toString(1 << i); 125 } 126 } 127 128 return string; 129 } 130 } 131