Create constructor of JAudioTrack class
Bug: 70363744
Test: Built successfully (mmm libmedia -j48)
Change-Id: I51e0510039fca2e84d1ced103fea62156cd1e5c2
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 0b4fd25..59703b7 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -306,6 +306,7 @@
srcs: [
"AudioParameter.cpp",
+ "JAudioTrack.cpp",
"MediaPlayer2Factory.cpp",
"MediaPlayer2Manager.cpp",
"TestPlayerStub.cpp",
@@ -314,6 +315,7 @@
],
shared_libs: [
+ "libandroid_runtime",
"libaudioclient",
"libbinder",
"libcutils",
diff --git a/media/libmedia/JAudioTrack.cpp b/media/libmedia/JAudioTrack.cpp
new file mode 100644
index 0000000..4ba9425
--- /dev/null
+++ b/media/libmedia/JAudioTrack.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "JAudioTrack"
+
+#include "media/JAudioAttributes.h"
+#include "media/JAudioFormat.h"
+#include "media/JAudioTrack.h"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <media/AudioResamplerPublic.h>
+
+namespace android {
+
+// TODO: Add NULL && Exception checks after every JNI call.
+JAudioTrack::JAudioTrack( // < Usages of the arguments are below >
+ audio_stream_type_t streamType, // AudioAudioAttributes
+ uint32_t sampleRate, // AudioFormat && bufferSizeInBytes
+ audio_format_t format, // AudioFormat && bufferSizeInBytes
+ audio_channel_mask_t channelMask, // AudioFormat && bufferSizeInBytes
+ size_t frameCount, // bufferSizeInBytes
+ audio_session_t sessionId, // AudioTrack
+ const audio_attributes_t* pAttributes, // AudioAttributes
+ float maxRequiredSpeed) { // bufferSizeInBytes
+
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ jclass jAudioTrackCls = env->FindClass("android/media/AudioTrack");
+
+ maxRequiredSpeed = std::min(std::max(maxRequiredSpeed, 1.0f), AUDIO_TIMESTRETCH_SPEED_MAX);
+
+ int bufferSizeInBytes = 0;
+ if (sampleRate == 0 || frameCount > 0) {
+ // Manually calculate buffer size.
+ bufferSizeInBytes = audio_channel_count_from_out_mask(channelMask)
+ * audio_bytes_per_sample(format) * (frameCount > 0 ? frameCount : 1);
+ } else if (sampleRate > 0) {
+ // Call Java AudioTrack::getMinBufferSize().
+ jmethodID jGetMinBufferSize =
+ env->GetStaticMethodID(jAudioTrackCls, "getMinBufferSize", "(III)I");
+ bufferSizeInBytes = env->CallStaticIntMethod(jAudioTrackCls, jGetMinBufferSize,
+ sampleRate, outChannelMaskFromNative(channelMask), audioFormatFromNative(format));
+ }
+ bufferSizeInBytes = (int) (bufferSizeInBytes * maxRequiredSpeed);
+
+ // Create a Java AudioTrack object through its Builder.
+ jclass jBuilderCls = env->FindClass("android/media/AudioTrack$Builder");
+ jmethodID jBuilderCtor = env->GetMethodID(jBuilderCls, "<init>", "()V");
+ jobject jBuilderObj = env->NewObject(jBuilderCls, jBuilderCtor);
+
+ jmethodID jSetAudioAttributes = env->GetMethodID(jBuilderCls, "setAudioAttributes",
+ "(Landroid/media/AudioAttributes;)Landroid/media/AudioTrack$Builder;");
+ jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetAudioAttributes,
+ JAudioAttributes::createAudioAttributesObj(env, pAttributes, streamType));
+
+ jmethodID jSetAudioFormat = env->GetMethodID(jBuilderCls, "setAudioFormat",
+ "(Landroid/media/AudioFormat;)Landroid/media/AudioTrack$Builder;");
+ jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetAudioFormat,
+ JAudioFormat::createAudioFormatObj(env, sampleRate, format, channelMask));
+
+ jmethodID jSetBufferSizeInBytes = env->GetMethodID(jBuilderCls, "setBufferSizeInBytes",
+ "(I)Landroid/media/AudioTrack$Builder;");
+ jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetBufferSizeInBytes, bufferSizeInBytes);
+
+ // We only use streaming mode of Java AudioTrack.
+ jfieldID jModeStream = env->GetStaticFieldID(jAudioTrackCls, "MODE_STREAM", "I");
+ jint transferMode = env->GetStaticIntField(jAudioTrackCls, jModeStream);
+ jmethodID jSetTransferMode = env->GetMethodID(jBuilderCls, "setTransferMode",
+ "(I)Landroid/media/AudioTrack$Builder;");
+ jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetTransferMode,
+ transferMode /* Java AudioTrack::MODE_STREAM */);
+
+ if (sessionId != 0) {
+ jmethodID jSetSessionId = env->GetMethodID(jBuilderCls, "setSessionId",
+ "(I)Landroid/media/AudioTrack$Builder;");
+ jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetSessionId, sessionId);
+ }
+
+ jmethodID jBuild = env->GetMethodID(jBuilderCls, "build", "()Landroid/media/AudioTrack;");
+ mAudioTrackObj = env->CallObjectMethod(jBuilderObj, jBuild);
+}
+
+void JAudioTrack::stop() {
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ jclass jAudioTrackCls = env->FindClass("android/media/AudioTrack");
+ jmethodID jStop = env->GetMethodID(jAudioTrackCls, "stop", "()V");
+ env->CallVoidMethod(mAudioTrackObj, jStop);
+}
+
+} // namespace android
diff --git a/media/libmedia/include/media/JAudioAttributes.h b/media/libmedia/include/media/JAudioAttributes.h
new file mode 100644
index 0000000..fb11435
--- /dev/null
+++ b/media/libmedia/include/media/JAudioAttributes.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_JAUDIOATTRIBUTES_H
+#define ANDROID_JAUDIOATTRIBUTES_H
+
+#include <jni.h>
+#include <system/audio.h>
+
+namespace android {
+
+class JAudioAttributes {
+public:
+ /* Creates a Java AudioAttributes object. */
+ static jobject createAudioAttributesObj(JNIEnv *env,
+ const audio_attributes_t* pAttributes,
+ audio_stream_type_t streamType) {
+
+ jclass jBuilderCls = env->FindClass("android/media/AudioAttributes$Builder");
+ jmethodID jBuilderCtor = env->GetMethodID(jBuilderCls, "<init>", "()V");
+ jobject jBuilderObj = env->NewObject(jBuilderCls, jBuilderCtor);
+
+ if (pAttributes != NULL) {
+ // If pAttributes is not null, streamType is ignored.
+ jmethodID jSetUsage = env->GetMethodID(
+ jBuilderCls, "setUsage", "(I)Landroid/media/AudioAttributes$Builder;");
+ jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetUsage, pAttributes->usage);
+
+ jmethodID jSetContentType = env->GetMethodID(jBuilderCls, "setContentType",
+ "(I)Landroid/media/AudioAttributes$Builder;");
+ jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetContentType,
+ pAttributes->content_type);
+
+ // TODO: Java AudioAttributes.Builder.setCapturePreset() is systemApi and hidden.
+ // Can we use this method?
+// jmethodID jSetCapturePreset = env->GetMethodID(jBuilderCls, "setCapturePreset",
+// "(I)Landroid/media/AudioAttributes$Builder;");
+// jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetCapturePreset,
+// pAttributes->source);
+
+ jmethodID jSetFlags = env->GetMethodID(jBuilderCls, "setFlags",
+ "(I)Landroid/media/AudioAttributes$Builder;");
+ jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetFlags, pAttributes->flags);
+
+ // TODO: Handle the 'tags' (char[] to HashSet<String>).
+ // How to parse the char[]? Is there any example of it?
+ // Also, the addTags() method is hidden.
+ } else {
+ // Call AudioAttributes.Builder.setLegacyStreamType().build()
+ jmethodID jSetLegacyStreamType = env->GetMethodID(jBuilderCls, "setLegacyStreamType",
+ "(I)Landroid/media/AudioAttributes$Builder;");
+ jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetLegacyStreamType, streamType);
+ }
+
+ jmethodID jBuild = env->GetMethodID(jBuilderCls, "build",
+ "()Landroid/media/AudioAttributes;");
+ return env->CallObjectMethod(jBuilderObj, jBuild);
+ }
+
+};
+
+} // namespace android
+
+#endif // ANDROID_JAUDIOATTRIBUTES_H
diff --git a/media/libmedia/include/media/JAudioFormat.h b/media/libmedia/include/media/JAudioFormat.h
new file mode 100644
index 0000000..00abdff
--- /dev/null
+++ b/media/libmedia/include/media/JAudioFormat.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_JAUDIOFORMAT_H
+#define ANDROID_JAUDIOFORMAT_H
+
+#include <android_media_AudioFormat.h>
+#include <jni.h>
+
+namespace android {
+
+class JAudioFormat {
+public:
+ /* Creates a Java AudioFormat object. */
+ static jobject createAudioFormatObj(JNIEnv *env,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask) {
+
+ jclass jBuilderCls = env->FindClass("android/media/AudioFormat$Builder");
+ jmethodID jBuilderCtor = env->GetMethodID(jBuilderCls, "<init>", "()V");
+ jobject jBuilderObj = env->NewObject(jBuilderCls, jBuilderCtor);
+
+ if (sampleRate == 0) {
+ jclass jAudioFormatCls = env->FindClass("android/media/AudioFormat");
+ jfieldID jSampleRateUnspecified =
+ env->GetStaticFieldID(jAudioFormatCls, "SAMPLE_RATE_UNSPECIFIED", "I");
+ sampleRate = env->GetStaticIntField(jAudioFormatCls, jSampleRateUnspecified);
+ }
+
+ jmethodID jSetEncoding = env->GetMethodID(jBuilderCls, "setEncoding",
+ "(I)Landroid/media/AudioFormat$Builder;");
+ jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetEncoding,
+ audioFormatFromNative(format));
+
+ jmethodID jSetSampleRate = env->GetMethodID(jBuilderCls, "setSampleRate",
+ "(I)Landroid/media/AudioFormat$Builder;");
+ jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetSampleRate, sampleRate);
+
+ jmethodID jSetChannelMask = env->GetMethodID(jBuilderCls, "setChannelMask",
+ "(I)Landroid/media/AudioFormat$Builder;");
+ jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetChannelMask,
+ outChannelMaskFromNative(channelMask));
+
+ jmethodID jBuild = env->GetMethodID(jBuilderCls, "build", "()Landroid/media/AudioFormat;");
+ return env->CallObjectMethod(jBuilderObj, jBuild);
+ }
+
+};
+
+} // namespace android
+
+#endif // ANDROID_JAUDIOFORMAT_H
diff --git a/media/libmedia/include/media/JAudioTrack.h b/media/libmedia/include/media/JAudioTrack.h
new file mode 100644
index 0000000..fb29c24
--- /dev/null
+++ b/media/libmedia/include/media/JAudioTrack.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_JAUDIOTRACK_H
+#define ANDROID_JAUDIOTRACK_H
+
+#include <jni.h>
+#include <system/audio.h>
+
+namespace android {
+
+class JAudioTrack {
+public:
+
+ /* Creates an JAudioTrack object for non-offload mode.
+ * Once created, the track needs to be started before it can be used.
+ * Unspecified values are set to appropriate default values.
+ *
+ * Parameters:
+ *
+ * streamType: Select the type of audio stream this track is attached to
+ * (e.g. AUDIO_STREAM_MUSIC).
+ * sampleRate: Data source sampling rate in Hz. Zero means to use the sink sample rate.
+ * A non-zero value must be specified if AUDIO_OUTPUT_FLAG_DIRECT is set.
+ * 0 will not work with current policy implementation for direct output
+ * selection where an exact match is needed for sampling rate.
+ * (TODO: Check direct output after flags can be used in Java AudioTrack.)
+ * format: Audio format. For mixed tracks, any PCM format supported by server is OK.
+ * For direct and offloaded tracks, the possible format(s) depends on the
+ * output sink.
+ * (TODO: How can we check whether a format is supported?)
+ * channelMask: Channel mask, such that audio_is_output_channel(channelMask) is true.
+ * frameCount: Minimum size of track PCM buffer in frames. This defines the
+ * application's contribution to the latency of the track.
+ * The actual size selected by the JAudioTrack could be larger if the
+ * requested size is not compatible with current audio HAL configuration.
+ * Zero means to use a default value.
+ * sessionId: Specific session ID, or zero to use default.
+ * pAttributes: If not NULL, supersedes streamType for use case selection.
+ * maxRequiredSpeed: For PCM tracks, this creates an appropriate buffer size that will allow
+ * maxRequiredSpeed playback. Values less than 1.0f and greater than
+ * AUDIO_TIMESTRETCH_SPEED_MAX will be clamped. For non-PCM tracks
+ * and direct or offloaded tracks, this parameter is ignored.
+ * (TODO: Handle this after offload / direct track is supported.)
+ *
+ * TODO: Revive removed arguments after offload mode is supported.
+ */
+ JAudioTrack(audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ size_t frameCount = 0,
+ audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
+ const audio_attributes_t* pAttributes = NULL,
+ float maxRequiredSpeed = 1.0f);
+
+ /*
+ Temporarily removed constructor arguments:
+
+ // Q. Values are in audio-base.h, but where can we find explanation for them?
+ audio_output_flags_t flags,
+
+ // Q. May be used in AudioTrack.setPreferredDevice(AudioDeviceInfo)?
+ audio_port_handle_t selectedDeviceId,
+
+ // Should be deleted, since we don't use Binder anymore.
+ bool doNotReconnect,
+
+ // Do we need UID and PID?
+ uid_t uid,
+ pid_t pid,
+
+ // TODO: Uses these values when Java AudioTrack supports the offload mode.
+ callback_t cbf,
+ void* user,
+ int32_t notificationFrames,
+ const audio_offload_info_t *offloadInfo,
+
+ // Fixed to false, but what is this?
+ threadCanCallJava
+ */
+
+ void stop();
+
+protected:
+ jobject mAudioTrackObj; // Java AudioTrack object
+
+};
+
+}; // namespace android
+
+#endif // ANDROID_JAUDIOTRACK_H