1 /* 2 * Copyright 2022 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.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 import java.util.Objects; 29 30 /** 31 * Represents Bluetooth Audio Policies of a Handsfree (HF) device (if HFP is used) and Call Terminal 32 * (CT) device (if BLE Audio is used), which describes the preferences of allowing or disallowing 33 * audio based on the use cases. The HF/CT devices shall send objects of this class to send its 34 * preference to the AG/CG devices. 35 * 36 * <p>HF/CT side applications on can use {@link BluetoothDevice#requestAudioPolicyAsSink} API to set 37 * and send a {@link BluetoothSinkAudioPolicy} object containing the preference/policy values. This 38 * object will be stored in the memory of HF/CT side, will be send to the AG/CG side using Android 39 * Specific AT Commands and will be stored in the AG side memory and database. 40 * 41 * <p>HF/CT side API {@link BluetoothDevice#getRequestedAudioPolicyAsSink} can be used to retrieve 42 * the stored audio policies currently. 43 * 44 * <p>Note that the setter APIs of this class will only set the values of the object. To actually 45 * set the policies, API {@link BluetoothDevice#requestAudioPolicyAsSink} must need to be invoked 46 * with the {@link BluetoothSinkAudioPolicy} object. 47 * 48 * <p>Note that any API related to this feature should be used after configuring the support of the 49 * AG device and after checking whether the AG device supports this feature or not by invoking 50 * {@link BluetoothDevice#isRequestAudioPolicyAsSinkSupported}. Only after getting a {@link 51 * BluetoothStatusCodes#FEATURE_SUPPORTED} response from the API should the APIs related to this 52 * feature be used. 53 * 54 * @hide 55 */ 56 @SystemApi 57 public final class BluetoothSinkAudioPolicy implements Parcelable { 58 59 /** @hide */ 60 @Retention(RetentionPolicy.SOURCE) 61 @IntDef( 62 prefix = {"POLICY_"}, 63 value = { 64 POLICY_UNCONFIGURED, 65 POLICY_ALLOWED, 66 POLICY_NOT_ALLOWED, 67 }) 68 public @interface AudioPolicyValues {} 69 70 /** 71 * Audio behavior not configured for the policy. 72 * 73 * <p>If a policy is set with this value, it means that the policy is not configured with a 74 * value yet and should not be used to make any decision. 75 * 76 * @hide 77 */ 78 @SystemApi public static final int POLICY_UNCONFIGURED = 0; 79 80 /** 81 * Audio is preferred by HF device for the policy. 82 * 83 * <p>If a policy is set with this value, then the HF device will prefer the audio for the 84 * policy use case. For example, if the Call Establish audio policy is set with this value, then 85 * the HF will prefer the audio during making or picking up a call. 86 * 87 * @hide 88 */ 89 @SystemApi public static final int POLICY_ALLOWED = 1; 90 91 /** 92 * Audio is not preferred by HF device for the policy. 93 * 94 * <p>If a policy is set with this value, then the HF device will not prefer the audio for the 95 * policy use case. For example, if the Call Establish audio policy is set with this value, then 96 * the HF will not prefer the audio during making or picking up a call. 97 * 98 * @hide 99 */ 100 @SystemApi public static final int POLICY_NOT_ALLOWED = 2; 101 102 /** 103 * The feature ID used in the HFP AT command. 104 * 105 * @hide 106 */ 107 public static final String HFP_SET_SINK_AUDIO_POLICY_ID = "SINKAUDIOPOLICY"; 108 109 @AudioPolicyValues private final int mCallEstablishPolicy; 110 @AudioPolicyValues private final int mConnectingTimePolicy; 111 @AudioPolicyValues private final int mInBandRingtonePolicy; 112 113 /** @hide */ BluetoothSinkAudioPolicy( int callEstablishPolicy, int connectingTimePolicy, int inBandRingtonePolicy)114 public BluetoothSinkAudioPolicy( 115 int callEstablishPolicy, int connectingTimePolicy, int inBandRingtonePolicy) { 116 mCallEstablishPolicy = callEstablishPolicy; 117 mConnectingTimePolicy = connectingTimePolicy; 118 mInBandRingtonePolicy = inBandRingtonePolicy; 119 } 120 121 /** 122 * Get Call establishment policy audio policy. 123 * 124 * <p>This policy is used to determine the audio preference when the HF device makes or answers 125 * a call. That is, if this device makes or answers a call, is the audio preferred by HF. 126 * 127 * @return the call pick up audio policy value 128 * @hide 129 */ 130 @SystemApi getCallEstablishPolicy()131 public @AudioPolicyValues int getCallEstablishPolicy() { 132 return mCallEstablishPolicy; 133 } 134 135 /** 136 * Get during connection audio up policy. 137 * 138 * <p>This policy is used to determine the audio preference when the HF device connects with the 139 * AG device. That is, when the HF device gets connected, should the HF become active and get 140 * audio is decided by this policy. This also covers the case of during a call. If the HF 141 * connects with the AG during an ongoing call, should the call audio be routed to the HF will 142 * be decided by this policy. 143 * 144 * @return the during connection audio policy value 145 * @hide 146 */ 147 @SystemApi getActiveDevicePolicyAfterConnection()148 public @AudioPolicyValues int getActiveDevicePolicyAfterConnection() { 149 return mConnectingTimePolicy; 150 } 151 152 /** 153 * Get In band ringtone audio up policy. 154 * 155 * <p>This policy is used to determine the audio preference of the in band ringtone. That is, if 156 * there is an incoming call, should the inband ringtone audio be routed to the HF will be 157 * decided by this policy. 158 * 159 * @return the in band ringtone audio policy value 160 * @hide 161 */ 162 @SystemApi getInBandRingtonePolicy()163 public @AudioPolicyValues int getInBandRingtonePolicy() { 164 return mInBandRingtonePolicy; 165 } 166 167 @Override toString()168 public String toString() { 169 StringBuilder builder = new StringBuilder("BluetoothSinkAudioPolicy{"); 170 builder.append("mCallEstablishPolicy: "); 171 builder.append(mCallEstablishPolicy); 172 builder.append(", mConnectingTimePolicy: "); 173 builder.append(mConnectingTimePolicy); 174 builder.append(", mInBandRingtonePolicy: "); 175 builder.append(mInBandRingtonePolicy); 176 builder.append("}"); 177 return builder.toString(); 178 } 179 180 /** {@link Parcelable.Creator} interface implementation. */ 181 public static final @android.annotation.NonNull Parcelable.Creator<BluetoothSinkAudioPolicy> 182 CREATOR = 183 new Parcelable.Creator<BluetoothSinkAudioPolicy>() { 184 @Override 185 public BluetoothSinkAudioPolicy createFromParcel(@NonNull Parcel in) { 186 return new BluetoothSinkAudioPolicy( 187 in.readInt(), in.readInt(), in.readInt()); 188 } 189 190 @Override 191 public BluetoothSinkAudioPolicy[] newArray(int size) { 192 return new BluetoothSinkAudioPolicy[size]; 193 } 194 }; 195 196 @Override writeToParcel(@onNull Parcel out, int flags)197 public void writeToParcel(@NonNull Parcel out, int flags) { 198 out.writeInt(mCallEstablishPolicy); 199 out.writeInt(mConnectingTimePolicy); 200 out.writeInt(mInBandRingtonePolicy); 201 } 202 203 /** @hide */ 204 @Override describeContents()205 public int describeContents() { 206 return 0; 207 } 208 209 @Override equals(@ullable Object o)210 public boolean equals(@Nullable Object o) { 211 if (o instanceof BluetoothSinkAudioPolicy) { 212 BluetoothSinkAudioPolicy other = (BluetoothSinkAudioPolicy) o; 213 return (other.mCallEstablishPolicy == mCallEstablishPolicy 214 && other.mConnectingTimePolicy == mConnectingTimePolicy 215 && other.mInBandRingtonePolicy == mInBandRingtonePolicy); 216 } 217 return false; 218 } 219 220 /** 221 * Returns a hash representation of this BluetoothCodecConfig based on all the config values. 222 * 223 * @hide 224 */ 225 @Override hashCode()226 public int hashCode() { 227 return Objects.hash(mCallEstablishPolicy, mConnectingTimePolicy, mInBandRingtonePolicy); 228 } 229 230 /** 231 * Builder for {@link BluetoothSinkAudioPolicy}. 232 * 233 * <p>By default, the audio policy values will be set to {@link 234 * BluetoothSinkAudioPolicy#POLICY_UNCONFIGURED}. 235 */ 236 public static final class Builder { 237 private int mCallEstablishPolicy = POLICY_UNCONFIGURED; 238 private int mConnectingTimePolicy = POLICY_UNCONFIGURED; 239 private int mInBandRingtonePolicy = POLICY_UNCONFIGURED; 240 Builder()241 public Builder() {} 242 Builder(@onNull BluetoothSinkAudioPolicy policies)243 public Builder(@NonNull BluetoothSinkAudioPolicy policies) { 244 mCallEstablishPolicy = policies.mCallEstablishPolicy; 245 mConnectingTimePolicy = policies.mConnectingTimePolicy; 246 mInBandRingtonePolicy = policies.mInBandRingtonePolicy; 247 } 248 249 /** 250 * Set Call Establish (pick up and answer) policy. 251 * 252 * <p>This policy is used to determine the audio preference when the HF device makes or 253 * answers a call. That is, if this device makes or answers a call, is the audio preferred 254 * by HF. 255 * 256 * <p>If set to {@link BluetoothSinkAudioPolicy#POLICY_ALLOWED}, answering or making a call 257 * from the HF device will route the call audio to it. If set to {@link 258 * BluetoothSinkAudioPolicy#POLICY_NOT_ALLOWED}, answering or making a call from the HF 259 * device will NOT route the call audio to it. 260 * 261 * @return reference to the current object 262 * @hide 263 */ 264 @SystemApi setCallEstablishPolicy(@udioPolicyValues int callEstablishPolicy)265 public @NonNull Builder setCallEstablishPolicy(@AudioPolicyValues int callEstablishPolicy) { 266 mCallEstablishPolicy = callEstablishPolicy; 267 return this; 268 } 269 270 /** 271 * Set during connection audio up policy. 272 * 273 * <p>This policy is used to determine the audio preference when the HF device connects with 274 * the AG device. That is, when the HF device gets connected, should the HF become active 275 * and get audio is decided by this policy. This also covers the case of during a call. If 276 * the HF connects with the AG during an ongoing call, should the call audio be routed to 277 * the HF will be decided by this policy. 278 * 279 * <p>If set to {@link BluetoothSinkAudioPolicy#POLICY_ALLOWED}, connecting HF during a call 280 * will route the call audio to it. If set to {@link 281 * BluetoothSinkAudioPolicy#POLICY_NOT_ALLOWED}, connecting HF during a call will NOT route 282 * the call audio to it. 283 * 284 * @return reference to the current object 285 * @hide 286 */ 287 @SystemApi setActiveDevicePolicyAfterConnection( @udioPolicyValues int connectingTimePolicy)288 public @NonNull Builder setActiveDevicePolicyAfterConnection( 289 @AudioPolicyValues int connectingTimePolicy) { 290 mConnectingTimePolicy = connectingTimePolicy; 291 return this; 292 } 293 294 /** 295 * Set In band ringtone audio up policy. 296 * 297 * <p>This policy is used to determine the audio preference of the in band ringtone. That 298 * is, if there is an incoming call, should the inband ringtone audio be routed to the HF 299 * will be decided by this policy. 300 * 301 * <p>If set to {@link BluetoothSinkAudioPolicy#POLICY_ALLOWED}, there will be in band 302 * ringtone in the HF device during an incoming call. If set to {@link 303 * BluetoothSinkAudioPolicy#POLICY_NOT_ALLOWED}, there will NOT be in band ringtone in the 304 * HF device during an incoming call. 305 * 306 * @return reference to the current object 307 * @hide 308 */ 309 @SystemApi setInBandRingtonePolicy( @udioPolicyValues int inBandRingtonePolicy)310 public @NonNull Builder setInBandRingtonePolicy( 311 @AudioPolicyValues int inBandRingtonePolicy) { 312 mInBandRingtonePolicy = inBandRingtonePolicy; 313 return this; 314 } 315 316 /** 317 * Build {@link BluetoothSinkAudioPolicy}. 318 * 319 * @return new BluetoothSinkAudioPolicy object 320 * @hide 321 */ 322 @SystemApi build()323 public @NonNull BluetoothSinkAudioPolicy build() { 324 return new BluetoothSinkAudioPolicy( 325 mCallEstablishPolicy, mConnectingTimePolicy, mInBandRingtonePolicy); 326 } 327 } 328 } 329