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.media; 18 19 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.BOILERPLATE_CODE; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.SystemApi; 24 import android.car.annotation.ApiRequirements; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 28 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport; 29 import com.android.internal.annotations.VisibleForTesting; 30 import com.android.internal.util.Preconditions; 31 32 import java.util.Objects; 33 34 /** 35 * Class to encapsulate car volume group information. 36 * 37 * @hide 38 */ 39 @SystemApi 40 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 41 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) 42 public final class CarVolumeGroupInfo implements Parcelable { 43 44 private static final long IS_USED_FIELD_SET = 0x01; 45 46 private final String mName; 47 private final int mZoneId; 48 private final int mId; 49 private final int mVolumeGainIndex; 50 private final int mMaxVolumeGainIndex; 51 private final int mMinVolumeGainIndex; 52 private final boolean mIsMuted; 53 private final boolean mIsBlocked; 54 private final boolean mIsAttenuated; 55 CarVolumeGroupInfo( String name, int zoneId, int id, int volumeGainIndex, int maxVolumeGainIndex, int minVolumeGainIndex, boolean isMuted, boolean isBlocked, boolean isAttenuated)56 private CarVolumeGroupInfo( 57 String name, 58 int zoneId, 59 int id, 60 int volumeGainIndex, 61 int maxVolumeGainIndex, 62 int minVolumeGainIndex, 63 boolean isMuted, 64 boolean isBlocked, 65 boolean isAttenuated) { 66 mName = Objects.requireNonNull(name, "Volume info name can not be null"); 67 mZoneId = zoneId; 68 mId = id; 69 mVolumeGainIndex = volumeGainIndex; 70 mMaxVolumeGainIndex = maxVolumeGainIndex; 71 mMinVolumeGainIndex = minVolumeGainIndex; 72 mIsMuted = isMuted; 73 mIsBlocked = isBlocked; 74 mIsAttenuated = isAttenuated; 75 } 76 77 /** 78 * Creates volume info from parcel 79 * 80 * @hide 81 */ 82 @VisibleForTesting() CarVolumeGroupInfo(Parcel in)83 public CarVolumeGroupInfo(Parcel in) { 84 mZoneId = in.readInt(); 85 mId = in.readInt(); 86 mName = in.readString(); 87 mVolumeGainIndex = in.readInt(); 88 mMaxVolumeGainIndex = in.readInt(); 89 mMinVolumeGainIndex = in.readInt(); 90 mIsMuted = in.readBoolean(); 91 mIsBlocked = in.readBoolean(); 92 mIsAttenuated = in.readBoolean(); 93 94 } 95 96 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 97 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) 98 @NonNull 99 public static final Creator<CarVolumeGroupInfo> CREATOR = new Creator<>() { 100 @Override 101 @NonNull 102 public CarVolumeGroupInfo createFromParcel(@NonNull Parcel in) { 103 return new CarVolumeGroupInfo(in); 104 } 105 106 @Override 107 @NonNull 108 public CarVolumeGroupInfo[] newArray(int size) { 109 return new CarVolumeGroupInfo[size]; 110 } 111 }; 112 113 @ExcludeFromCodeCoverageGeneratedReport(reason = BOILERPLATE_CODE) 114 @Override 115 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 116 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) describeContents()117 public int describeContents() { 118 return 0; 119 } 120 121 /** 122 * Returns the volume group name 123 */ 124 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 125 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) getName()126 public @NonNull String getName() { 127 return mName; 128 } 129 130 /** 131 * Returns the zone id where the volume group belongs 132 */ 133 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 134 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) getZoneId()135 public int getZoneId() { 136 return mZoneId; 137 } 138 139 /** 140 * Returns the volume group id 141 */ 142 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 143 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) getId()144 public int getId() { 145 return mId; 146 } 147 148 /** 149 * Returns the volume group volume gain index 150 */ 151 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 152 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) getVolumeGainIndex()153 public int getVolumeGainIndex() { 154 return mVolumeGainIndex; 155 } 156 157 /** 158 * Returns the volume group max volume gain index 159 */ 160 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 161 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) getMaxVolumeGainIndex()162 public int getMaxVolumeGainIndex() { 163 return mMaxVolumeGainIndex; 164 } 165 166 /** 167 * Returns the volume group min volume gain index 168 */ 169 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 170 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) getMinVolumeGainIndex()171 public int getMinVolumeGainIndex() { 172 return mMinVolumeGainIndex; 173 } 174 175 /** 176 * Returns the volume mute state, {@code true} for muted 177 */ 178 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 179 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) isMuted()180 public boolean isMuted() { 181 return mIsMuted; 182 } 183 184 /** 185 * Returns the volume blocked state, {@code true} for blocked 186 */ 187 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 188 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) isBlocked()189 public boolean isBlocked() { 190 return mIsBlocked; 191 } 192 193 /** 194 * Returns the volume attenuated state, {@code true} for attenuated 195 */ 196 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 197 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) isAttenuated()198 public boolean isAttenuated() { 199 return mIsAttenuated; 200 } 201 202 @Override 203 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 204 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) toString()205 public String toString() { 206 return new StringBuilder().append("CarVolumeGroupId { .name = ").append(mName) 207 .append(", zone id = ").append(mZoneId).append(" id = ").append(mId) 208 .append(", gain = ").append(mVolumeGainIndex) 209 .append(", max gain = ").append(mMaxVolumeGainIndex) 210 .append(", min gain = ").append(mMinVolumeGainIndex) 211 .append(", muted = ").append(mIsMuted) 212 .append(", blocked = ").append(mIsBlocked) 213 .append(", attenuated = ").append(mIsAttenuated) 214 .append(" }").toString(); 215 } 216 217 @Override 218 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 219 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) writeToParcel(@onNull Parcel dest, int flags)220 public void writeToParcel(@NonNull Parcel dest, int flags) { 221 dest.writeInt(mZoneId); 222 dest.writeInt(mId); 223 dest.writeString(mName); 224 dest.writeInt(mVolumeGainIndex); 225 dest.writeInt(mMaxVolumeGainIndex); 226 dest.writeInt(mMinVolumeGainIndex); 227 dest.writeBoolean(mIsMuted); 228 dest.writeBoolean(mIsBlocked); 229 dest.writeBoolean(mIsAttenuated); 230 } 231 232 /** 233 * Determines if it is the same volume group, only comparing the group name, zone id, and 234 * group id. 235 * 236 * @return {@code true} if the group info is the same, {@code false} otherwise 237 */ 238 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 239 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) isSameVolumeGroup(@ullable CarVolumeGroupInfo group)240 public boolean isSameVolumeGroup(@Nullable CarVolumeGroupInfo group) { 241 return group != null && mZoneId == group.mZoneId && mId == group.mId 242 && mName.equals(group.mName); 243 } 244 245 @Override 246 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 247 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) equals(Object o)248 public boolean equals(Object o) { 249 if (this == o) { 250 return true; 251 } 252 253 if (!(o instanceof CarVolumeGroupInfo)) { 254 return false; 255 } 256 257 CarVolumeGroupInfo that = (CarVolumeGroupInfo) o; 258 259 return isSameVolumeGroup(that) && mVolumeGainIndex == that.mVolumeGainIndex 260 && mMaxVolumeGainIndex == that.mMaxVolumeGainIndex 261 && mMinVolumeGainIndex == that.mMinVolumeGainIndex 262 && mIsMuted == that.mIsMuted && mIsBlocked == that.mIsBlocked 263 && mIsAttenuated == that.mIsAttenuated; 264 } 265 266 @Override 267 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 268 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) hashCode()269 public int hashCode() { 270 return Objects.hash(mName, mZoneId, mId, mVolumeGainIndex, mMaxVolumeGainIndex, 271 mMinVolumeGainIndex, mIsMuted, mIsBlocked, mIsAttenuated); 272 } 273 274 /** 275 * A builder for {@link CarVolumeGroupInfo} 276 */ 277 @SuppressWarnings("WeakerAccess") 278 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 279 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) 280 public static final class Builder { 281 282 private @NonNull String mName; 283 private int mZoneId; 284 private int mId; 285 private int mVolumeGainIndex; 286 private int mMinVolumeGainIndex; 287 private int mMaxVolumeGainIndex; 288 private boolean mIsMuted; 289 private boolean mIsBlocked; 290 private boolean mIsAttenuated; 291 292 private long mBuilderFieldsSet = 0L; 293 Builder(@onNull String name, int zoneId, int id)294 public Builder(@NonNull String name, int zoneId, int id) { 295 mName = Objects.requireNonNull(name, "Volume info name can not be null"); 296 mZoneId = zoneId; 297 mId = id; 298 } 299 Builder(@onNull CarVolumeGroupInfo info)300 public Builder(@NonNull CarVolumeGroupInfo info) { 301 Objects.requireNonNull(info, "Volume info can not be null"); 302 mName = info.mName; 303 mZoneId = info.mZoneId; 304 mId = info.mId; 305 mVolumeGainIndex = info.mVolumeGainIndex; 306 mMaxVolumeGainIndex = info.mMaxVolumeGainIndex; 307 mMinVolumeGainIndex = info.mMinVolumeGainIndex; 308 mIsMuted = info.mIsMuted; 309 mIsBlocked = info.mIsBlocked; 310 mIsAttenuated = info.mIsAttenuated; 311 } 312 313 /** 314 * Sets the volume group volume gain index 315 */ 316 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 317 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) setVolumeGainIndex(int gainIndex)318 public @NonNull Builder setVolumeGainIndex(int gainIndex) { 319 checkNotUsed(); 320 mVolumeGainIndex = gainIndex; 321 return this; 322 } 323 324 /** 325 * Sets the volume group max volume gain index 326 */ 327 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 328 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) setMaxVolumeGainIndex(int gainIndex)329 public @NonNull Builder setMaxVolumeGainIndex(int gainIndex) { 330 checkNotUsed(); 331 mMaxVolumeGainIndex = gainIndex; 332 return this; 333 } 334 335 /** 336 * Sets the volume group min volume gain index 337 */ 338 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 339 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) setMinVolumeGainIndex(int gainIndex)340 public @NonNull Builder setMinVolumeGainIndex(int gainIndex) { 341 checkNotUsed(); 342 mMinVolumeGainIndex = gainIndex; 343 return this; 344 } 345 346 /** 347 * Sets the volume group muted state, {@code true} for muted 348 */ 349 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 350 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) setMuted(boolean muted)351 public @NonNull Builder setMuted(boolean muted) { 352 checkNotUsed(); 353 mIsMuted = muted; 354 return this; 355 } 356 357 /** 358 * Sets the volume group blocked state, {@code true} for blocked 359 */ 360 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 361 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) setBlocked(boolean blocked)362 public @NonNull Builder setBlocked(boolean blocked) { 363 checkNotUsed(); 364 mIsBlocked = blocked; 365 return this; 366 } 367 368 /** 369 * Sets the volume group attenuated state, {@code true} for attenuated 370 */ 371 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 372 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) setAttenuated(boolean attenuated)373 public @NonNull Builder setAttenuated(boolean attenuated) { 374 checkNotUsed(); 375 mIsAttenuated = attenuated; 376 return this; 377 } 378 379 /** 380 * Builds the instance. 381 * 382 * @throws IllegalArgumentException if min volume gain index is larger than max volume 383 * gain index, or if the volume gain index is outside the range of max and min volume 384 * gain index. 385 * 386 * @throws IllegalStateException if the constructor is re-used 387 */ 388 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_3, 389 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) 390 @NonNull build()391 public CarVolumeGroupInfo build() { 392 checkNotUsed(); 393 validateGainIndexRange(); 394 395 mBuilderFieldsSet |= IS_USED_FIELD_SET; // Mark builder used 396 397 398 return new CarVolumeGroupInfo(mName, mZoneId, mId, mVolumeGainIndex, 399 mMaxVolumeGainIndex, mMinVolumeGainIndex, mIsMuted, mIsBlocked, mIsAttenuated); 400 } 401 validateGainIndexRange()402 private void validateGainIndexRange() { 403 Preconditions.checkArgument(mMinVolumeGainIndex < mMaxVolumeGainIndex, 404 "Min volume gain index %d must be smaller than max volume gain index %d", 405 mMinVolumeGainIndex, mMaxVolumeGainIndex); 406 407 Preconditions.checkArgumentInRange(mVolumeGainIndex, mMinVolumeGainIndex, 408 mMaxVolumeGainIndex, "Volume gain index"); 409 } 410 411 private void checkNotUsed() throws IllegalStateException { 412 if ((mBuilderFieldsSet & IS_USED_FIELD_SET) != 0) { 413 throw new IllegalStateException( 414 "This Builder should not be reused. Use a new Builder instance instead"); 415 } 416 } 417 } 418 } 419