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