blob: 99e1c418c65485c6b821fc4d854eeb02e0469eb1 [file] [log] [blame]
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -08001/*
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
17package android.bluetooth;
18
Etienne Ruffieux55a03862021-10-05 17:11:45 +000019import android.annotation.NonNull;
Jean-Michel Trividfd389c2018-09-14 16:01:28 -070020import android.annotation.Nullable;
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -080021import android.os.Parcel;
22import android.os.Parcelable;
23
Etienne Ruffieux55a03862021-10-05 17:11:45 +000024import java.util.Collections;
25import java.util.List;
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -080026import java.util.Objects;
27
28/**
David Duarteee52b7e2023-12-02 01:32:11 +000029 * Represents the codec status (configuration and capability) for a Bluetooth A2DP source device.
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -080030 *
David Duarte5a02bb42023-12-04 23:07:42 +000031 * @see BluetoothA2dp
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -080032 */
33public final class BluetoothCodecStatus implements Parcelable {
34 /**
35 * Extra for the codec configuration intents of the individual profiles.
36 *
David Duarteee52b7e2023-12-02 01:32:11 +000037 * <p>This extra represents the current codec status of the A2DP profile.
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -080038 */
David Duarteee52b7e2023-12-02 01:32:11 +000039 public static final String EXTRA_CODEC_STATUS = "android.bluetooth.extra.CODEC_STATUS";
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -080040
Jean-Michel Trividfd389c2018-09-14 16:01:28 -070041 private final @Nullable BluetoothCodecConfig mCodecConfig;
Etienne Ruffieux55a03862021-10-05 17:11:45 +000042 private final @Nullable List<BluetoothCodecConfig> mCodecsLocalCapabilities;
43 private final @Nullable List<BluetoothCodecConfig> mCodecsSelectableCapabilities;
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -080044
Etienne Ruffieuxd3c62fd2022-03-08 13:37:12 +000045 /**
46 * Creates a new BluetoothCodecStatus.
47 *
48 * @hide
49 */
David Duarteee52b7e2023-12-02 01:32:11 +000050 public BluetoothCodecStatus(
51 @Nullable BluetoothCodecConfig codecConfig,
Etienne Ruffieux55a03862021-10-05 17:11:45 +000052 @Nullable List<BluetoothCodecConfig> codecsLocalCapabilities,
53 @Nullable List<BluetoothCodecConfig> codecsSelectableCapabilities) {
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -080054 mCodecConfig = codecConfig;
55 mCodecsLocalCapabilities = codecsLocalCapabilities;
56 mCodecsSelectableCapabilities = codecsSelectableCapabilities;
57 }
58
Etienne Ruffieux55a03862021-10-05 17:11:45 +000059 private BluetoothCodecStatus(Parcel in) {
60 mCodecConfig = in.readTypedObject(BluetoothCodecConfig.CREATOR);
61 mCodecsLocalCapabilities = in.createTypedArrayList(BluetoothCodecConfig.CREATOR);
62 mCodecsSelectableCapabilities = in.createTypedArrayList(BluetoothCodecConfig.CREATOR);
63 }
64
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -080065 @Override
Roman Kalukiewicz2883f7a2020-10-14 15:59:06 -070066 public boolean equals(@Nullable Object o) {
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -080067 if (o instanceof BluetoothCodecStatus) {
Jack He910201b2017-08-22 16:06:54 -070068 BluetoothCodecStatus other = (BluetoothCodecStatus) o;
Jack He9e045d22017-08-22 21:21:23 -070069 return (Objects.equals(other.mCodecConfig, mCodecConfig)
Pavlin Radoslavov93e6d422018-04-19 14:16:15 -070070 && sameCapabilities(other.mCodecsLocalCapabilities, mCodecsLocalCapabilities)
David Duarteee52b7e2023-12-02 01:32:11 +000071 && sameCapabilities(
72 other.mCodecsSelectableCapabilities, mCodecsSelectableCapabilities));
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -080073 }
74 return false;
75 }
76
Pavlin Radoslavov93e6d422018-04-19 14:16:15 -070077 /**
David Duarteee52b7e2023-12-02 01:32:11 +000078 * Checks whether two lists of capabilities contain same capabilities. The order of the
79 * capabilities in each list is ignored.
Pavlin Radoslavov93e6d422018-04-19 14:16:15 -070080 *
Etienne Ruffieux55a03862021-10-05 17:11:45 +000081 * @param c1 the first list of capabilities to compare
82 * @param c2 the second list of capabilities to compare
83 * @return {@code true} if both lists contain same capabilities
Pavlin Radoslavov93e6d422018-04-19 14:16:15 -070084 */
David Duarteee52b7e2023-12-02 01:32:11 +000085 private static boolean sameCapabilities(
86 @Nullable List<BluetoothCodecConfig> c1, @Nullable List<BluetoothCodecConfig> c2) {
Pavlin Radoslavov93e6d422018-04-19 14:16:15 -070087 if (c1 == null) {
88 return (c2 == null);
89 }
90 if (c2 == null) {
91 return false;
92 }
Etienne Ruffieux55a03862021-10-05 17:11:45 +000093 if (c1.size() != c2.size()) {
Pavlin Radoslavov93e6d422018-04-19 14:16:15 -070094 return false;
95 }
Etienne Ruffieux55a03862021-10-05 17:11:45 +000096 return c1.containsAll(c2);
Pavlin Radoslavov93e6d422018-04-19 14:16:15 -070097 }
98
Cheney Ni38a87162019-07-18 21:45:10 +080099 /**
David Duarteee52b7e2023-12-02 01:32:11 +0000100 * Checks whether the codec config matches the selectable capabilities. Any parameters of the
101 * codec config with NONE value will be considered a wildcard matching.
Cheney Ni38a87162019-07-18 21:45:10 +0800102 *
103 * @param codecConfig the codec config to compare against
Etienne Ruffieux55a03862021-10-05 17:11:45 +0000104 * @return {@code true} if the codec config matches, {@code false} otherwise
Cheney Ni38a87162019-07-18 21:45:10 +0800105 */
Etienne Ruffieux55a03862021-10-05 17:11:45 +0000106 public boolean isCodecConfigSelectable(@Nullable BluetoothCodecConfig codecConfig) {
David Duarteee52b7e2023-12-02 01:32:11 +0000107 if (codecConfig == null
108 || !codecConfig.hasSingleSampleRate()
109 || !codecConfig.hasSingleBitsPerSample()
110 || !codecConfig.hasSingleChannelMode()) {
Cheney Ni38a87162019-07-18 21:45:10 +0800111 return false;
112 }
113 for (BluetoothCodecConfig selectableConfig : mCodecsSelectableCapabilities) {
114 if (codecConfig.getCodecType() != selectableConfig.getCodecType()) {
115 continue;
116 }
117 int sampleRate = codecConfig.getSampleRate();
118 if ((sampleRate & selectableConfig.getSampleRate()) == 0
119 && sampleRate != BluetoothCodecConfig.SAMPLE_RATE_NONE) {
120 continue;
121 }
122 int bitsPerSample = codecConfig.getBitsPerSample();
123 if ((bitsPerSample & selectableConfig.getBitsPerSample()) == 0
124 && bitsPerSample != BluetoothCodecConfig.BITS_PER_SAMPLE_NONE) {
125 continue;
126 }
127 int channelMode = codecConfig.getChannelMode();
128 if ((channelMode & selectableConfig.getChannelMode()) == 0
129 && channelMode != BluetoothCodecConfig.CHANNEL_MODE_NONE) {
130 continue;
131 }
132 return true;
133 }
134 return false;
135 }
136
David Duarteee52b7e2023-12-02 01:32:11 +0000137 /** Returns a hash based on the codec config and local capabilities. */
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -0800138 @Override
139 public int hashCode() {
David Duarteee52b7e2023-12-02 01:32:11 +0000140 return Objects.hash(mCodecConfig, mCodecsLocalCapabilities, mCodecsLocalCapabilities);
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -0800141 }
142
Etienne Ruffieux55a03862021-10-05 17:11:45 +0000143 /**
David Duarteee52b7e2023-12-02 01:32:11 +0000144 * Returns a {@link String} that describes each BluetoothCodecStatus parameter current value.
Etienne Ruffieux55a03862021-10-05 17:11:45 +0000145 */
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -0800146 @Override
147 public String toString() {
David Duarteee52b7e2023-12-02 01:32:11 +0000148 return "{mCodecConfig:"
149 + mCodecConfig
150 + ",mCodecsLocalCapabilities:"
151 + mCodecsLocalCapabilities
152 + ",mCodecsSelectableCapabilities:"
153 + mCodecsSelectableCapabilities
Jack He9e045d22017-08-22 21:21:23 -0700154 + "}";
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -0800155 }
156
Rahul Sabnis4f8a2b32019-11-15 16:08:54 -0800157 /**
Rahul Sabnis4f8a2b32019-11-15 16:08:54 -0800158 * @return 0
159 * @hide
160 */
Jack He9e045d22017-08-22 21:21:23 -0700161 @Override
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -0800162 public int describeContents() {
163 return 0;
164 }
165
David Duarteee52b7e2023-12-02 01:32:11 +0000166 public static final @NonNull Creator<BluetoothCodecStatus> CREATOR =
167 new Creator<>() {
168 public BluetoothCodecStatus createFromParcel(Parcel in) {
169 return new BluetoothCodecStatus(in);
170 }
Jack He910201b2017-08-22 16:06:54 -0700171
David Duarteee52b7e2023-12-02 01:32:11 +0000172 public BluetoothCodecStatus[] newArray(int size) {
173 return new BluetoothCodecStatus[size];
174 }
175 };
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -0800176
Rahul Sabnis4f8a2b32019-11-15 16:08:54 -0800177 /**
Etienne Ruffieux55a03862021-10-05 17:11:45 +0000178 * Flattens the object to a parcel.
Rahul Sabnis4f8a2b32019-11-15 16:08:54 -0800179 *
Etienne Ruffieux55a03862021-10-05 17:11:45 +0000180 * @param out The Parcel in which the object should be written
181 * @param flags Additional flags about how the object should be written
Rahul Sabnis4f8a2b32019-11-15 16:08:54 -0800182 */
Jack He9e045d22017-08-22 21:21:23 -0700183 @Override
Etienne Ruffieux55a03862021-10-05 17:11:45 +0000184 public void writeToParcel(@NonNull Parcel out, int flags) {
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -0800185 out.writeTypedObject(mCodecConfig, 0);
Etienne Ruffieux55a03862021-10-05 17:11:45 +0000186 out.writeTypedList(mCodecsLocalCapabilities);
187 out.writeTypedList(mCodecsSelectableCapabilities);
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -0800188 }
189
David Duarteee52b7e2023-12-02 01:32:11 +0000190 /** Returns the current codec configuration. */
Jean-Michel Trividfd389c2018-09-14 16:01:28 -0700191 public @Nullable BluetoothCodecConfig getCodecConfig() {
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -0800192 return mCodecConfig;
193 }
194
David Duarteee52b7e2023-12-02 01:32:11 +0000195 /** Returns the codecs local capabilities. */
Etienne Ruffieux55a03862021-10-05 17:11:45 +0000196 public @NonNull List<BluetoothCodecConfig> getCodecsLocalCapabilities() {
197 return (mCodecsLocalCapabilities == null)
David Duarteee52b7e2023-12-02 01:32:11 +0000198 ? Collections.emptyList()
199 : mCodecsLocalCapabilities;
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -0800200 }
201
David Duarteee52b7e2023-12-02 01:32:11 +0000202 /** Returns the codecs selectable capabilities. */
Etienne Ruffieux55a03862021-10-05 17:11:45 +0000203 public @NonNull List<BluetoothCodecConfig> getCodecsSelectableCapabilities() {
204 return (mCodecsSelectableCapabilities == null)
David Duarteee52b7e2023-12-02 01:32:11 +0000205 ? Collections.emptyList()
206 : mCodecsSelectableCapabilities;
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -0800207 }
Etienne Ruffieuxd3c62fd2022-03-08 13:37:12 +0000208
David Duarteee52b7e2023-12-02 01:32:11 +0000209 /** Builder for {@link BluetoothCodecStatus}. */
Etienne Ruffieuxd3c62fd2022-03-08 13:37:12 +0000210 public static final class Builder {
211 private BluetoothCodecConfig mCodecConfig = null;
212 private List<BluetoothCodecConfig> mCodecsLocalCapabilities = null;
213 private List<BluetoothCodecConfig> mCodecsSelectableCapabilities = null;
214
215 /**
216 * Set Bluetooth codec config for this codec status.
217 *
218 * @param codecConfig of this codec status
219 * @return the same Builder instance
220 */
221 public @NonNull Builder setCodecConfig(@NonNull BluetoothCodecConfig codecConfig) {
222 mCodecConfig = codecConfig;
223 return this;
224 }
225
226 /**
227 * Set codec local capabilities list for this codec status.
228 *
229 * @param codecsLocalCapabilities of this codec status
230 * @return the same Builder instance
231 */
232 public @NonNull Builder setCodecsLocalCapabilities(
233 @NonNull List<BluetoothCodecConfig> codecsLocalCapabilities) {
234 mCodecsLocalCapabilities = codecsLocalCapabilities;
235 return this;
236 }
237
238 /**
239 * Set codec selectable capabilities list for this codec status.
240 *
241 * @param codecsSelectableCapabilities of this codec status
242 * @return the same Builder instance
243 */
244 public @NonNull Builder setCodecsSelectableCapabilities(
245 @NonNull List<BluetoothCodecConfig> codecsSelectableCapabilities) {
246 mCodecsSelectableCapabilities = codecsSelectableCapabilities;
247 return this;
248 }
249
250 /**
251 * Build {@link BluetoothCodecStatus}.
David Duarteee52b7e2023-12-02 01:32:11 +0000252 *
Etienne Ruffieuxd3c62fd2022-03-08 13:37:12 +0000253 * @return new BluetoothCodecStatus built
254 */
255 public @NonNull BluetoothCodecStatus build() {
David Duarteee52b7e2023-12-02 01:32:11 +0000256 return new BluetoothCodecStatus(
257 mCodecConfig, mCodecsLocalCapabilities, mCodecsSelectableCapabilities);
Etienne Ruffieuxd3c62fd2022-03-08 13:37:12 +0000258 }
259 }
Pavlin Radoslavovf6d543a2017-01-25 16:54:07 -0800260}