1 /* 2 * Copyright (C) 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.car.oem; 18 19 import android.annotation.NonNull; 20 import android.annotation.SystemApi; 21 import android.car.annotation.ApiRequirements; 22 import android.media.AudioFocusInfo; 23 import android.os.Parcelable; 24 25 import com.android.internal.annotations.VisibleForTesting; 26 27 import java.util.Objects; 28 29 /** 30 * Class to encapsulate the focus information of evaluation from a car oem audio focus service 31 * 32 * @hide 33 */ 34 @SystemApi 35 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 36 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) 37 public final class AudioFocusEntry implements Parcelable { 38 39 @NonNull 40 private final AudioFocusInfo mAudioFocusInfo; 41 private final int mAudioContextId; 42 private final int mAudioVolumeGroupId; 43 private final int mAudioFocusResult; 44 AudioFocusEntry( @onNull AudioFocusInfo audioFocusInfo, int audioContextId, int audioVolumeGroupId, int focusResult)45 AudioFocusEntry( 46 @NonNull AudioFocusInfo audioFocusInfo, 47 int audioContextId, 48 int audioVolumeGroupId, 49 int focusResult) { 50 mAudioFocusInfo = Objects.requireNonNull(audioFocusInfo, 51 "Audio focus info can not be null"); 52 mAudioContextId = audioContextId; 53 mAudioVolumeGroupId = audioVolumeGroupId; 54 mAudioFocusResult = focusResult; 55 } 56 57 /** 58 * Returns the audio focus info 59 */ 60 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 61 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) getAudioFocusInfo()62 public @NonNull AudioFocusInfo getAudioFocusInfo() { 63 return mAudioFocusInfo; 64 } 65 66 /** 67 * Returns the caudio context as evaluated from the audio attributes 68 */ 69 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 70 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) getAudioContextId()71 public int getAudioContextId() { 72 return mAudioContextId; 73 } 74 75 /** 76 * Returns the volume group as evaluated from the audio attributes 77 */ 78 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 79 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) getAudioVolumeGroupId()80 public int getAudioVolumeGroupId() { 81 return mAudioVolumeGroupId; 82 } 83 84 /** 85 * Returns the focus results, must be on of {@link AudioManager.AUDIOFOCUS_GAIN}, 86 * {@link AudioManager.AUDIOFOCUS_LOSS}, {@link AudioManager.AUDIOFOCUS_LOSS_TRANSIENT}, 87 * {@link AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK} 88 **/ 89 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 90 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) getAudioFocusResult()91 public int getAudioFocusResult() { 92 return mAudioFocusResult; 93 } 94 95 @Override 96 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 97 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) toString()98 public String toString() { 99 return new StringBuilder().append("AudioFocusEntry { audioFocusInfo = ") 100 .append(getAudioFocusInfoString()).append(", audioContextId = ") 101 .append(mAudioContextId).append(", audioVolumeGroupId = ") 102 .append(mAudioVolumeGroupId).append(", focusResult = ") 103 .append(mAudioFocusResult).append(" }").toString(); 104 } 105 getAudioFocusInfoString()106 private String getAudioFocusInfoString() { 107 return new StringBuilder().append("{ attributes: ").append(mAudioFocusInfo.getAttributes()) 108 .append(", UID : ").append(mAudioFocusInfo.getClientUid()) 109 .append(", client Id: ").append(mAudioFocusInfo.getClientId()) 110 .append(", pkg: ").append(mAudioFocusInfo.getPackageName()) 111 .append(", gain: ").append(mAudioFocusInfo.getGainRequest()) 112 .append(", loss received: ").append(mAudioFocusInfo.getLossReceived()) 113 .append(", flags: ").append(mAudioFocusInfo.getFlags()) 114 .append("}").toString(); 115 } 116 117 @Override 118 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 119 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) writeToParcel(@onNull android.os.Parcel dest, int flags)120 public void writeToParcel(@NonNull android.os.Parcel dest, int flags) { 121 mAudioFocusInfo.writeToParcel(dest, flags); 122 dest.writeInt(mAudioContextId); 123 dest.writeInt(mAudioVolumeGroupId); 124 dest.writeInt(mAudioFocusResult); 125 } 126 127 @Override 128 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 129 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) describeContents()130 public int describeContents() { 131 return 0; 132 } 133 134 /** @hide */ 135 @SuppressWarnings({"unchecked", "RedundantCast"}) 136 @VisibleForTesting AudioFocusEntry(@onNull android.os.Parcel in)137 public AudioFocusEntry(@NonNull android.os.Parcel in) { 138 AudioFocusInfo audioFocusInfo = AudioFocusInfo.CREATOR.createFromParcel(in); 139 int audioContextId = in.readInt(); 140 int audioVolumeGroupId = in.readInt(); 141 int focusResult = in.readInt(); 142 143 mAudioFocusInfo = audioFocusInfo; 144 mAudioContextId = audioContextId; 145 mAudioVolumeGroupId = audioVolumeGroupId; 146 mAudioFocusResult = focusResult; 147 } 148 149 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 150 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) 151 @NonNull 152 public static final Parcelable.Creator<AudioFocusEntry> CREATOR = 153 new Parcelable.Creator<>() { 154 @Override 155 public AudioFocusEntry[] newArray(int size) { 156 return new AudioFocusEntry[size]; 157 } 158 159 @Override 160 public AudioFocusEntry createFromParcel(@NonNull android.os.Parcel in) { 161 return new AudioFocusEntry(in); 162 } 163 }; 164 165 @Override 166 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 167 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) equals(Object o)168 public boolean equals(Object o) { 169 if (this == o) { 170 return true; 171 } 172 173 if (!(o instanceof AudioFocusEntry)) { 174 return false; 175 } 176 177 AudioFocusEntry that = (AudioFocusEntry) o; 178 179 return mAudioContextId == that.mAudioContextId 180 && mAudioFocusResult == that.mAudioFocusResult 181 && mAudioVolumeGroupId == that.mAudioVolumeGroupId 182 && mAudioFocusInfo.equals(that.mAudioFocusInfo); 183 } 184 185 @Override 186 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 187 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) hashCode()188 public int hashCode() { 189 return Objects.hash(mAudioFocusInfo.hashCode(), mAudioContextId, mAudioFocusResult, 190 mAudioVolumeGroupId); 191 } 192 193 /** 194 * A builder for {@link AudioFocusEntry} 195 */ 196 @SuppressWarnings("WeakerAccess") 197 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 198 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) 199 public static final class Builder { 200 201 private @NonNull AudioFocusInfo mAudioFocusInfo; 202 private int mAudioContextId; 203 private int mAudioVolumeGroupId; 204 private int mAudioFocusResult; 205 206 private long mBuilderFieldsSet = 0L; 207 Builder(@onNull AudioFocusEntry entry)208 public Builder(@NonNull AudioFocusEntry entry) { 209 this(Objects.requireNonNull(entry, "Audio focus entry can not be null") 210 .mAudioFocusInfo, entry.mAudioContextId, entry.mAudioVolumeGroupId, 211 entry.mAudioFocusResult); 212 } 213 Builder( @onNull AudioFocusInfo audioFocusInfo, int audioContextId, int audioVolumeGroupId, int focusResult)214 public Builder( 215 @NonNull AudioFocusInfo audioFocusInfo, 216 int audioContextId, 217 int audioVolumeGroupId, 218 int focusResult) { 219 mAudioFocusInfo = Objects.requireNonNull(audioFocusInfo, 220 "Audio focus info can not be null"); 221 mAudioContextId = audioContextId; 222 mAudioVolumeGroupId = audioVolumeGroupId; 223 mAudioFocusResult = focusResult; 224 } 225 226 /** see {@link AudioFocusEntry#getAudioFocusInfo()} */ 227 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 228 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) setAudioFocusInfo(@onNull AudioFocusInfo audioFocusInfo)229 public @NonNull Builder setAudioFocusInfo(@NonNull AudioFocusInfo audioFocusInfo) { 230 checkNotUsed(); 231 mBuilderFieldsSet |= 0x1; 232 mAudioFocusInfo = Objects.requireNonNull(audioFocusInfo, 233 "Audio focus info can not be null"); 234 return this; 235 } 236 237 /** see {@link AudioFocusEntry#getAudioContextId()} */ 238 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 239 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) setAudioContextId(int value)240 public @NonNull Builder setAudioContextId(int value) { 241 checkNotUsed(); 242 mBuilderFieldsSet |= 0x2; 243 mAudioContextId = value; 244 return this; 245 } 246 247 /** see {@link AudioFocusEntry#getAudioVolumeGroupId()} */ 248 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 249 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) setAudioVolumeGroupId(int value)250 public @NonNull Builder setAudioVolumeGroupId(int value) { 251 checkNotUsed(); 252 mBuilderFieldsSet |= 0x4; 253 mAudioVolumeGroupId = value; 254 return this; 255 } 256 257 /** see {@link AudioFocusEntry#getAudioFocusResult()} */ 258 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 259 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) setAudioFocusResult(int value)260 public @NonNull Builder setAudioFocusResult(int value) { 261 checkNotUsed(); 262 mBuilderFieldsSet |= 0x8; 263 mAudioFocusResult = value; 264 return this; 265 } 266 267 /** Builds the instance. This builder should not be touched after calling this! */ 268 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 269 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) build()270 public @NonNull AudioFocusEntry build() { 271 checkNotUsed(); 272 mBuilderFieldsSet |= 0x10; // Mark builder used 273 274 AudioFocusEntry o = new AudioFocusEntry( 275 mAudioFocusInfo, 276 mAudioContextId, 277 mAudioVolumeGroupId, 278 mAudioFocusResult); 279 return o; 280 } 281 checkNotUsed()282 private void checkNotUsed() { 283 if ((mBuilderFieldsSet & 0x10) != 0) { 284 throw new IllegalStateException( 285 "This Builder should not be reused. Use a new Builder instance instead"); 286 } 287 } 288 } 289 } 290