1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.bluetooth.avrcpcontroller; 18 19 import android.bluetooth.BluetoothAvrcpPlayerSettings; 20 21 import android.util.Log; 22 23 import java.util.ArrayList; 24 import java.util.HashMap; 25 import java.util.Map; 26 27 /* 28 * Contains information Player Application Setting extended from BluetootAvrcpPlayerSettings 29 */ 30 class PlayerApplicationSettings { 31 private static final String TAG = "PlayerApplicationSettings"; 32 33 /* 34 * Values for SetPlayerApplicationSettings from AVRCP Spec V1.6 Appendix F. 35 */ 36 private static final byte JNI_ATTRIB_EQUALIZER_STATUS = 0x01; 37 private static final byte JNI_ATTRIB_REPEAT_STATUS = 0x02; 38 private static final byte JNI_ATTRIB_SHUFFLE_STATUS = 0x03; 39 private static final byte JNI_ATTRIB_SCAN_STATUS = 0x04; 40 41 private static final byte JNI_EQUALIZER_STATUS_OFF = 0x01; 42 private static final byte JNI_EQUALIZER_STATUS_ON = 0x02; 43 44 private static final byte JNI_REPEAT_STATUS_OFF = 0x01; 45 private static final byte JNI_REPEAT_STATUS_SINGLE_TRACK_REPEAT = 0x02; 46 private static final byte JNI_REPEAT_STATUS_ALL_TRACK_REPEAT = 0x03; 47 private static final byte JNI_REPEAT_STATUS_GROUP_REPEAT = 0x04; 48 49 private static final byte JNI_SHUFFLE_STATUS_OFF = 0x01; 50 private static final byte JNI_SHUFFLE_STATUS_ALL_TRACK_SHUFFLE = 0x02; 51 private static final byte JNI_SHUFFLE_STATUS_GROUP_SHUFFLE = 0x03; 52 53 private static final byte JNI_SCAN_STATUS_OFF = 0x01; 54 private static final byte JNI_SCAN_STATUS_ALL_TRACK_SCAN = 0x02; 55 private static final byte JNI_SCAN_STATUS_GROUP_SCAN = 0x03; 56 57 private static final byte JNI_STATUS_INVALID = -1; 58 59 60 /* 61 * Hash map of current settings. 62 */ 63 private Map<Integer, Integer> mSettings = new HashMap<Integer, Integer>(); 64 65 /* 66 * Hash map of supported values, a setting should be supported by the remote in order to enable 67 * in mSettings. 68 */ 69 private Map<Integer, ArrayList<Integer>> mSupportedValues = 70 new HashMap<Integer, ArrayList<Integer>>(); 71 72 /* Convert from JNI array to Java classes. */ 73 static PlayerApplicationSettings makeSupportedSettings(byte[] btAvrcpAttributeList) { 74 PlayerApplicationSettings newObj = new PlayerApplicationSettings(); 75 try { 76 for (int i = 0; i < btAvrcpAttributeList.length; ) { 77 byte attrId = btAvrcpAttributeList[i++]; 78 byte numSupportedVals = btAvrcpAttributeList[i++]; 79 ArrayList<Integer> supportedValues = new ArrayList<Integer>(); 80 81 for (int j = 0; j < numSupportedVals; j++) { 82 // Yes, keep using i for array indexing. 83 supportedValues.add(mapAttribIdValtoAvrcpPlayerSetting(attrId, 84 btAvrcpAttributeList[i++])); 85 } 86 newObj.mSupportedValues.put(mapBTAttribIdToAvrcpPlayerSettings(attrId), 87 supportedValues); 88 } 89 } catch (ArrayIndexOutOfBoundsException exception) { 90 Log.e(TAG,"makeSupportedSettings attributeList index error."); 91 } 92 return newObj; 93 } 94 95 public BluetoothAvrcpPlayerSettings getAvrcpSettings() { 96 int supportedSettings = 0; 97 for (Integer setting : mSettings.keySet()) { 98 supportedSettings |= setting; 99 } 100 BluetoothAvrcpPlayerSettings result = new BluetoothAvrcpPlayerSettings(supportedSettings); 101 for (Integer setting : mSettings.keySet()) { 102 result.addSettingValue(setting, mSettings.get(setting)); 103 } 104 return result; 105 } 106 107 static PlayerApplicationSettings makeSettings(byte[] btAvrcpAttributeList) { 108 PlayerApplicationSettings newObj = new PlayerApplicationSettings(); 109 try { 110 for (int i = 0; i < btAvrcpAttributeList.length; ) { 111 byte attrId = btAvrcpAttributeList[i++]; 112 113 newObj.mSettings.put(mapBTAttribIdToAvrcpPlayerSettings(attrId), 114 mapAttribIdValtoAvrcpPlayerSetting(attrId, 115 btAvrcpAttributeList[i++])); 116 } 117 } catch (ArrayIndexOutOfBoundsException exception) { 118 Log.e(TAG,"makeSettings JNI_ATTRIButeList index error."); 119 } 120 return newObj; 121 } 122 123 public void setSupport(PlayerApplicationSettings updates) { 124 mSettings = updates.mSettings; 125 mSupportedValues = updates.mSupportedValues; 126 } 127 128 public void setValues(BluetoothAvrcpPlayerSettings updates) { 129 int supportedSettings = updates.getSettings(); 130 for (int i = 1; i <= BluetoothAvrcpPlayerSettings.SETTING_SCAN; i++) { 131 if ((i & supportedSettings) > 0) { 132 mSettings.put(i, updates.getSettingValue(i)); 133 } 134 } 135 } 136 137 /* 138 * Check through all settings to ensure that they are all available to be set and then check 139 * that the desired value is in fact supported by our remote player. 140 */ 141 public boolean supportsSettings(BluetoothAvrcpPlayerSettings settingsToCheck) { 142 int settingSubset = settingsToCheck.getSettings(); 143 int supportedSettings = 0; 144 for (Integer setting : mSupportedValues.keySet()) { 145 supportedSettings |= setting; 146 } 147 try { 148 if ((supportedSettings & settingSubset) == settingSubset) { 149 for (Integer settingId : mSettings.keySet()) { 150 if ((settingId & settingSubset )== settingId && 151 (!mSupportedValues.get(settingId).contains(settingsToCheck. 152 getSettingValue(settingId)))) 153 // The setting is in both settings to check and supported settings but the 154 // value is not supported. 155 return false; 156 } 157 return true; 158 } 159 } catch (NullPointerException e) { 160 Log.e(TAG, 161 "supportsSettings received a supported setting that has no supported values."); 162 } 163 return false; 164 } 165 166 // Convert currently desired settings into an attribute array to pass to the native layer to 167 // enable them. 168 public ArrayList<Byte> getNativeSettings() { 169 int i = 0; 170 ArrayList<Byte> attribArray = new ArrayList<Byte>(); 171 for (Integer settingId : mSettings.keySet()) { 172 switch (settingId) 173 { 174 case BluetoothAvrcpPlayerSettings.SETTING_EQUALIZER: 175 attribArray.add(JNI_ATTRIB_EQUALIZER_STATUS); 176 attribArray.add(mapAvrcpPlayerSettingstoBTattribVal( 177 settingId, mSettings.get(settingId))); 178 break; 179 case BluetoothAvrcpPlayerSettings.SETTING_REPEAT: 180 attribArray.add(JNI_ATTRIB_REPEAT_STATUS); 181 attribArray.add(mapAvrcpPlayerSettingstoBTattribVal( 182 settingId, mSettings.get(settingId))); 183 break; 184 case BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE: 185 attribArray.add(JNI_ATTRIB_SHUFFLE_STATUS); 186 attribArray.add(mapAvrcpPlayerSettingstoBTattribVal( 187 settingId, mSettings.get(settingId))); 188 break; 189 case BluetoothAvrcpPlayerSettings.SETTING_SCAN: 190 attribArray.add(JNI_ATTRIB_SCAN_STATUS); 191 attribArray.add(mapAvrcpPlayerSettingstoBTattribVal( 192 settingId, mSettings.get(settingId))); 193 break; 194 default: 195 Log.w(TAG,"Unknown setting found in getNativeSettings: " + settingId); 196 } 197 } 198 return attribArray; 199 } 200 201 // Convert a native Attribute Id/Value pair into the AVRCP equivalent value. 202 private static int mapAttribIdValtoAvrcpPlayerSetting(byte attribId, byte attribVal) { 203 if (attribId == JNI_ATTRIB_EQUALIZER_STATUS) { 204 switch(attribVal) { 205 case JNI_EQUALIZER_STATUS_OFF: 206 return BluetoothAvrcpPlayerSettings.STATE_OFF; 207 case JNI_EQUALIZER_STATUS_ON: 208 return BluetoothAvrcpPlayerSettings.STATE_ON; 209 } 210 } else if (attribId == JNI_ATTRIB_REPEAT_STATUS) { 211 switch(attribVal) { 212 case JNI_REPEAT_STATUS_ALL_TRACK_REPEAT: 213 return BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK; 214 case JNI_REPEAT_STATUS_GROUP_REPEAT: 215 return BluetoothAvrcpPlayerSettings.STATE_GROUP; 216 case JNI_REPEAT_STATUS_OFF: 217 return BluetoothAvrcpPlayerSettings.STATE_OFF; 218 case JNI_REPEAT_STATUS_SINGLE_TRACK_REPEAT: 219 return BluetoothAvrcpPlayerSettings.STATE_SINGLE_TRACK; 220 } 221 } else if (attribId == JNI_ATTRIB_SCAN_STATUS) { 222 switch(attribVal) { 223 case JNI_SCAN_STATUS_ALL_TRACK_SCAN: 224 return BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK; 225 case JNI_SCAN_STATUS_GROUP_SCAN: 226 return BluetoothAvrcpPlayerSettings.STATE_GROUP; 227 case JNI_SCAN_STATUS_OFF: 228 return BluetoothAvrcpPlayerSettings.STATE_OFF; 229 } 230 } else if (attribId == JNI_ATTRIB_SHUFFLE_STATUS) { 231 switch(attribVal) { 232 case JNI_SHUFFLE_STATUS_ALL_TRACK_SHUFFLE: 233 return BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK; 234 case JNI_SHUFFLE_STATUS_GROUP_SHUFFLE: 235 return BluetoothAvrcpPlayerSettings.STATE_GROUP; 236 case JNI_SHUFFLE_STATUS_OFF: 237 return BluetoothAvrcpPlayerSettings.STATE_OFF; 238 } 239 } 240 return BluetoothAvrcpPlayerSettings.STATE_INVALID; 241 } 242 243 // Convert an AVRCP Setting/Value pair into the native equivalent value; 244 private static byte mapAvrcpPlayerSettingstoBTattribVal(int mSetting, int mSettingVal) { 245 if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_EQUALIZER) { 246 switch(mSettingVal) { 247 case BluetoothAvrcpPlayerSettings.STATE_OFF: 248 return JNI_EQUALIZER_STATUS_OFF; 249 case BluetoothAvrcpPlayerSettings.STATE_ON: 250 return JNI_EQUALIZER_STATUS_ON; 251 } 252 } else if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_REPEAT) { 253 switch(mSettingVal) { 254 case BluetoothAvrcpPlayerSettings.STATE_OFF: 255 return JNI_REPEAT_STATUS_OFF; 256 case BluetoothAvrcpPlayerSettings.STATE_SINGLE_TRACK: 257 return JNI_REPEAT_STATUS_SINGLE_TRACK_REPEAT; 258 case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK: 259 return JNI_REPEAT_STATUS_ALL_TRACK_REPEAT; 260 case BluetoothAvrcpPlayerSettings.STATE_GROUP: 261 return JNI_REPEAT_STATUS_GROUP_REPEAT; 262 } 263 } else if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE) { 264 switch(mSettingVal) { 265 case BluetoothAvrcpPlayerSettings.STATE_OFF: 266 return JNI_SHUFFLE_STATUS_OFF; 267 case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK: 268 return JNI_SHUFFLE_STATUS_ALL_TRACK_SHUFFLE; 269 case BluetoothAvrcpPlayerSettings.STATE_GROUP: 270 return JNI_SHUFFLE_STATUS_GROUP_SHUFFLE; 271 } 272 } else if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_SCAN) { 273 switch(mSettingVal) { 274 case BluetoothAvrcpPlayerSettings.STATE_OFF: 275 return JNI_SCAN_STATUS_OFF; 276 case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK: 277 return JNI_SCAN_STATUS_ALL_TRACK_SCAN; 278 case BluetoothAvrcpPlayerSettings.STATE_GROUP: 279 return JNI_SCAN_STATUS_GROUP_SCAN; 280 } 281 } 282 return JNI_STATUS_INVALID; 283 } 284 285 // convert a native Attribute Id into the AVRCP Setting equivalent value; 286 private static int mapBTAttribIdToAvrcpPlayerSettings(byte attribId) { 287 switch(attribId) { 288 case JNI_ATTRIB_EQUALIZER_STATUS: 289 return BluetoothAvrcpPlayerSettings.SETTING_EQUALIZER; 290 case JNI_ATTRIB_REPEAT_STATUS: 291 return BluetoothAvrcpPlayerSettings.SETTING_REPEAT; 292 case JNI_ATTRIB_SHUFFLE_STATUS: 293 return BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE; 294 case JNI_ATTRIB_SCAN_STATUS: 295 return BluetoothAvrcpPlayerSettings.SETTING_SCAN; 296 default: 297 return BluetoothAvrcpPlayerSettings.STATE_INVALID; 298 } 299 } 300 301 } 302 303