1 /*
2  * Copyright (C) 2012 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.SystemApi;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 
24 import java.util.Objects;
25 
26 /**
27  * The MediaSyncEvent class defines events that can be used to synchronize playback or capture
28  * actions between different players and recorders.
29  * <p>For instance, {@link AudioRecord#startRecording(MediaSyncEvent)} is used to start capture
30  * only when the playback on a particular audio session is complete.
31  * The audio session ID is retrieved from a player (e.g {@link MediaPlayer}, {@link AudioTrack} or
32  * {@link ToneGenerator}) by use of the getAudioSessionId() method.
33  */
34 public class MediaSyncEvent implements Parcelable {
35 
36     /**
37      * No sync event specified. When used with a synchronized playback or capture method, the
38      * behavior is equivalent to calling the corresponding non synchronized method.
39      */
40     public static final int SYNC_EVENT_NONE = AudioSystem.SYNC_EVENT_NONE;
41 
42     /**
43      * The corresponding action is triggered only when the presentation is completed
44      * (meaning the media has been presented to the user) on the specified session.
45      * A synchronization of this type requires a source audio session ID to be set via
46      * {@link #setAudioSessionId(int)} method.
47      */
48     public static final int SYNC_EVENT_PRESENTATION_COMPLETE =
49             AudioSystem.SYNC_EVENT_PRESENTATION_COMPLETE;
50 
51     /**
52      * @hide
53      * Used when sharing audio history between AudioRecord instances.
54      * See {@link AudioRecord.Builder#setSharedAudioEvent(MediaSyncEvent).
55      */
56     @SystemApi
57     public static final int SYNC_EVENT_SHARE_AUDIO_HISTORY =
58             AudioSystem.SYNC_EVENT_SHARE_AUDIO_HISTORY;
59 
60     /**
61      * Creates a synchronization event of the sepcified type.
62      *
63      * <p>The type specifies which kind of event is monitored.
64      * For instance, event {@link #SYNC_EVENT_PRESENTATION_COMPLETE} corresponds to the audio being
65      * presented to the user on a particular audio session.
66      * @param eventType the synchronization event type.
67      * @return the MediaSyncEvent created.
68      * @throws java.lang.IllegalArgumentException
69      */
createEvent(int eventType)70     public static MediaSyncEvent createEvent(int eventType)
71                             throws IllegalArgumentException {
72         if (!isValidType(eventType)) {
73             throw (new IllegalArgumentException(eventType
74                     + "is not a valid MediaSyncEvent type."));
75         } else {
76             return new MediaSyncEvent(eventType);
77         }
78     }
79 
80     private final int mType;
81     private int mAudioSession = 0;
82 
MediaSyncEvent(int eventType)83     private MediaSyncEvent(int eventType) {
84         mType = eventType;
85     }
86 
87     /**
88      * Sets the event source audio session ID.
89      *
90      * <p>The audio session ID specifies on which audio session the synchronization event should be
91      * monitored.
92      * It is mandatory for certain event types (e.g. {@link #SYNC_EVENT_PRESENTATION_COMPLETE}).
93      * For instance, the audio session ID can be retrieved via
94      * {@link MediaPlayer#getAudioSessionId()} when monitoring an event on a particular MediaPlayer.
95      * @param audioSessionId the audio session ID of the event source being monitored.
96      * @return the MediaSyncEvent the method is called on.
97      * @throws java.lang.IllegalArgumentException
98      */
setAudioSessionId(int audioSessionId)99     public MediaSyncEvent setAudioSessionId(int audioSessionId)
100             throws IllegalArgumentException {
101         if (audioSessionId > 0) {
102             mAudioSession = audioSessionId;
103         } else {
104             throw (new IllegalArgumentException(audioSessionId + " is not a valid session ID."));
105         }
106         return this;
107     }
108 
109     /**
110      * Gets the synchronization event type.
111      *
112      * @return the synchronization event type.
113      */
getType()114     public int getType() {
115         return mType;
116     }
117 
118     /**
119      * Gets the synchronization event audio session ID.
120      *
121      * @return the synchronization audio session ID. The returned audio session ID is 0 if it has
122      * not been set.
123      */
getAudioSessionId()124     public int getAudioSessionId() {
125         return mAudioSession;
126     }
127 
isValidType(int type)128     private static boolean isValidType(int type) {
129         switch (type) {
130             case SYNC_EVENT_NONE:
131             case SYNC_EVENT_PRESENTATION_COMPLETE:
132             case SYNC_EVENT_SHARE_AUDIO_HISTORY:
133                 return true;
134             default:
135                 return false;
136         }
137     }
138 
139     // Parcelable implementation
140     @Override
describeContents()141     public int describeContents() {
142         return 0;
143     }
144 
145     @Override
writeToParcel(@onNull Parcel dest, int flags)146     public void writeToParcel(@NonNull Parcel dest, int flags) {
147         Objects.requireNonNull(dest);
148         dest.writeInt(mType);
149         dest.writeInt(mAudioSession);
150     }
151 
MediaSyncEvent(Parcel in)152     private MediaSyncEvent(Parcel in) {
153         mType = in.readInt();
154         mAudioSession = in.readInt();
155     }
156 
157     public static final @NonNull Parcelable.Creator<MediaSyncEvent> CREATOR =
158             new Parcelable.Creator<MediaSyncEvent>() {
159         /**
160          * Rebuilds an MediaSyncEvent previously stored with writeToParcel().
161          * @param p Parcel object to read the MediaSyncEvent from
162          * @return a new MediaSyncEvent created from the data in the parcel
163          */
164         public MediaSyncEvent createFromParcel(Parcel p) {
165             return new MediaSyncEvent(p);
166         }
167         public MediaSyncEvent[] newArray(int size) {
168             return new MediaSyncEvent[size];
169         }
170     };
171 
172     @Override
equals(Object o)173     public boolean equals(Object o) {
174         if (this == o) return true;
175         if (o == null || getClass() != o.getClass()) return false;
176 
177         MediaSyncEvent that = (MediaSyncEvent) o;
178         return ((mType == that.mType)
179                 && (mAudioSession == that.mAudioSession));
180     }
181 
182     @Override
hashCode()183     public int hashCode() {
184         return Objects.hash(mType, mAudioSession);
185     }
186 
187     @Override
toString()188     public String toString() {
189         return new String("MediaSyncEvent:"
190                 + " type=" + typeToString(mType)
191                 + " session=" + mAudioSession);
192     }
193 
194     /**
195      * Returns the string representation for the type.
196      * @param type one of the {@link MediaSyncEvent} type constants
197      * @hide
198      */
typeToString(int type)199     public static @NonNull String typeToString(int type) {
200         switch (type) {
201             case SYNC_EVENT_NONE:
202                 return "SYNC_EVENT_NONE";
203             case SYNC_EVENT_PRESENTATION_COMPLETE:
204                 return "SYNC_EVENT_PRESENTATION_COMPLETE";
205             case SYNC_EVENT_SHARE_AUDIO_HISTORY:
206                 return "SYNC_EVENT_SHARE_AUDIO_HISTORY";
207             default:
208                 return "unknown event type " + type;
209         }
210     }
211 
212 }
213