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