/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.avrcpcontroller; import android.support.v4.media.session.PlaybackStateCompat; import android.util.Log; import android.util.SparseArray; import java.util.ArrayList; /* * Contains information Player Application Setting extended from BluetootAvrcpPlayerSettings */ class PlayerApplicationSettings { private static final String TAG = "PlayerApplicationSettings"; /* * Values for SetPlayerApplicationSettings from AVRCP Spec V1.6 Appendix F. */ static final byte EQUALIZER_STATUS = 0x01; static final byte REPEAT_STATUS = 0x02; static final byte SHUFFLE_STATUS = 0x03; static final byte SCAN_STATUS = 0x04; private static final byte JNI_EQUALIZER_STATUS_OFF = 0x01; private static final byte JNI_EQUALIZER_STATUS_ON = 0x02; private static final byte JNI_REPEAT_STATUS_OFF = 0x01; private static final byte JNI_REPEAT_STATUS_SINGLE_TRACK_REPEAT = 0x02; private static final byte JNI_REPEAT_STATUS_ALL_TRACK_REPEAT = 0x03; private static final byte JNI_REPEAT_STATUS_GROUP_REPEAT = 0x04; private static final byte JNI_SHUFFLE_STATUS_OFF = 0x01; private static final byte JNI_SHUFFLE_STATUS_ALL_TRACK_SHUFFLE = 0x02; private static final byte JNI_SHUFFLE_STATUS_GROUP_SHUFFLE = 0x03; private static final byte JNI_SCAN_STATUS_OFF = 0x01; private static final byte JNI_SCAN_STATUS_ALL_TRACK_SCAN = 0x02; private static final byte JNI_SCAN_STATUS_GROUP_SCAN = 0x03; private static final byte JNI_STATUS_INVALID = -1; /* * Hash map of current settings. */ private SparseArray mSettings = new SparseArray<>(); /* * Hash map of supported values, a setting should be supported by the remote in order to enable * in mSettings. */ private SparseArray> mSupportedValues = new SparseArray>(); /* Convert from JNI array to Java classes. */ static PlayerApplicationSettings makeSupportedSettings(byte[] btAvrcpAttributeList) { PlayerApplicationSettings newObj = new PlayerApplicationSettings(); try { for (int i = 0; i < btAvrcpAttributeList.length; ) { byte attrId = btAvrcpAttributeList[i++]; byte numSupportedVals = btAvrcpAttributeList[i++]; ArrayList supportedValues = new ArrayList(); for (int j = 0; j < numSupportedVals; j++) { // Yes, keep using i for array indexing. supportedValues.add( mapAttribIdValtoAvrcpPlayerSetting(attrId, btAvrcpAttributeList[i++])); } newObj.mSupportedValues.put(attrId, supportedValues); } } catch (ArrayIndexOutOfBoundsException exception) { Log.e(TAG, "makeSupportedSettings attributeList index error."); } return newObj; } static PlayerApplicationSettings makeSettings(byte[] btAvrcpAttributeList) { PlayerApplicationSettings newObj = new PlayerApplicationSettings(); try { for (int i = 0; i < btAvrcpAttributeList.length; ) { byte attrId = btAvrcpAttributeList[i++]; newObj.mSettings.put(attrId, mapAttribIdValtoAvrcpPlayerSetting(attrId, btAvrcpAttributeList[i++])); } } catch (ArrayIndexOutOfBoundsException exception) { Log.e(TAG, "makeSettings JNI_ATTRIButeList index error."); } return newObj; } public void setSupport(PlayerApplicationSettings updates) { mSettings = updates.mSettings; mSupportedValues = updates.mSupportedValues; } public boolean supportsSetting(int settingType, int settingValue) { if (null == mSupportedValues.get(settingType)) return false; return mSupportedValues.valueAt(settingType).contains(settingValue); } public boolean supportsSetting(int settingType) { return (null != mSupportedValues.get(settingType)); } public int getSetting(int settingType) { if (null == mSettings.get(settingType)) return -1; return mSettings.get(settingType); } // Convert a native Attribute Id/Value pair into the AVRCP equivalent value. private static int mapAttribIdValtoAvrcpPlayerSetting(byte attribId, byte attribVal) { if (attribId == REPEAT_STATUS) { switch (attribVal) { case JNI_REPEAT_STATUS_ALL_TRACK_REPEAT: return PlaybackStateCompat.REPEAT_MODE_ALL; case JNI_REPEAT_STATUS_GROUP_REPEAT: return PlaybackStateCompat.REPEAT_MODE_GROUP; case JNI_REPEAT_STATUS_OFF: return PlaybackStateCompat.REPEAT_MODE_NONE; case JNI_REPEAT_STATUS_SINGLE_TRACK_REPEAT: return PlaybackStateCompat.REPEAT_MODE_ONE; } } else if (attribId == SHUFFLE_STATUS) { switch (attribVal) { case JNI_SHUFFLE_STATUS_ALL_TRACK_SHUFFLE: return PlaybackStateCompat.SHUFFLE_MODE_ALL; case JNI_SHUFFLE_STATUS_GROUP_SHUFFLE: return PlaybackStateCompat.SHUFFLE_MODE_GROUP; case JNI_SHUFFLE_STATUS_OFF: return PlaybackStateCompat.SHUFFLE_MODE_NONE; } } return JNI_STATUS_INVALID; } // Convert an AVRCP Setting/Value pair into the native equivalent value; static byte mapAvrcpPlayerSettingstoBTattribVal(int mSetting, int mSettingVal) { if (mSetting == REPEAT_STATUS) { switch (mSettingVal) { case PlaybackStateCompat.REPEAT_MODE_NONE: return JNI_REPEAT_STATUS_OFF; case PlaybackStateCompat.REPEAT_MODE_ONE: return JNI_REPEAT_STATUS_SINGLE_TRACK_REPEAT; case PlaybackStateCompat.REPEAT_MODE_ALL: return JNI_REPEAT_STATUS_ALL_TRACK_REPEAT; case PlaybackStateCompat.REPEAT_MODE_GROUP: return JNI_REPEAT_STATUS_GROUP_REPEAT; } } else if (mSetting == SHUFFLE_STATUS) { switch (mSettingVal) { case PlaybackStateCompat.SHUFFLE_MODE_NONE: return JNI_SHUFFLE_STATUS_OFF; case PlaybackStateCompat.SHUFFLE_MODE_ALL: return JNI_SHUFFLE_STATUS_ALL_TRACK_SHUFFLE; case PlaybackStateCompat.SHUFFLE_MODE_GROUP: return JNI_SHUFFLE_STATUS_GROUP_SHUFFLE; } } return JNI_STATUS_INVALID; } }