1 /*
2  * Copyright (C) 2014 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.media;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.annotation.TestApi;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 
26 import java.util.Objects;
27 
28 /**
29  * @hide
30  * A class to encapsulate information about an audio focus owner or request.
31  */
32 @TestApi
33 @SystemApi
34 public final class AudioFocusInfo implements Parcelable {
35 
36     private final @NonNull AudioAttributes mAttributes;
37     private final int mClientUid;
38     private final @NonNull String mClientId;
39     private final @NonNull String mPackageName;
40     private final int mSdkTarget;
41     private int mGainRequest;
42     private int mLossReceived;
43     private int mFlags;
44 
45     // generation count for the validity of a request/response async exchange between
46     // external focus policy and MediaFocusControl
47     private long mGenCount = -1;
48 
49 
50     /**
51      * Class constructor
52      * @param aa
53      * @param clientId
54      * @param packageName
55      * @param gainRequest
56      * @param lossReceived
57      * @param flags
58      * @hide
59      */
AudioFocusInfo(AudioAttributes aa, int clientUid, String clientId, String packageName, int gainRequest, int lossReceived, int flags, int sdk)60     public AudioFocusInfo(AudioAttributes aa, int clientUid, String clientId, String packageName,
61             int gainRequest, int lossReceived, int flags, int sdk) {
62         mAttributes = aa == null ? new AudioAttributes.Builder().build() : aa;
63         mClientUid = clientUid;
64         mClientId = clientId == null ? "" : clientId;
65         mPackageName = packageName == null ? "" : packageName;
66         mGainRequest = gainRequest;
67         mLossReceived = lossReceived;
68         mFlags = flags;
69         mSdkTarget = sdk;
70     }
71 
72     /** @hide */
setGen(long g)73     public void setGen(long g) {
74         mGenCount = g;
75     }
76 
77     /** @hide */
getGen()78     public long getGen() {
79         return mGenCount;
80     }
81 
82 
83     /**
84      * The audio attributes for the audio focus request.
85      * @return non-null {@link AudioAttributes}.
86      */
getAttributes()87     public @NonNull AudioAttributes getAttributes() {
88         return mAttributes;
89     }
90 
getClientUid()91     public int getClientUid() {
92         return mClientUid;
93     }
94 
getClientId()95     public @NonNull String getClientId() {
96         return mClientId;
97     }
98 
getPackageName()99     public @NonNull String getPackageName() {
100         return mPackageName;
101     }
102 
103     /**
104      * The type of audio focus gain request.
105      * @return one of {@link AudioManager#AUDIOFOCUS_GAIN},
106      *     {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
107      *     {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK},
108      *     {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}.
109      */
getGainRequest()110     public int getGainRequest() { return mGainRequest; }
111 
112     /**
113      * The type of audio focus loss that was received by the
114      * {@link AudioManager.OnAudioFocusChangeListener} if one was set.
115      * @return 0 if focus wasn't lost, or one of {@link AudioManager#AUDIOFOCUS_LOSS},
116      *   {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT} or
117      *   {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}.
118      */
getLossReceived()119     public int getLossReceived() { return mLossReceived; }
120 
121     /** @hide */
getSdkTarget()122     public int getSdkTarget() { return mSdkTarget; }
123 
124     /** @hide */
clearLossReceived()125     public void clearLossReceived() { mLossReceived = 0; }
126 
127     /**
128      * The flags set in the audio focus request.
129      * @return 0 or a combination of {link AudioManager#AUDIOFOCUS_FLAG_DELAY_OK},
130      *     {@link AudioManager#AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS}, and
131      *     {@link AudioManager#AUDIOFOCUS_FLAG_LOCK}.
132      */
getFlags()133     public int getFlags() { return mFlags; }
134 
135     @Override
describeContents()136     public int describeContents() {
137         return 0;
138     }
139 
140     @Override
writeToParcel(Parcel dest, int flags)141     public void writeToParcel(Parcel dest, int flags) {
142         mAttributes.writeToParcel(dest, flags);
143         dest.writeInt(mClientUid);
144         dest.writeString(mClientId);
145         dest.writeString(mPackageName);
146         dest.writeInt(mGainRequest);
147         dest.writeInt(mLossReceived);
148         dest.writeInt(mFlags);
149         dest.writeInt(mSdkTarget);
150         dest.writeLong(mGenCount);
151     }
152 
153     @Override
hashCode()154     public int hashCode() {
155         return Objects.hash(mAttributes, mClientUid, mClientId, mPackageName, mGainRequest, mFlags);
156     }
157 
158     @Override
equals(@ullable Object obj)159     public boolean equals(@Nullable Object obj) {
160         if (this == obj)
161             return true;
162         if (obj == null)
163             return false;
164         if (getClass() != obj.getClass())
165             return false;
166         AudioFocusInfo other = (AudioFocusInfo) obj;
167         if (!mAttributes.equals(other.mAttributes)) {
168             return false;
169         }
170         if (mClientUid != other.mClientUid) {
171             return false;
172         }
173         if (!mClientId.equals(other.mClientId)) {
174             return false;
175         }
176         if (!mPackageName.equals(other.mPackageName)) {
177             return false;
178         }
179         if (mGainRequest != other.mGainRequest) {
180             return false;
181         }
182         if (mLossReceived != other.mLossReceived) {
183             return false;
184         }
185         if (mFlags != other.mFlags) {
186             return false;
187         }
188         if (mSdkTarget != other.mSdkTarget) {
189             return false;
190         }
191         // mGenCount is not used to verify equality between two focus holds as multiple requests
192         // (hence of different generations) could correspond to the same hold
193         return true;
194     }
195 
196     public static final @android.annotation.NonNull Parcelable.Creator<AudioFocusInfo> CREATOR
197             = new Parcelable.Creator<AudioFocusInfo>() {
198 
199         public AudioFocusInfo createFromParcel(Parcel in) {
200             final AudioFocusInfo afi = new AudioFocusInfo(
201                     AudioAttributes.CREATOR.createFromParcel(in), //AudioAttributes aa
202                     in.readInt(), // int clientUid
203                     in.readString(), //String clientId
204                     in.readString(), //String packageName
205                     in.readInt(), //int gainRequest
206                     in.readInt(), //int lossReceived
207                     in.readInt(), //int flags
208                     in.readInt()  //int sdkTarget
209                     );
210             afi.setGen(in.readLong());
211             return afi;
212         }
213 
214         public AudioFocusInfo[] newArray(int size) {
215             return new AudioFocusInfo[size];
216         }
217     };
218 }
219