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