Merge "AudioRecord: Allow to share capture history." into sc-dev
This commit is contained in:
@@ -23413,11 +23413,14 @@ package android.media {
|
||||
method public void onError(@NonNull android.media.MediaSync, int, int);
|
||||
}
|
||||
|
||||
public class MediaSyncEvent {
|
||||
public class MediaSyncEvent implements android.os.Parcelable {
|
||||
method public static android.media.MediaSyncEvent createEvent(int) throws java.lang.IllegalArgumentException;
|
||||
method public int describeContents();
|
||||
method public int getAudioSessionId();
|
||||
method public int getType();
|
||||
method public android.media.MediaSyncEvent setAudioSessionId(int) throws java.lang.IllegalArgumentException;
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.media.MediaSyncEvent> CREATOR;
|
||||
field public static final int SYNC_EVENT_NONE = 0; // 0x0
|
||||
field public static final int SYNC_EVENT_PRESENTATION_COMPLETE = 1; // 0x1
|
||||
}
|
||||
|
||||
@@ -5271,11 +5271,15 @@ package android.media {
|
||||
|
||||
public class AudioRecord implements android.media.AudioRecordingMonitor android.media.AudioRouting android.media.MicrophoneDirection {
|
||||
ctor @RequiresPermission(android.Manifest.permission.RECORD_AUDIO) public AudioRecord(android.media.AudioAttributes, android.media.AudioFormat, int, int) throws java.lang.IllegalArgumentException;
|
||||
method public static long getMaxSharedAudioHistoryMillis();
|
||||
method @NonNull @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_HOTWORD) public android.media.MediaSyncEvent shareAudioHistory(@NonNull String, @IntRange(from=0) long);
|
||||
}
|
||||
|
||||
public static class AudioRecord.Builder {
|
||||
method public android.media.AudioRecord.Builder setAudioAttributes(@NonNull android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
|
||||
method @NonNull @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_HOTWORD) public android.media.AudioRecord.Builder setMaxSharedAudioHistoryMillis(long) throws java.lang.IllegalArgumentException;
|
||||
method public android.media.AudioRecord.Builder setSessionId(int) throws java.lang.IllegalArgumentException;
|
||||
method @NonNull public android.media.AudioRecord.Builder setSharedAudioEvent(@NonNull android.media.MediaSyncEvent) throws java.lang.IllegalArgumentException;
|
||||
}
|
||||
|
||||
public final class AudioRecordingConfiguration implements android.os.Parcelable {
|
||||
@@ -5338,6 +5342,10 @@ package android.media {
|
||||
method public void onPreferredFeaturesChanged(@NonNull java.util.List<java.lang.String>);
|
||||
}
|
||||
|
||||
public class MediaSyncEvent implements android.os.Parcelable {
|
||||
field public static final int SYNC_EVENT_SHARE_AUDIO_HISTORY = 100; // 0x64
|
||||
}
|
||||
|
||||
public class PlayerProxy {
|
||||
method public void pause();
|
||||
method public void setPan(float);
|
||||
|
||||
@@ -189,7 +189,8 @@ static jint android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject w
|
||||
jobject jaa, jintArray jSampleRate, jint channelMask,
|
||||
jint channelIndexMask, jint audioFormat,
|
||||
jint buffSizeInBytes, jintArray jSession,
|
||||
jobject jIdentity, jlong nativeRecordInJavaObj) {
|
||||
jobject jIdentity, jlong nativeRecordInJavaObj,
|
||||
jint sharedAudioHistoryMs) {
|
||||
//ALOGV(">> Entering android_media_AudioRecord_setup");
|
||||
//ALOGV("sampleRate=%d, audioFormat=%d, channel mask=%x, buffSizeInBytes=%d "
|
||||
// "nativeRecordInJavaObj=0x%llX",
|
||||
@@ -288,20 +289,18 @@ static jint android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject w
|
||||
lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this);
|
||||
lpCallbackData->busy = false;
|
||||
|
||||
const status_t status = lpRecorder->set(paa->source,
|
||||
sampleRateInHertz,
|
||||
format, // word length, PCM
|
||||
localChanMask,
|
||||
frameCount,
|
||||
recorderCallback,// callback_t
|
||||
lpCallbackData,// void* user
|
||||
0, // notificationFrames,
|
||||
true, // threadCanCallJava
|
||||
sessionId,
|
||||
AudioRecord::TRANSFER_DEFAULT,
|
||||
flags,
|
||||
-1, -1, // default uid, pid
|
||||
paa.get());
|
||||
const status_t status =
|
||||
lpRecorder->set(paa->source, sampleRateInHertz,
|
||||
format, // word length, PCM
|
||||
localChanMask, frameCount,
|
||||
recorderCallback, // callback_t
|
||||
lpCallbackData, // void* user
|
||||
0, // notificationFrames,
|
||||
true, // threadCanCallJava
|
||||
sessionId, AudioRecord::TRANSFER_DEFAULT, flags, -1,
|
||||
-1, // default uid, pid
|
||||
paa.get(), AUDIO_PORT_HANDLE_NONE, MIC_DIRECTION_UNSPECIFIED,
|
||||
MIC_FIELD_DIMENSION_DEFAULT, sharedAudioHistoryMs);
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
ALOGE("Error creating AudioRecord instance: initialization check failed with status %d.",
|
||||
@@ -877,6 +876,23 @@ static void android_media_AudioRecord_setLogSessionId(JNIEnv *env, jobject thiz,
|
||||
record->setLogSessionId(logSessionId.c_str());
|
||||
}
|
||||
|
||||
static jint android_media_AudioRecord_shareAudioHistory(JNIEnv *env, jobject thiz,
|
||||
jstring jSharedPackageName,
|
||||
jlong jSharedStartMs) {
|
||||
sp<AudioRecord> record = getAudioRecord(env, thiz);
|
||||
if (record == nullptr) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException",
|
||||
"Unable to retrieve AudioRecord pointer for setLogSessionId()");
|
||||
}
|
||||
if (jSharedPackageName == nullptr) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", "package name cannot be null");
|
||||
}
|
||||
ScopedUtfChars nSharedPackageName(env, jSharedPackageName);
|
||||
ALOGV("%s: nSharedPackageName '%s'", __func__, nSharedPackageName.c_str());
|
||||
return nativeToJavaStatus(record->shareAudioHistory(nSharedPackageName.c_str(),
|
||||
static_cast<int64_t>(jSharedStartMs)));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
static jint android_media_AudioRecord_get_port_id(JNIEnv *env, jobject thiz) {
|
||||
sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
|
||||
@@ -896,7 +912,7 @@ static const JNINativeMethod gMethods[] = {
|
||||
{"native_start", "(II)I", (void *)android_media_AudioRecord_start},
|
||||
{"native_stop", "()V", (void *)android_media_AudioRecord_stop},
|
||||
{"native_setup",
|
||||
"(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILandroid/media/permission/Identity;J)I",
|
||||
"(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILandroid/media/permission/Identity;JI)I",
|
||||
(void *)android_media_AudioRecord_setup},
|
||||
{"native_finalize", "()V", (void *)android_media_AudioRecord_finalize},
|
||||
{"native_release", "()V", (void *)android_media_AudioRecord_release},
|
||||
@@ -936,6 +952,8 @@ static const JNINativeMethod gMethods[] = {
|
||||
(void *)android_media_AudioRecord_set_preferred_microphone_field_dimension},
|
||||
{"native_setLogSessionId", "(Ljava/lang/String;)V",
|
||||
(void *)android_media_AudioRecord_setLogSessionId},
|
||||
{"native_shareAudioHistory", "(Ljava/lang/String;J)I",
|
||||
(void *)android_media_AudioRecord_shareAudioHistory},
|
||||
};
|
||||
|
||||
// field names found in android/media/AudioRecord.java
|
||||
|
||||
@@ -21,6 +21,7 @@ import static android.media.permission.PermissionUtil.myIdentity;
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.FloatRange;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
@@ -358,7 +359,8 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
|
||||
@RequiresPermission(android.Manifest.permission.RECORD_AUDIO)
|
||||
public AudioRecord(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
|
||||
int sessionId) throws IllegalArgumentException {
|
||||
this(attributes, format, bufferSizeInBytes, sessionId, ActivityThread.currentApplication());
|
||||
this(attributes, format, bufferSizeInBytes, sessionId,
|
||||
ActivityThread.currentApplication(), 0 /*maxSharedAudioHistoryMs*/);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,7 +385,8 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
private AudioRecord(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
|
||||
int sessionId, @Nullable Context context) throws IllegalArgumentException {
|
||||
int sessionId, @Nullable Context context,
|
||||
int maxSharedAudioHistoryMs) throws IllegalArgumentException {
|
||||
mRecordingState = RECORDSTATE_STOPPED;
|
||||
|
||||
if (attributes == null) {
|
||||
@@ -455,12 +458,14 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
|
||||
int[] sampleRate = new int[] {mSampleRate};
|
||||
int[] session = new int[1];
|
||||
session[0] = sessionId;
|
||||
|
||||
//TODO: update native initialization when information about hardware init failure
|
||||
// due to capture device already open is available.
|
||||
int initResult = native_setup(new WeakReference<AudioRecord>(this),
|
||||
mAudioAttributes, sampleRate, mChannelMask, mChannelIndexMask,
|
||||
mAudioFormat, mNativeBufferSizeInBytes,
|
||||
session, identity, 0 /*nativeRecordInJavaObj*/);
|
||||
session, identity, 0 /*nativeRecordInJavaObj*/,
|
||||
maxSharedAudioHistoryMs);
|
||||
if (initResult != SUCCESS) {
|
||||
loge("Error code "+initResult+" when initializing native AudioRecord object.");
|
||||
return; // with mState == STATE_UNINITIALIZED
|
||||
@@ -522,7 +527,8 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
|
||||
0 /*mNativeBufferSizeInBytes*/,
|
||||
session,
|
||||
myIdentity(null),
|
||||
nativeRecordInJavaObj);
|
||||
nativeRecordInJavaObj,
|
||||
0);
|
||||
if (initResult != SUCCESS) {
|
||||
loge("Error code "+initResult+" when initializing native AudioRecord object.");
|
||||
return; // with mState == STATE_UNINITIALIZED
|
||||
@@ -581,7 +587,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
|
||||
private int mBufferSizeInBytes;
|
||||
private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
|
||||
private int mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT;
|
||||
|
||||
private int mMaxSharedAudioHistoryMs = 0;
|
||||
private static final int PRIVACY_SENSITIVE_DEFAULT = -1;
|
||||
private static final int PRIVACY_SENSITIVE_DISABLED = 0;
|
||||
private static final int PRIVACY_SENSITIVE_ENABLED = 1;
|
||||
@@ -747,7 +753,12 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
|
||||
if (sessionId < 0) {
|
||||
throw new IllegalArgumentException("Invalid session ID " + sessionId);
|
||||
}
|
||||
mSessionId = sessionId;
|
||||
// Do not override a session ID previously set with setSharedAudioEvent()
|
||||
if (mSessionId == AudioManager.AUDIO_SESSION_ID_GENERATE) {
|
||||
mSessionId = sessionId;
|
||||
} else {
|
||||
Log.e(TAG, "setSessionId() called twice or after setSharedAudioEvent()");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -771,6 +782,57 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Specifies the maximum duration in the past of the this AudioRecord's capture buffer
|
||||
* that can be shared with another app by calling
|
||||
* {@link AudioRecord#shareAudioHistory(String, long)}.
|
||||
* @param maxSharedAudioHistoryMillis the maximum duration that will be available
|
||||
* in milliseconds.
|
||||
* @return the same Builder instance.
|
||||
* @throws IllegalArgumentException
|
||||
*
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_HOTWORD)
|
||||
public @NonNull Builder setMaxSharedAudioHistoryMillis(long maxSharedAudioHistoryMillis)
|
||||
throws IllegalArgumentException {
|
||||
if (maxSharedAudioHistoryMillis <= 0
|
||||
|| maxSharedAudioHistoryMillis > MAX_SHARED_AUDIO_HISTORY_MS) {
|
||||
throw new IllegalArgumentException("Illegal maxSharedAudioHistoryMillis argument");
|
||||
}
|
||||
mMaxSharedAudioHistoryMs = (int) maxSharedAudioHistoryMillis;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Indicates that this AudioRecord will use the audio history shared by another app's
|
||||
* AudioRecord. See {@link AudioRecord#shareAudioHistory(String, long)}.
|
||||
* The audio session ID set with {@link AudioRecord.Builder#setSessionId(int)} will be
|
||||
* ignored if this method is used.
|
||||
* @param event The {@link MediaSyncEvent} provided by the app sharing its audio history
|
||||
* with this AudioRecord.
|
||||
* @return the same Builder instance.
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
@SystemApi
|
||||
public @NonNull Builder setSharedAudioEvent(@NonNull MediaSyncEvent event)
|
||||
throws IllegalArgumentException {
|
||||
Objects.requireNonNull(event);
|
||||
if (event.getType() != MediaSyncEvent.SYNC_EVENT_SHARE_AUDIO_HISTORY) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid event type " + event.getType());
|
||||
}
|
||||
if (event.getAudioSessionId() == AudioSystem.AUDIO_SESSION_ALLOCATE) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid session ID " + event.getAudioSessionId());
|
||||
}
|
||||
// This prevails over a session ID set with setSessionId()
|
||||
mSessionId = event.getAudioSessionId();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new {@link AudioRecord} instance successfully initialized with all
|
||||
* the parameters set on this <code>Builder</code>.
|
||||
@@ -837,7 +899,8 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
|
||||
* mFormat.getBytesPerSample(mFormat.getEncoding());
|
||||
}
|
||||
final AudioRecord record = new AudioRecord(
|
||||
mAttributes, mFormat, mBufferSizeInBytes, mSessionId, mContext);
|
||||
mAttributes, mFormat, mBufferSizeInBytes, mSessionId, mContext,
|
||||
mMaxSharedAudioHistoryMs);
|
||||
if (record.getState() == STATE_UNINITIALIZED) {
|
||||
// release is not necessary
|
||||
throw new UnsupportedOperationException("Cannot create AudioRecord");
|
||||
@@ -1423,7 +1486,6 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
|
||||
|| (offsetInShorts + sizeInShorts > audioData.length)) {
|
||||
return ERROR_BAD_VALUE;
|
||||
}
|
||||
|
||||
return native_read_in_short_array(audioData, offsetInShorts, sizeInShorts,
|
||||
readMode == READ_BLOCKING);
|
||||
}
|
||||
@@ -1642,6 +1704,70 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
|
||||
return AudioManager.getDeviceForPortId(deviceId, AudioManager.GET_DEVICES_INPUTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Must match the native definition in frameworks/av/service/audioflinger/Audioflinger.h.
|
||||
*/
|
||||
private static final long MAX_SHARED_AUDIO_HISTORY_MS = 5000;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* returns the maximum duration in milliseconds of the audio history that can be requested
|
||||
* to be made available to other clients using the same session with
|
||||
* {@Link Builder#setMaxSharedAudioHistory(long)}.
|
||||
*/
|
||||
@SystemApi
|
||||
public static long getMaxSharedAudioHistoryMillis() {
|
||||
return MAX_SHARED_AUDIO_HISTORY_MS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*
|
||||
* A privileged app with permission CAPTURE_AUDIO_HOTWORD can share part of its recent
|
||||
* capture history on a given AudioRecord with the following steps:
|
||||
* 1) Specify the maximum time in the past that will be available for other apps by calling
|
||||
* {@link Builder#setMaxSharedAudioHistoryMillis(long)} when creating the AudioRecord.
|
||||
* 2) Start recording and determine where the other app should start capturing in the past.
|
||||
* 3) Call this method with the package name of the app the history will be shared with and
|
||||
* the intended start time for this app's capture relative to this AudioRecord's start time.
|
||||
* 4) Communicate the {@link MediaSyncEvent} returned by this method to the other app.
|
||||
* 5) The other app will use the MediaSyncEvent when creating its AudioRecord with
|
||||
* {@link Builder#setSharedAudioEvent(MediaSyncEvent).
|
||||
* 6) Only after the other app has started capturing can this app stop capturing and
|
||||
* release its AudioRecord.
|
||||
* This method is intended to be called only once: if called multiple times, only the last
|
||||
* request will be honored.
|
||||
* The implementation is "best effort": if the specified start time if too far in the past
|
||||
* compared to the max available history specified, the start time will be adjusted to the
|
||||
* start of the available history.
|
||||
* @param sharedPackage the package the history will be shared with
|
||||
* @param startFromMillis the start time, relative to the initial start time of this
|
||||
* AudioRecord, at which the other AudioRecord will start.
|
||||
* @return a {@link MediaSyncEvent} to be communicated to the app this AudioRecord's audio
|
||||
* history will be shared with.
|
||||
* @throws IllegalArgumentException
|
||||
* @throws SecurityException
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_HOTWORD)
|
||||
@NonNull public MediaSyncEvent shareAudioHistory(@NonNull String sharedPackage,
|
||||
@IntRange(from = 0) long startFromMillis) {
|
||||
Objects.requireNonNull(sharedPackage);
|
||||
if (startFromMillis < 0) {
|
||||
throw new IllegalArgumentException("Illegal negative sharedAudioHistoryMs argument");
|
||||
}
|
||||
int status = native_shareAudioHistory(sharedPackage, startFromMillis);
|
||||
if (status == AudioSystem.BAD_VALUE) {
|
||||
throw new IllegalArgumentException("Illegal sharedAudioHistoryMs argument");
|
||||
} else if (status == AudioSystem.PERMISSION_DENIED) {
|
||||
throw new SecurityException("permission CAPTURE_AUDIO_HOTWORD required");
|
||||
}
|
||||
MediaSyncEvent event =
|
||||
MediaSyncEvent.createEvent(MediaSyncEvent.SYNC_EVENT_SHARE_AUDIO_HISTORY);
|
||||
event.setAudioSessionId(mSessionId);
|
||||
return event;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call BEFORE adding a routing callback handler.
|
||||
*/
|
||||
@@ -2105,13 +2231,14 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
|
||||
identity.packageName = opPackageName;
|
||||
|
||||
return native_setup(audiorecordThis, attributes, sampleRate, channelMask, channelIndexMask,
|
||||
audioFormat, buffSizeInBytes, sessionId, identity, nativeRecordInJavaObj);
|
||||
audioFormat, buffSizeInBytes, sessionId, identity, nativeRecordInJavaObj, 0);
|
||||
}
|
||||
|
||||
private native int native_setup(Object audiorecordThis,
|
||||
Object /*AudioAttributes*/ attributes,
|
||||
int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
|
||||
int buffSizeInBytes, int[] sessionId, Identity identity, long nativeRecordInJavaObj);
|
||||
int buffSizeInBytes, int[] sessionId, Identity identity, long nativeRecordInJavaObj,
|
||||
int maxSharedAudioHistoryMs);
|
||||
|
||||
// TODO remove: implementation calls directly into implementation of native_release()
|
||||
private native void native_finalize();
|
||||
@@ -2170,6 +2297,8 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
|
||||
|
||||
private native void native_setLogSessionId(@Nullable String logSessionId);
|
||||
|
||||
private native int native_shareAudioHistory(@NonNull String sharedPackage, long startFromMs);
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Utility methods
|
||||
//------------------
|
||||
|
||||
@@ -1464,6 +1464,10 @@ public class AudioSystem
|
||||
// usage for AudioRecord.startRecordingSync(), must match AudioSystem::sync_event_t
|
||||
/** @hide */ public static final int SYNC_EVENT_NONE = 0;
|
||||
/** @hide */ public static final int SYNC_EVENT_PRESENTATION_COMPLETE = 1;
|
||||
/** @hide
|
||||
* Not used by native implementation.
|
||||
* See {@link AudioRecord.Builder#setSharedAudioEvent(MediaSyncEvent) */
|
||||
public static final int SYNC_EVENT_SHARE_AUDIO_HISTORY = 100;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
|
||||
@@ -16,6 +16,13 @@
|
||||
|
||||
package android.media;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* The MediaSyncEvent class defines events that can be used to synchronize playback or capture
|
||||
* actions between different players and recorders.
|
||||
@@ -24,7 +31,7 @@ package android.media;
|
||||
* The audio session ID is retrieved from a player (e.g {@link MediaPlayer}, {@link AudioTrack} or
|
||||
* {@link ToneGenerator}) by use of the getAudioSessionId() method.
|
||||
*/
|
||||
public class MediaSyncEvent {
|
||||
public class MediaSyncEvent implements Parcelable {
|
||||
|
||||
/**
|
||||
* No sync event specified. When used with a synchronized playback or capture method, the
|
||||
@@ -39,8 +46,16 @@ public class MediaSyncEvent {
|
||||
* {@link #setAudioSessionId(int)} method.
|
||||
*/
|
||||
public static final int SYNC_EVENT_PRESENTATION_COMPLETE =
|
||||
AudioSystem.SYNC_EVENT_PRESENTATION_COMPLETE;
|
||||
AudioSystem.SYNC_EVENT_PRESENTATION_COMPLETE;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Used when sharing audio history between AudioRecord instances.
|
||||
* See {@link AudioRecord.Builder#setSharedAudioEvent(MediaSyncEvent).
|
||||
*/
|
||||
@SystemApi
|
||||
public static final int SYNC_EVENT_SHARE_AUDIO_HISTORY =
|
||||
AudioSystem.SYNC_EVENT_SHARE_AUDIO_HISTORY;
|
||||
|
||||
/**
|
||||
* Creates a synchronization event of the sepcified type.
|
||||
@@ -112,11 +127,86 @@ public class MediaSyncEvent {
|
||||
|
||||
private static boolean isValidType(int type) {
|
||||
switch (type) {
|
||||
case SYNC_EVENT_NONE:
|
||||
case SYNC_EVENT_PRESENTATION_COMPLETE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
case SYNC_EVENT_NONE:
|
||||
case SYNC_EVENT_PRESENTATION_COMPLETE:
|
||||
case SYNC_EVENT_SHARE_AUDIO_HISTORY:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Parcelable implementation
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
Objects.requireNonNull(dest);
|
||||
dest.writeInt(mType);
|
||||
dest.writeInt(mAudioSession);
|
||||
}
|
||||
|
||||
private MediaSyncEvent(Parcel in) {
|
||||
mType = in.readInt();
|
||||
mAudioSession = in.readInt();
|
||||
}
|
||||
|
||||
public static final @NonNull Parcelable.Creator<MediaSyncEvent> CREATOR =
|
||||
new Parcelable.Creator<MediaSyncEvent>() {
|
||||
/**
|
||||
* Rebuilds an MediaSyncEvent previously stored with writeToParcel().
|
||||
* @param p Parcel object to read the MediaSyncEvent from
|
||||
* @return a new MediaSyncEvent created from the data in the parcel
|
||||
*/
|
||||
public MediaSyncEvent createFromParcel(Parcel p) {
|
||||
return new MediaSyncEvent(p);
|
||||
}
|
||||
public MediaSyncEvent[] newArray(int size) {
|
||||
return new MediaSyncEvent[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
MediaSyncEvent that = (MediaSyncEvent) o;
|
||||
return ((mType == that.mType)
|
||||
&& (mAudioSession == that.mAudioSession));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mType, mAudioSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new String("MediaSyncEvent:"
|
||||
+ " type=" + typeToString(mType)
|
||||
+ " session=" + mAudioSession);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string representation for the type.
|
||||
* @param type one of the {@link MediaSyncEvent} type constants
|
||||
* @hide
|
||||
*/
|
||||
public static @NonNull String typeToString(int type) {
|
||||
switch (type) {
|
||||
case SYNC_EVENT_NONE:
|
||||
return "SYNC_EVENT_NONE";
|
||||
case SYNC_EVENT_PRESENTATION_COMPLETE:
|
||||
return "SYNC_EVENT_PRESENTATION_COMPLETE";
|
||||
case SYNC_EVENT_SHARE_AUDIO_HISTORY:
|
||||
return "SYNC_EVENT_SHARE_AUDIO_HISTORY";
|
||||
default:
|
||||
return "unknown event type " + type;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user