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