/* * Copyright (C) 2017 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 android.bluetooth; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import java.util.Arrays; import java.util.Objects; /** * Represents the codec status (configuration and capability) for a Bluetooth * A2DP source device. * * {@see BluetoothA2dp} * * {@hide} */ public final class BluetoothCodecStatus implements Parcelable { /** * Extra for the codec configuration intents of the individual profiles. * * This extra represents the current codec status of the A2DP * profile. */ public static final String EXTRA_CODEC_STATUS = "android.bluetooth.extra.CODEC_STATUS"; private final @Nullable BluetoothCodecConfig mCodecConfig; private final BluetoothCodecConfig[] mCodecsLocalCapabilities; private final BluetoothCodecConfig[] mCodecsSelectableCapabilities; public BluetoothCodecStatus(@Nullable BluetoothCodecConfig codecConfig, @Nullable BluetoothCodecConfig[] codecsLocalCapabilities, @Nullable BluetoothCodecConfig[] codecsSelectableCapabilities) { mCodecConfig = codecConfig; mCodecsLocalCapabilities = codecsLocalCapabilities; mCodecsSelectableCapabilities = codecsSelectableCapabilities; } @Override public boolean equals(Object o) { if (o instanceof BluetoothCodecStatus) { BluetoothCodecStatus other = (BluetoothCodecStatus) o; return (Objects.equals(other.mCodecConfig, mCodecConfig) && sameCapabilities(other.mCodecsLocalCapabilities, mCodecsLocalCapabilities) && sameCapabilities(other.mCodecsSelectableCapabilities, mCodecsSelectableCapabilities)); } return false; } /** * Checks whether two arrays of capabilities contain same capabilities. * The order of the capabilities in each array is ignored. * * @param c1 the first array of capabilities to compare * @param c2 the second array of capabilities to compare * @return true if both arrays contain same capabilities * @hide */ public static boolean sameCapabilities(BluetoothCodecConfig[] c1, BluetoothCodecConfig[] c2) { if (c1 == null) { return (c2 == null); } if (c2 == null) { return false; } if (c1.length != c2.length) { return false; } return Arrays.asList(c1).containsAll(Arrays.asList(c2)); } /** * Checks whether the codec config matches the selectable capabilities. * Any parameters of the codec config with NONE value will be considered a wildcard matching. * * @param codecConfig the codec config to compare against * @return true if the codec config matches, otherwise false * @hide */ public boolean isCodecConfigSelectable(BluetoothCodecConfig codecConfig) { if (codecConfig == null || !codecConfig.hasSingleSampleRate() || !codecConfig.hasSingleBitsPerSample() || !codecConfig.hasSingleChannelMode()) { return false; } for (BluetoothCodecConfig selectableConfig : mCodecsSelectableCapabilities) { if (codecConfig.getCodecType() != selectableConfig.getCodecType()) { continue; } int sampleRate = codecConfig.getSampleRate(); if ((sampleRate & selectableConfig.getSampleRate()) == 0 && sampleRate != BluetoothCodecConfig.SAMPLE_RATE_NONE) { continue; } int bitsPerSample = codecConfig.getBitsPerSample(); if ((bitsPerSample & selectableConfig.getBitsPerSample()) == 0 && bitsPerSample != BluetoothCodecConfig.BITS_PER_SAMPLE_NONE) { continue; } int channelMode = codecConfig.getChannelMode(); if ((channelMode & selectableConfig.getChannelMode()) == 0 && channelMode != BluetoothCodecConfig.CHANNEL_MODE_NONE) { continue; } return true; } return false; } /** * Returns a hash based on the codec config and local capabilities * * @return a hash based on the config values * @hide */ @Override public int hashCode() { return Objects.hash(mCodecConfig, mCodecsLocalCapabilities, mCodecsLocalCapabilities); } @Override public String toString() { return "{mCodecConfig:" + mCodecConfig + ",mCodecsLocalCapabilities:" + Arrays.toString(mCodecsLocalCapabilities) + ",mCodecsSelectableCapabilities:" + Arrays.toString(mCodecsSelectableCapabilities) + "}"; } /** * Always returns 0 * * @return 0 * @hide */ @Override public int describeContents() { return 0; } public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { public BluetoothCodecStatus createFromParcel(Parcel in) { final BluetoothCodecConfig codecConfig = in.readTypedObject( BluetoothCodecConfig.CREATOR); final BluetoothCodecConfig[] codecsLocalCapabilities = in.createTypedArray( BluetoothCodecConfig.CREATOR); final BluetoothCodecConfig[] codecsSelectableCapabilities = in.createTypedArray( BluetoothCodecConfig.CREATOR); return new BluetoothCodecStatus(codecConfig, codecsLocalCapabilities, codecsSelectableCapabilities); } public BluetoothCodecStatus[] newArray(int size) { return new BluetoothCodecStatus[size]; } }; /** * Flattens the object to a parcel * * @param out The Parcel in which the object should be written. * @param flags Additional flags about how the object should be written. * * @hide */ @Override public void writeToParcel(Parcel out, int flags) { out.writeTypedObject(mCodecConfig, 0); out.writeTypedArray(mCodecsLocalCapabilities, 0); out.writeTypedArray(mCodecsSelectableCapabilities, 0); } /** * Gets the current codec configuration. * * @return the current codec configuration */ public @Nullable BluetoothCodecConfig getCodecConfig() { return mCodecConfig; } /** * Gets the codecs local capabilities. * * @return an array with the codecs local capabilities */ public @Nullable BluetoothCodecConfig[] getCodecsLocalCapabilities() { return mCodecsLocalCapabilities; } /** * Gets the codecs selectable capabilities. * * @return an array with the codecs selectable capabilities */ public @Nullable BluetoothCodecConfig[] getCodecsSelectableCapabilities() { return mCodecsSelectableCapabilities; } }