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.support.v4.media.session.PlaybackStateCompat; 20 import android.util.Log; 21 import android.util.SparseArray; 22 import android.util.SparseIntArray; 23 24 import com.android.internal.annotations.VisibleForTesting; 25 26 import java.util.ArrayList; 27 28 /* 29 * Contains information Player Application Setting extended from BluetootAvrcpPlayerSettings 30 */ 31 class PlayerApplicationSettings { 32 private static final String TAG = "PlayerApplicationSettings"; 33 34 /* 35 * Values for SetPlayerApplicationSettings from AVRCP Spec V1.6 Appendix F. 36 */ 37 static final byte REPEAT_STATUS = 0x02; 38 static final byte SHUFFLE_STATUS = 0x03; 39 40 @VisibleForTesting static final byte JNI_REPEAT_STATUS_OFF = 0x01; 41 @VisibleForTesting static final byte JNI_REPEAT_STATUS_SINGLE_TRACK_REPEAT = 0x02; 42 @VisibleForTesting static final byte JNI_REPEAT_STATUS_ALL_TRACK_REPEAT = 0x03; 43 @VisibleForTesting static final byte JNI_REPEAT_STATUS_GROUP_REPEAT = 0x04; 44 45 @VisibleForTesting static final byte JNI_SHUFFLE_STATUS_OFF = 0x01; 46 @VisibleForTesting static final byte JNI_SHUFFLE_STATUS_ALL_TRACK_SHUFFLE = 0x02; 47 @VisibleForTesting static final byte JNI_SHUFFLE_STATUS_GROUP_SHUFFLE = 0x03; 48 49 @VisibleForTesting static final byte JNI_STATUS_INVALID = -1; 50 51 /* 52 * Hash map of current settings. 53 */ 54 private SparseIntArray mSettings = new SparseIntArray(); 55 56 /* 57 * Hash map of supported values, a setting should be supported by the remote in order to enable 58 * in mSettings. 59 */ 60 private SparseArray<ArrayList<Integer>> mSupportedValues = 61 new SparseArray<ArrayList<Integer>>(); 62 63 /* Convert from JNI array to Java classes. */ makeSupportedSettings(byte[] btAvrcpAttributeList)64 static PlayerApplicationSettings makeSupportedSettings(byte[] btAvrcpAttributeList) { 65 PlayerApplicationSettings newObj = new PlayerApplicationSettings(); 66 try { 67 for (int i = 0; i < btAvrcpAttributeList.length; ) { 68 byte attrId = btAvrcpAttributeList[i++]; 69 byte numSupportedVals = btAvrcpAttributeList[i++]; 70 ArrayList<Integer> supportedValues = new ArrayList<Integer>(); 71 72 for (int j = 0; j < numSupportedVals; j++) { 73 // Yes, keep using i for array indexing. 74 supportedValues.add( 75 mapAttribIdValtoAvrcpPlayerSetting(attrId, btAvrcpAttributeList[i++])); 76 } 77 newObj.mSupportedValues.put(attrId, supportedValues); 78 } 79 } catch (ArrayIndexOutOfBoundsException exception) { 80 Log.e(TAG, "makeSupportedSettings attributeList index error."); 81 } 82 return newObj; 83 } 84 makeSettings(byte[] btAvrcpAttributeList)85 static PlayerApplicationSettings makeSettings(byte[] btAvrcpAttributeList) { 86 PlayerApplicationSettings newObj = new PlayerApplicationSettings(); 87 try { 88 for (int i = 0; i < btAvrcpAttributeList.length; ) { 89 byte attrId = btAvrcpAttributeList[i++]; 90 91 newObj.mSettings.put( 92 attrId, 93 mapAttribIdValtoAvrcpPlayerSetting(attrId, btAvrcpAttributeList[i++])); 94 } 95 } catch (ArrayIndexOutOfBoundsException exception) { 96 Log.e(TAG, "makeSettings JNI_ATTRIButeList index error."); 97 } 98 return newObj; 99 } 100 setSupport(PlayerApplicationSettings updates)101 public void setSupport(PlayerApplicationSettings updates) { 102 mSettings = updates.mSettings; 103 mSupportedValues = updates.mSupportedValues; 104 } 105 supportsSetting(int settingType, int settingValue)106 public boolean supportsSetting(int settingType, int settingValue) { 107 if (null == mSupportedValues.get(settingType)) return false; 108 return mSupportedValues.valueAt(settingType).contains(settingValue); 109 } 110 supportsSetting(int settingType)111 public boolean supportsSetting(int settingType) { 112 return (null != mSupportedValues.get(settingType)); 113 } 114 getSetting(int settingType)115 public int getSetting(int settingType) { 116 return mSettings.get(settingType, -1); 117 } 118 119 // Convert a native Attribute Id/Value pair into the AVRCP equivalent value. 120 @VisibleForTesting mapAttribIdValtoAvrcpPlayerSetting(byte attribId, byte attribVal)121 static int mapAttribIdValtoAvrcpPlayerSetting(byte attribId, byte attribVal) { 122 if (attribId == REPEAT_STATUS) { 123 switch (attribVal) { 124 case JNI_REPEAT_STATUS_ALL_TRACK_REPEAT: 125 return PlaybackStateCompat.REPEAT_MODE_ALL; 126 case JNI_REPEAT_STATUS_GROUP_REPEAT: 127 return PlaybackStateCompat.REPEAT_MODE_GROUP; 128 case JNI_REPEAT_STATUS_OFF: 129 return PlaybackStateCompat.REPEAT_MODE_NONE; 130 case JNI_REPEAT_STATUS_SINGLE_TRACK_REPEAT: 131 return PlaybackStateCompat.REPEAT_MODE_ONE; 132 } 133 } else if (attribId == SHUFFLE_STATUS) { 134 switch (attribVal) { 135 case JNI_SHUFFLE_STATUS_ALL_TRACK_SHUFFLE: 136 return PlaybackStateCompat.SHUFFLE_MODE_ALL; 137 case JNI_SHUFFLE_STATUS_GROUP_SHUFFLE: 138 return PlaybackStateCompat.SHUFFLE_MODE_GROUP; 139 case JNI_SHUFFLE_STATUS_OFF: 140 return PlaybackStateCompat.SHUFFLE_MODE_NONE; 141 } 142 } 143 return JNI_STATUS_INVALID; 144 } 145 146 // Convert an AVRCP Setting/Value pair into the native equivalent value; mapAvrcpPlayerSettingstoBTattribVal(int mSetting, int mSettingVal)147 static byte mapAvrcpPlayerSettingstoBTattribVal(int mSetting, int mSettingVal) { 148 if (mSetting == REPEAT_STATUS) { 149 switch (mSettingVal) { 150 case PlaybackStateCompat.REPEAT_MODE_NONE: 151 return JNI_REPEAT_STATUS_OFF; 152 case PlaybackStateCompat.REPEAT_MODE_ONE: 153 return JNI_REPEAT_STATUS_SINGLE_TRACK_REPEAT; 154 case PlaybackStateCompat.REPEAT_MODE_ALL: 155 return JNI_REPEAT_STATUS_ALL_TRACK_REPEAT; 156 case PlaybackStateCompat.REPEAT_MODE_GROUP: 157 return JNI_REPEAT_STATUS_GROUP_REPEAT; 158 } 159 } else if (mSetting == SHUFFLE_STATUS) { 160 switch (mSettingVal) { 161 case PlaybackStateCompat.SHUFFLE_MODE_NONE: 162 return JNI_SHUFFLE_STATUS_OFF; 163 case PlaybackStateCompat.SHUFFLE_MODE_ALL: 164 return JNI_SHUFFLE_STATUS_ALL_TRACK_SHUFFLE; 165 case PlaybackStateCompat.SHUFFLE_MODE_GROUP: 166 return JNI_SHUFFLE_STATUS_GROUP_SHUFFLE; 167 } 168 } 169 return JNI_STATUS_INVALID; 170 } 171 repeatStatusToString(int repeatMode)172 public static String repeatStatusToString(int repeatMode) { 173 switch (repeatMode) { 174 case PlaybackStateCompat.REPEAT_MODE_ALL: 175 return "ALL"; 176 case PlaybackStateCompat.REPEAT_MODE_GROUP: 177 return "GROUP"; 178 case PlaybackStateCompat.REPEAT_MODE_NONE: 179 return "NONE"; 180 case PlaybackStateCompat.REPEAT_MODE_ONE: 181 return "ONE"; 182 default: 183 return "Unsupported"; 184 } 185 } 186 shuffleStatusToString(int shuffleMode)187 public static String shuffleStatusToString(int shuffleMode) { 188 switch (shuffleMode) { 189 case PlaybackStateCompat.SHUFFLE_MODE_NONE: 190 return "NONE"; 191 case PlaybackStateCompat.SHUFFLE_MODE_ALL: 192 return "ALL"; 193 case PlaybackStateCompat.SHUFFLE_MODE_GROUP: 194 return "GROUP"; 195 default: 196 return "Unsupported"; 197 } 198 } 199 200 @Override toString()201 public String toString() { 202 return "<PlayerApplicationSettings" 203 + " repeat=" 204 + repeatStatusToString(getSetting(REPEAT_STATUS)) 205 + " shuffle=" 206 + shuffleStatusToString(getSetting(SHUFFLE_STATUS)) 207 + ">"; 208 } 209 } 210