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