1 /* 2 * Copyright (C) 2017 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 android.bluetooth; 18 19 import android.annotation.Nullable; 20 import android.os.Parcel; 21 import android.os.Parcelable; 22 23 import java.util.Arrays; 24 import java.util.Objects; 25 26 /** 27 * Represents the codec status (configuration and capability) for a Bluetooth 28 * A2DP source device. 29 * 30 * {@see BluetoothA2dp} 31 * 32 * {@hide} 33 */ 34 public final class BluetoothCodecStatus implements Parcelable { 35 /** 36 * Extra for the codec configuration intents of the individual profiles. 37 * 38 * This extra represents the current codec status of the A2DP 39 * profile. 40 */ 41 public static final String EXTRA_CODEC_STATUS = 42 "android.bluetooth.extra.CODEC_STATUS"; 43 44 private final @Nullable BluetoothCodecConfig mCodecConfig; 45 private final BluetoothCodecConfig[] mCodecsLocalCapabilities; 46 private final BluetoothCodecConfig[] mCodecsSelectableCapabilities; 47 BluetoothCodecStatus(@ullable BluetoothCodecConfig codecConfig, @Nullable BluetoothCodecConfig[] codecsLocalCapabilities, @Nullable BluetoothCodecConfig[] codecsSelectableCapabilities)48 public BluetoothCodecStatus(@Nullable BluetoothCodecConfig codecConfig, 49 @Nullable BluetoothCodecConfig[] codecsLocalCapabilities, 50 @Nullable BluetoothCodecConfig[] codecsSelectableCapabilities) { 51 mCodecConfig = codecConfig; 52 mCodecsLocalCapabilities = codecsLocalCapabilities; 53 mCodecsSelectableCapabilities = codecsSelectableCapabilities; 54 } 55 56 @Override equals(Object o)57 public boolean equals(Object o) { 58 if (o instanceof BluetoothCodecStatus) { 59 BluetoothCodecStatus other = (BluetoothCodecStatus) o; 60 return (Objects.equals(other.mCodecConfig, mCodecConfig) 61 && sameCapabilities(other.mCodecsLocalCapabilities, mCodecsLocalCapabilities) 62 && sameCapabilities(other.mCodecsSelectableCapabilities, 63 mCodecsSelectableCapabilities)); 64 } 65 return false; 66 } 67 68 /** 69 * Checks whether two arrays of capabilities contain same capabilities. 70 * The order of the capabilities in each array is ignored. 71 * 72 * @param c1 the first array of capabilities to compare 73 * @param c2 the second array of capabilities to compare 74 * @return true if both arrays contain same capabilities 75 * @hide 76 */ sameCapabilities(BluetoothCodecConfig[] c1, BluetoothCodecConfig[] c2)77 public static boolean sameCapabilities(BluetoothCodecConfig[] c1, 78 BluetoothCodecConfig[] c2) { 79 if (c1 == null) { 80 return (c2 == null); 81 } 82 if (c2 == null) { 83 return false; 84 } 85 if (c1.length != c2.length) { 86 return false; 87 } 88 return Arrays.asList(c1).containsAll(Arrays.asList(c2)); 89 } 90 91 /** 92 * Checks whether the codec config matches the selectable capabilities. 93 * Any parameters of the codec config with NONE value will be considered a wildcard matching. 94 * 95 * @param codecConfig the codec config to compare against 96 * @return true if the codec config matches, otherwise false 97 * @hide 98 */ isCodecConfigSelectable(BluetoothCodecConfig codecConfig)99 public boolean isCodecConfigSelectable(BluetoothCodecConfig codecConfig) { 100 if (codecConfig == null || !codecConfig.hasSingleSampleRate() 101 || !codecConfig.hasSingleBitsPerSample() || !codecConfig.hasSingleChannelMode()) { 102 return false; 103 } 104 for (BluetoothCodecConfig selectableConfig : mCodecsSelectableCapabilities) { 105 if (codecConfig.getCodecType() != selectableConfig.getCodecType()) { 106 continue; 107 } 108 int sampleRate = codecConfig.getSampleRate(); 109 if ((sampleRate & selectableConfig.getSampleRate()) == 0 110 && sampleRate != BluetoothCodecConfig.SAMPLE_RATE_NONE) { 111 continue; 112 } 113 int bitsPerSample = codecConfig.getBitsPerSample(); 114 if ((bitsPerSample & selectableConfig.getBitsPerSample()) == 0 115 && bitsPerSample != BluetoothCodecConfig.BITS_PER_SAMPLE_NONE) { 116 continue; 117 } 118 int channelMode = codecConfig.getChannelMode(); 119 if ((channelMode & selectableConfig.getChannelMode()) == 0 120 && channelMode != BluetoothCodecConfig.CHANNEL_MODE_NONE) { 121 continue; 122 } 123 return true; 124 } 125 return false; 126 } 127 128 /** 129 * Returns a hash based on the codec config and local capabilities 130 * 131 * @return a hash based on the config values 132 * @hide 133 */ 134 @Override hashCode()135 public int hashCode() { 136 return Objects.hash(mCodecConfig, mCodecsLocalCapabilities, 137 mCodecsLocalCapabilities); 138 } 139 140 @Override toString()141 public String toString() { 142 return "{mCodecConfig:" + mCodecConfig 143 + ",mCodecsLocalCapabilities:" + Arrays.toString(mCodecsLocalCapabilities) 144 + ",mCodecsSelectableCapabilities:" + Arrays.toString(mCodecsSelectableCapabilities) 145 + "}"; 146 } 147 148 /** 149 * Always returns 0 150 * 151 * @return 0 152 * @hide 153 */ 154 @Override describeContents()155 public int describeContents() { 156 return 0; 157 } 158 159 public static final @android.annotation.NonNull Parcelable.Creator<BluetoothCodecStatus> CREATOR = 160 new Parcelable.Creator<BluetoothCodecStatus>() { 161 public BluetoothCodecStatus createFromParcel(Parcel in) { 162 final BluetoothCodecConfig codecConfig = in.readTypedObject( 163 BluetoothCodecConfig.CREATOR); 164 final BluetoothCodecConfig[] codecsLocalCapabilities = in.createTypedArray( 165 BluetoothCodecConfig.CREATOR); 166 final BluetoothCodecConfig[] codecsSelectableCapabilities = in.createTypedArray( 167 BluetoothCodecConfig.CREATOR); 168 169 return new BluetoothCodecStatus(codecConfig, 170 codecsLocalCapabilities, 171 codecsSelectableCapabilities); 172 } 173 174 public BluetoothCodecStatus[] newArray(int size) { 175 return new BluetoothCodecStatus[size]; 176 } 177 }; 178 179 /** 180 * Flattens the object to a parcel 181 * 182 * @param out The Parcel in which the object should be written. 183 * @param flags Additional flags about how the object should be written. 184 * 185 * @hide 186 */ 187 @Override writeToParcel(Parcel out, int flags)188 public void writeToParcel(Parcel out, int flags) { 189 out.writeTypedObject(mCodecConfig, 0); 190 out.writeTypedArray(mCodecsLocalCapabilities, 0); 191 out.writeTypedArray(mCodecsSelectableCapabilities, 0); 192 } 193 194 /** 195 * Gets the current codec configuration. 196 * 197 * @return the current codec configuration 198 */ getCodecConfig()199 public @Nullable BluetoothCodecConfig getCodecConfig() { 200 return mCodecConfig; 201 } 202 203 /** 204 * Gets the codecs local capabilities. 205 * 206 * @return an array with the codecs local capabilities 207 */ getCodecsLocalCapabilities()208 public @Nullable BluetoothCodecConfig[] getCodecsLocalCapabilities() { 209 return mCodecsLocalCapabilities; 210 } 211 212 /** 213 * Gets the codecs selectable capabilities. 214 * 215 * @return an array with the codecs selectable capabilities 216 */ getCodecsSelectableCapabilities()217 public @Nullable BluetoothCodecConfig[] getCodecsSelectableCapabilities() { 218 return mCodecsSelectableCapabilities; 219 } 220 } 221