Merge "audiopolicy: Refactor XML deserializer for the APM config"
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index ddf98f6..1ca0fdc 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -22,9 +22,6 @@
libsoundtriggerservice \
libutils
-LOCAL_STATIC_LIBRARIES := \
- libjsoncpp
-
# TODO oboeservice is the old folder name for aaudioservice. It will be changed.
LOCAL_C_INCLUDES := \
frameworks/av/services/audioflinger \
@@ -58,13 +55,9 @@
# both to build both 32 bit and 64 bit libraries,
# and use primary target architecture (32 or 64) for audioserver.
# first to build libraries and audioserver for the primary target architecture only.
-# <empty> to build both 32 and 64 bit libraries and 32 bit audioserver.
+# <empty> to build both 32 and 64 bit libraries and primary target audioserver.
-ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
-LOCAL_MULTILIB := 32
-else
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-endif
LOCAL_MODULE := audioserver
diff --git a/media/libaudioclient/AudioTrackShared.cpp b/media/libaudioclient/AudioTrackShared.cpp
index 6002ad9..c997cfa 100644
--- a/media/libaudioclient/AudioTrackShared.cpp
+++ b/media/libaudioclient/AudioTrackShared.cpp
@@ -26,6 +26,24 @@
namespace android {
+// TODO: consider pulling this into a shared header.
+// safe_sub_overflow is used ensure that subtraction occurs in the same native type
+// with proper 2's complement overflow. Without calling this function, it is possible,
+// for example, that optimizing compilers may elect to treat 32 bit subtraction
+// as 64 bit subtraction when storing into a 64 bit destination as integer overflow is
+// technically undefined.
+template<typename T,
+ typename U,
+ typename = std::enable_if_t<std::is_same<std::decay_t<T>,
+ std::decay_t<U>>{}>>
+ // ensure arguments are same type (ignoring volatile, which is used in cblk variables).
+auto safe_sub_overflow(const T& a, const U& b) {
+ std::decay_t<T> result;
+ (void)__builtin_sub_overflow(a, b, &result);
+ // note if __builtin_sub_overflow returns true, an overflow occurred.
+ return result;
+}
+
// used to clamp a value to size_t. TODO: move to another file.
template <typename T>
size_t clampToSize(T x) {
@@ -186,7 +204,7 @@
front = cblk->u.mStreaming.mFront;
}
// write to rear, read from front
- ssize_t filled = rear - front;
+ ssize_t filled = safe_sub_overflow(rear, front);
// pipe should not be overfull
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
if (mIsOut) {
@@ -684,7 +702,7 @@
const size_t overflowBit = mFrameCountP2 << 1;
const size_t mask = overflowBit - 1;
int32_t newFront = (front & ~mask) | (flush & mask);
- ssize_t filled = rear - newFront;
+ ssize_t filled = safe_sub_overflow(rear, newFront);
if (filled >= (ssize_t)overflowBit) {
// front and rear offsets span the overflow bit of the p2 mask
// so rebasing newFront on the front offset is off by the overflow bit.
@@ -726,7 +744,7 @@
const size_t overflowBit = mFrameCountP2 << 1;
const size_t mask = overflowBit - 1;
int32_t newRear = (rear & ~mask) | (stop & mask);
- ssize_t filled = newRear - front;
+ ssize_t filled = safe_sub_overflow(newRear, front);
// overflowBit is unsigned, so cast to signed for comparison.
if (filled >= (ssize_t)overflowBit) {
// front and rear offsets span the overflow bit of the p2 mask
@@ -778,7 +796,7 @@
front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront);
rear = cblk->u.mStreaming.mRear;
}
- ssize_t filled = rear - front;
+ ssize_t filled = safe_sub_overflow(rear, front);
// pipe should not already be overfull
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
ALOGE("Shared memory control block is corrupt (filled=%zd, mFrameCount=%zu); shutting down",
@@ -905,7 +923,7 @@
return mFrameCount;
}
const int32_t rear = getRear();
- ssize_t filled = rear - cblk->u.mStreaming.mFront;
+ ssize_t filled = safe_sub_overflow(rear, cblk->u.mStreaming.mFront);
// pipe should not already be overfull
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
ALOGE("Shared memory control block is corrupt (filled=%zd, mFrameCount=%zu); shutting down",
@@ -931,7 +949,7 @@
return mFrameCount;
}
const int32_t rear = getRear();
- const ssize_t filled = rear - cblk->u.mStreaming.mFront;
+ const ssize_t filled = safe_sub_overflow(rear, cblk->u.mStreaming.mFront);
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
return 0; // error condition, silently return 0.
}
@@ -1241,7 +1259,7 @@
}
const int32_t front = android_atomic_acquire_load(&mCblk->u.mStreaming.mFront);
const int32_t rear = mCblk->u.mStreaming.mRear;
- const ssize_t filled = rear - front;
+ const ssize_t filled = safe_sub_overflow(rear, front);
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
return 0; // error condition, silently return 0.
}
diff --git a/media/libmediaplayer2/Android.bp b/media/libmediaplayer2/Android.bp
index 0672ca9..e30da85 100644
--- a/media/libmediaplayer2/Android.bp
+++ b/media/libmediaplayer2/Android.bp
@@ -8,8 +8,6 @@
name: "libmediaplayer2",
srcs: [
- "JAudioTrack.cpp",
- "JavaVMHelper.cpp",
"MediaPlayer2AudioOutput.cpp",
"mediaplayer2.cpp",
],
@@ -84,3 +82,55 @@
},
},
}
+
+cc_library {
+ name: "libmedia2_jni_core",
+
+ srcs: [
+ "JavaVMHelper.cpp",
+ "JAudioTrack.cpp",
+ "JMedia2HTTPService.cpp",
+ "JMedia2HTTPConnection.cpp",
+ ],
+
+ shared_libs: [
+ "android.hidl.token@1.0-utils",
+ "liblog",
+ "libcutils",
+ "libutils",
+ "libbinder",
+ "libstagefright_foundation",
+ "libmediaextractor",
+ "libdl",
+ "libaudioutils",
+ "libaudioclient",
+ "libnativehelper",
+ ],
+
+ include_dirs: [
+ "frameworks/av/media/libmedia/include",
+ "frameworks/base/core/jni",
+ ],
+
+ export_include_dirs: [
+ "include",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wno-error=deprecated-declarations",
+ "-Wall",
+ ],
+
+ sanitize: {
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ cfi: true,
+ diag: {
+ cfi: true,
+ },
+ },
+
+}
diff --git a/media/libmediaplayer2/JMedia2HTTPConnection.cpp b/media/libmediaplayer2/JMedia2HTTPConnection.cpp
new file mode 100644
index 0000000..d264a7f
--- /dev/null
+++ b/media/libmediaplayer2/JMedia2HTTPConnection.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2017, 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_NDEBUG 0
+#define LOG_TAG "JMedia2HTTPConnection"
+#include <utils/Log.h>
+
+#include <mediaplayer2/JavaVMHelper.h>
+#include <mediaplayer2/JMedia2HTTPConnection.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <nativehelper/ScopedLocalRef.h>
+
+#include "log/log.h"
+#include "jni.h"
+#include <nativehelper/JNIHelp.h>
+
+namespace android {
+
+static const size_t kBufferSize = 32768;
+
+JMedia2HTTPConnection::JMedia2HTTPConnection(JNIEnv *env, jobject thiz) {
+ mMedia2HTTPConnectionObj = env->NewGlobalRef(thiz);
+ CHECK(mMedia2HTTPConnectionObj != NULL);
+
+ ScopedLocalRef<jclass> media2HTTPConnectionClass(
+ env, env->GetObjectClass(mMedia2HTTPConnectionObj));
+ CHECK(media2HTTPConnectionClass.get() != NULL);
+
+ mConnectMethod = env->GetMethodID(
+ media2HTTPConnectionClass.get(),
+ "connect",
+ "(Ljava/lang/String;Ljava/lang/String;)Z");
+ CHECK(mConnectMethod != NULL);
+
+ mDisconnectMethod = env->GetMethodID(
+ media2HTTPConnectionClass.get(),
+ "disconnect",
+ "()V");
+ CHECK(mDisconnectMethod != NULL);
+
+ mReadAtMethod = env->GetMethodID(
+ media2HTTPConnectionClass.get(),
+ "readAt",
+ "(J[BI)I");
+ CHECK(mReadAtMethod != NULL);
+
+ mGetSizeMethod = env->GetMethodID(
+ media2HTTPConnectionClass.get(),
+ "getSize",
+ "()J");
+ CHECK(mGetSizeMethod != NULL);
+
+ mGetMIMETypeMethod = env->GetMethodID(
+ media2HTTPConnectionClass.get(),
+ "getMIMEType",
+ "()Ljava/lang/String;");
+ CHECK(mGetMIMETypeMethod != NULL);
+
+ mGetUriMethod = env->GetMethodID(
+ media2HTTPConnectionClass.get(),
+ "getUri",
+ "()Ljava/lang/String;");
+ CHECK(mGetUriMethod != NULL);
+
+ ScopedLocalRef<jbyteArray> tmp(
+ env, env->NewByteArray(kBufferSize));
+ mByteArrayObj = (jbyteArray)env->NewGlobalRef(tmp.get());
+ CHECK(mByteArrayObj != NULL);
+}
+
+JMedia2HTTPConnection::~JMedia2HTTPConnection() {
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
+ env->DeleteGlobalRef(mMedia2HTTPConnectionObj);
+ env->DeleteGlobalRef(mByteArrayObj);
+}
+
+bool JMedia2HTTPConnection::connect(
+ const char *uri, const KeyedVector<String8, String8> *headers) {
+ String8 tmp("");
+ if (headers != NULL) {
+ for (size_t i = 0; i < headers->size(); ++i) {
+ tmp.append(headers->keyAt(i));
+ tmp.append(String8(": "));
+ tmp.append(headers->valueAt(i));
+ tmp.append(String8("\r\n"));
+ }
+ }
+
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
+ jstring juri = env->NewStringUTF(uri);
+ jstring jheaders = env->NewStringUTF(tmp.string());
+
+ jboolean ret =
+ env->CallBooleanMethod(mMedia2HTTPConnectionObj, mConnectMethod, juri, jheaders);
+
+ env->DeleteLocalRef(juri);
+ env->DeleteLocalRef(jheaders);
+
+ return (bool)ret;
+}
+
+void JMedia2HTTPConnection::disconnect() {
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
+ env->CallVoidMethod(mMedia2HTTPConnectionObj, mDisconnectMethod);
+}
+
+ssize_t JMedia2HTTPConnection::readAt(off64_t offset, void *data, size_t size) {
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
+
+ if (size > kBufferSize) {
+ size = kBufferSize;
+ }
+
+ jint n = env->CallIntMethod(
+ mMedia2HTTPConnectionObj, mReadAtMethod, (jlong)offset, mByteArrayObj, (jint)size);
+
+ if (n > 0) {
+ env->GetByteArrayRegion(
+ mByteArrayObj,
+ 0,
+ n,
+ (jbyte *)data);
+ }
+
+ return n;
+}
+
+off64_t JMedia2HTTPConnection::getSize() {
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
+ return (off64_t)(env->CallLongMethod(mMedia2HTTPConnectionObj, mGetSizeMethod));
+}
+
+status_t JMedia2HTTPConnection::getMIMEType(String8 *mimeType) {
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
+ jstring jmime = (jstring)env->CallObjectMethod(mMedia2HTTPConnectionObj, mGetMIMETypeMethod);
+ jboolean flag = env->ExceptionCheck();
+ if (flag) {
+ env->ExceptionClear();
+ return UNKNOWN_ERROR;
+ }
+
+ const char *str = env->GetStringUTFChars(jmime, 0);
+ if (str != NULL) {
+ *mimeType = String8(str);
+ } else {
+ *mimeType = "application/octet-stream";
+ }
+ env->ReleaseStringUTFChars(jmime, str);
+ return OK;
+}
+
+status_t JMedia2HTTPConnection::getUri(String8 *uri) {
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
+ jstring juri = (jstring)env->CallObjectMethod(mMedia2HTTPConnectionObj, mGetUriMethod);
+ jboolean flag = env->ExceptionCheck();
+ if (flag) {
+ env->ExceptionClear();
+ return UNKNOWN_ERROR;
+ }
+
+ const char *str = env->GetStringUTFChars(juri, 0);
+ *uri = String8(str);
+ env->ReleaseStringUTFChars(juri, str);
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libmediaplayer2/JMedia2HTTPService.cpp b/media/libmediaplayer2/JMedia2HTTPService.cpp
new file mode 100644
index 0000000..264c15d
--- /dev/null
+++ b/media/libmediaplayer2/JMedia2HTTPService.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2017, 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_NDEBUG 0
+#define LOG_TAG "JMedia2HTTPService"
+#include <utils/Log.h>
+
+#include <jni.h>
+
+#include <mediaplayer2/JavaVMHelper.h>
+#include <mediaplayer2/JMedia2HTTPService.h>
+#include <mediaplayer2/JMedia2HTTPConnection.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
+
+namespace android {
+
+JMedia2HTTPService::JMedia2HTTPService(JNIEnv *env, jobject thiz) {
+ mMedia2HTTPServiceObj = env->NewGlobalRef(thiz);
+ CHECK(mMedia2HTTPServiceObj != NULL);
+
+ ScopedLocalRef<jclass> media2HTTPServiceClass(env, env->GetObjectClass(mMedia2HTTPServiceObj));
+ CHECK(media2HTTPServiceClass.get() != NULL);
+
+ mMakeHTTPConnectionMethod = env->GetMethodID(
+ media2HTTPServiceClass.get(),
+ "makeHTTPConnection",
+ "()Landroid/media/Media2HTTPConnection;");
+ CHECK(mMakeHTTPConnectionMethod != NULL);
+}
+
+JMedia2HTTPService::~JMedia2HTTPService() {
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
+ env->DeleteGlobalRef(mMedia2HTTPServiceObj);
+}
+
+sp<MediaHTTPConnection> JMedia2HTTPService::makeHTTPConnection() {
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
+ jobject media2HTTPConnectionObj =
+ env->CallObjectMethod(mMedia2HTTPServiceObj, mMakeHTTPConnectionMethod);
+
+ return new JMedia2HTTPConnection(env, media2HTTPConnectionObj);
+}
+
+} // namespace android
diff --git a/media/libmediaplayer2/include/mediaplayer2/JMedia2HTTPConnection.h b/media/libmediaplayer2/include/mediaplayer2/JMedia2HTTPConnection.h
new file mode 100644
index 0000000..15f7f83
--- /dev/null
+++ b/media/libmediaplayer2/include/mediaplayer2/JMedia2HTTPConnection.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2017, 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 _J_MEDIA2_HTTP_CONNECTION_H_
+#define _J_MEDIA2_HTTP_CONNECTION_H_
+
+#include "jni.h"
+
+#include <media/MediaHTTPConnection.h>
+#include <media/stagefright/foundation/ABase.h>
+
+namespace android {
+
+struct JMedia2HTTPConnection : public MediaHTTPConnection {
+ JMedia2HTTPConnection(JNIEnv *env, jobject thiz);
+
+ virtual bool connect(
+ const char *uri, const KeyedVector<String8, String8> *headers) override;
+
+ virtual void disconnect() override;
+ virtual ssize_t readAt(off64_t offset, void *data, size_t size) override;
+ virtual off64_t getSize() override;
+ virtual status_t getMIMEType(String8 *mimeType) override;
+ virtual status_t getUri(String8 *uri) override;
+
+protected:
+ virtual ~JMedia2HTTPConnection();
+
+private:
+ jobject mMedia2HTTPConnectionObj;
+ jmethodID mConnectMethod;
+ jmethodID mDisconnectMethod;
+ jmethodID mReadAtMethod;
+ jmethodID mGetSizeMethod;
+ jmethodID mGetMIMETypeMethod;
+ jmethodID mGetUriMethod;
+
+ jbyteArray mByteArrayObj;
+
+ DISALLOW_EVIL_CONSTRUCTORS(JMedia2HTTPConnection);
+};
+
+} // namespace android
+
+#endif // _J_MEDIA2_HTTP_CONNECTION_H_
diff --git a/media/libmediaplayer2/include/mediaplayer2/JMedia2HTTPService.h b/media/libmediaplayer2/include/mediaplayer2/JMedia2HTTPService.h
new file mode 100644
index 0000000..bf61a7f
--- /dev/null
+++ b/media/libmediaplayer2/include/mediaplayer2/JMedia2HTTPService.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017, 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 _J_MEDIA2_HTTP_SERVICE_H_
+#define _J_MEDIA2_HTTP_SERVICE_H_
+
+#include <jni.h>
+#include <utils/RefBase.h>
+
+#include <media/MediaHTTPService.h>
+#include <media/MediaHTTPConnection.h>
+#include <media/stagefright/foundation/ABase.h>
+
+namespace android {
+
+struct JMedia2HTTPService : public MediaHTTPService {
+ JMedia2HTTPService(JNIEnv *env, jobject thiz);
+
+ virtual sp<MediaHTTPConnection> makeHTTPConnection() override;
+
+protected:
+ virtual ~JMedia2HTTPService();
+
+private:
+ jobject mMedia2HTTPServiceObj;
+
+ jmethodID mMakeHTTPConnectionMethod;
+
+ DISALLOW_EVIL_CONSTRUCTORS(JMedia2HTTPService);
+};
+
+} // namespace android
+
+#endif // _J_MEDIA2_HTTP_SERVICE_H_
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h
index 4b0a960..1fe2efa 100644
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h
@@ -34,8 +34,7 @@
MEDIA2_SET_VIDEO_SIZE = 5,
MEDIA2_STARTED = 6,
MEDIA2_PAUSED = 7,
- MEDIA2_STOPPED = 8,
- MEDIA2_SKIPPED = 9,
+ MEDIA2_SKIPPED = 8,
MEDIA2_NOTIFY_TIME = 98,
MEDIA2_TIMED_TEXT = 99,
MEDIA2_ERROR = 100,
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
index 2f90825..e51727b 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
@@ -487,7 +487,7 @@
status_t NuPlayer2::setPlaybackSettings(const AudioPlaybackRate &rate) {
// do some cursory validation of the settings here. audio modes are
// only validated when set on the audiosink.
- if ((rate.mSpeed != 0.f && rate.mSpeed < AUDIO_TIMESTRETCH_SPEED_MIN)
+ if (rate.mSpeed < AUDIO_TIMESTRETCH_SPEED_MIN
|| rate.mSpeed > AUDIO_TIMESTRETCH_SPEED_MAX
|| rate.mPitch < AUDIO_TIMESTRETCH_SPEED_MIN
|| rate.mPitch > AUDIO_TIMESTRETCH_SPEED_MAX) {
@@ -986,8 +986,7 @@
if (mRenderer != NULL) {
// AudioSink allows only 1.f and 0.f for offload mode.
// For other speed, switch to non-offload mode.
- if (mOffloadAudio && ((rate.mSpeed != 0.f && rate.mSpeed != 1.f)
- || rate.mPitch != 1.f)) {
+ if (mOffloadAudio && (rate.mSpeed != 1.f || rate.mPitch != 1.f)) {
int64_t currentPositionUs;
if (getCurrentPosition(¤tPositionUs) != OK) {
currentPositionUs = mPreviousSeekTimeUs;
@@ -1010,36 +1009,15 @@
err = mRenderer->setPlaybackSettings(rate);
}
if (err == OK) {
- if (rate.mSpeed == 0.f) {
- onPause();
- notifyListener(mSrcId, MEDIA2_PAUSED, 0, 0);
- mPausedByClient = true;
- // save all other settings (using non-paused speed)
- // so we can restore them on start
- AudioPlaybackRate newRate = rate;
- newRate.mSpeed = mPlaybackSettings.mSpeed;
- mPlaybackSettings = newRate;
- } else { /* rate.mSpeed != 0.f */
- mPlaybackSettings = rate;
- if (mStarted) {
- // do not resume yet if the source is still buffering
- if (!mPausedForBuffering) {
- onResume();
- }
- } else if (mPrepared) {
- onStart();
- }
+ mPlaybackSettings = rate;
- mPausedByClient = false;
+ if (mVideoDecoder != NULL) {
+ sp<AMessage> params = new AMessage();
+ params->setFloat("playback-speed", mPlaybackSettings.mSpeed);
+ mVideoDecoder->setParameters(params);
}
}
- if (mVideoDecoder != NULL) {
- sp<AMessage> params = new AMessage();
- params->setFloat("playback-speed", mPlaybackSettings.mSpeed);
- mVideoDecoder->setParameters(params);
- }
-
sp<AMessage> response = new AMessage;
response->setInt32("err", err);
response->postReply(replyID);
@@ -1059,9 +1037,6 @@
// get playback settings used by renderer, as it may be
// slightly off due to audiosink not taking small changes.
mPlaybackSettings = rate;
- if (mPaused) {
- rate.mSpeed = 0.f;
- }
}
sp<AMessage> response = new AMessage;
if (err == OK) {
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
index d3be53a..b02e3f6 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
@@ -352,14 +352,6 @@
// try to update position
int64_t unused;
getCurrentPosition(&unused);
- Mutex::Autolock autoLock(mLock);
- if (rate.mSpeed == 0.f && mState == STATE_RUNNING) {
- mState = STATE_PAUSED;
- } else if (rate.mSpeed != 0.f
- && (mState == STATE_PAUSED
- || mState == STATE_PREPARED)) {
- err = start_l();
- }
}
return err;
}
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
index a0bd900..021ddde 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
@@ -133,8 +133,7 @@
mUseAudioCallback(false),
mWakeLock(new JWakeLock()) {
CHECK(mediaClock != NULL);
- mPlaybackRate = mPlaybackSettings.mSpeed;
- mMediaClock->setPlaybackRate(mPlaybackRate);
+ mMediaClock->setPlaybackRate(mPlaybackSettings.mSpeed);
}
NuPlayer2::Renderer::~Renderer() {
@@ -190,26 +189,20 @@
}
status_t NuPlayer2::Renderer::onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */) {
- if (rate.mSpeed == 0.f) {
- onPause();
- // don't call audiosink's setPlaybackRate if pausing, as pitch does not
- // have to correspond to the any non-0 speed (e.g old speed). Keep
- // settings nonetheless, using the old speed, in case audiosink changes.
- AudioPlaybackRate newRate = rate;
- newRate.mSpeed = mPlaybackSettings.mSpeed;
- mPlaybackSettings = newRate;
- return OK;
+ if (rate.mSpeed <= 0.f) {
+ ALOGW("playback rate cannot be %f", rate.mSpeed);
+ return BAD_VALUE;
}
if (mAudioSink != NULL && mAudioSink->ready()) {
status_t err = mAudioSink->setPlaybackRate(rate);
if (err != OK) {
+ ALOGW("failed to get playback rate from audio sink, err(%d)", err);
return err;
}
}
mPlaybackSettings = rate;
- mPlaybackRate = rate.mSpeed;
- mMediaClock->setPlaybackRate(mPlaybackRate);
+ mMediaClock->setPlaybackRate(mPlaybackSettings.mSpeed);
return OK;
}
@@ -236,9 +229,6 @@
// get playback settings used by audiosink, as it may be
// slightly off due to audiosink not taking small changes.
mPlaybackSettings = *rate;
- if (mPaused) {
- rate->mSpeed = 0.f;
- }
}
return err;
}
@@ -560,8 +550,8 @@
int64_t delayUs =
mAudioSink->msecsPerFrame()
* numFramesPendingPlayout * 1000ll;
- if (mPlaybackRate > 1.0f) {
- delayUs /= mPlaybackRate;
+ if (mPlaybackSettings.mSpeed > 1.0f) {
+ delayUs /= mPlaybackSettings.mSpeed;
}
// Let's give it more data after about half that time
@@ -1773,7 +1763,7 @@
mAudioSink->setPlaybackRate(mPlaybackSettings);
}
- mMediaClock->setPlaybackRate(mPlaybackRate);
+ mMediaClock->setPlaybackRate(mPlaybackSettings.mSpeed);
if (!mAudioQueue.empty()) {
postDrainAudioQueue_l();
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
index 62cf0d8..305af68 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
@@ -167,7 +167,6 @@
int32_t mAudioEOSGeneration;
const sp<MediaClock> mMediaClock;
- float mPlaybackRate; // audio track rate
AudioPlaybackRate mPlaybackSettings;
AVSyncSettings mSyncSettings;
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index be01a7d..231d540 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -342,15 +342,15 @@
for (size_t i = 0; i < matchingCodecs.size(); ++i) {
const AString &componentName = matchingCodecs[i];
- VideoFrameDecoder decoder(componentName, trackMeta, source);
- if (decoder.init(timeUs, numFrames, option, colorFormat) == OK) {
+ sp<VideoFrameDecoder> decoder = new VideoFrameDecoder(componentName, trackMeta, source);
+ if (decoder->init(timeUs, numFrames, option, colorFormat) == OK) {
if (outFrame != NULL) {
- *outFrame = decoder.extractFrame();
+ *outFrame = decoder->extractFrame();
if (*outFrame != NULL) {
return OK;
}
} else if (outFrames != NULL) {
- status_t err = decoder.extractFrames(outFrames);
+ status_t err = decoder->extractFrames(outFrames);
if (err == OK) {
return OK;
}
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 8912f8a..d534f64 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -548,11 +548,21 @@
// Make sure that the next buffer output does not still
// depend on fragments from the last one decoded.
+ mInputBufferCount = 0;
mNumFramesOutput = 0;
+ if (mState != NULL) {
+ vorbis_dsp_clear(mState);
+ delete mState;
+ mState = NULL;
+ }
+ if (mVi != NULL) {
+ vorbis_info_clear(mVi);
+ delete mVi;
+ mVi = NULL;
+ }
mSawInputEos = false;
mSignalledOutputEos = false;
mNumFramesLeftOnPage = -1;
- vorbis_dsp_restart(mState);
}
}
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 4a36681..2f298cf 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -82,6 +82,7 @@
"libbinder",
"libgui",
"libui",
+ "libmedia2_jni_core",
],
export_include_dirs: ["include"],
diff --git a/media/ndk/NdkMediaDataSource.cpp b/media/ndk/NdkMediaDataSource.cpp
index 9d00e5e..ec2aed6 100644
--- a/media/ndk/NdkMediaDataSource.cpp
+++ b/media/ndk/NdkMediaDataSource.cpp
@@ -23,13 +23,18 @@
#include <jni.h>
#include <unistd.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <android_util_Binder.h>
#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/StrongPointer.h>
+#include <media/IMediaHTTPService.h>
#include <media/NdkMediaError.h>
#include <media/NdkMediaDataSource.h>
#include <media/stagefright/InterfaceUtils.h>
+#include <mediaplayer2/JavaVMHelper.h>
+#include <mediaplayer2/JMedia2HTTPService.h>
#include "../../libstagefright/include/HTTPBase.h"
#include "../../libstagefright/include/NuCachedSource2.h"
@@ -92,6 +97,84 @@
}
}
+static sp<MediaHTTPService> createMediaHttpServiceFromJavaObj(JNIEnv *env, jobject obj, int version) {
+ if (obj == NULL) {
+ return NULL;
+ }
+ switch (version) {
+ case 1:
+ return interface_cast<IMediaHTTPService>(ibinderForJavaObject(env, obj));
+ case 2:
+ return new JMedia2HTTPService(env, obj);
+ default:
+ return NULL;
+ }
+}
+
+static sp<MediaHTTPService> createMediaHttpServiceTemplate(
+ JNIEnv *env,
+ const char *uri,
+ const char *clazz,
+ const char *method,
+ const char *signature,
+ int version) {
+ jobject service = NULL;
+ if (env == NULL) {
+ ALOGE("http service must be created from Java thread");
+ return NULL;
+ }
+
+ jclass mediahttpclass = env->FindClass(clazz);
+ if (mediahttpclass == NULL) {
+ ALOGE("can't find Media(2)HttpService");
+ env->ExceptionClear();
+ return NULL;
+ }
+
+ jmethodID mediaHttpCreateMethod = env->GetStaticMethodID(mediahttpclass, method, signature);
+ if (mediaHttpCreateMethod == NULL) {
+ ALOGE("can't find method");
+ env->ExceptionClear();
+ return NULL;
+ }
+
+ jstring juri = env->NewStringUTF(uri);
+
+ service = env->CallStaticObjectMethod(mediahttpclass, mediaHttpCreateMethod, juri);
+ env->DeleteLocalRef(juri);
+
+ env->ExceptionClear();
+ sp<MediaHTTPService> httpService = createMediaHttpServiceFromJavaObj(env, service, version);
+ return httpService;
+
+}
+
+sp<MediaHTTPService> createMediaHttpService(const char *uri, int version) {
+
+ JNIEnv *env;
+ const char *clazz, *method, *signature;
+
+ switch (version) {
+ case 1:
+ env = AndroidRuntime::getJNIEnv();
+ clazz = "android/media/MediaHTTPService";
+ method = "createHttpServiceBinderIfNecessary";
+ signature = "(Ljava/lang/String;)Landroid/os/IBinder;";
+ break;
+ case 2:
+ env = JavaVMHelper::getJNIEnv();
+ clazz = "android/media/Media2HTTPService";
+ method = "createHTTPService";
+ signature = "(Ljava/lang/String;)Landroid/media/Media2HTTPService;";
+ break;
+ default:
+ return NULL;
+ }
+
+ return createMediaHttpServiceTemplate(env, uri, clazz, method, signature, version);
+
+}
+
extern "C" {
EXPORT
diff --git a/media/ndk/NdkMediaDataSourcePriv.h b/media/ndk/NdkMediaDataSourcePriv.h
index ea9c865..3b0aa59 100644
--- a/media/ndk/NdkMediaDataSourcePriv.h
+++ b/media/ndk/NdkMediaDataSourcePriv.h
@@ -32,6 +32,7 @@
#include <sys/types.h>
#include <media/DataSource.h>
+#include <media/MediaHTTPService.h>
#include <media/NdkMediaDataSource.h>
#include <utils/Mutex.h>
#include <utils/String8.h>
@@ -59,5 +60,7 @@
};
+sp<MediaHTTPService> createMediaHttpService(const char *uri, int version);
+
#endif // _NDK_MEDIA_DATASOURCE_PRIV_H
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index c66cd50..f00a19c 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -96,39 +96,12 @@
ALOGV("setDataSource(%s)", uri);
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- jobject service = NULL;
- if (env == NULL) {
- ALOGE("setDataSource(path) must be called from Java thread");
+ sp<MediaHTTPService> httpService = createMediaHttpService(uri, /* version = */ 1);
+ if (httpService == NULL) {
+ ALOGE("can't create http service");
return AMEDIA_ERROR_UNSUPPORTED;
}
- jclass mediahttpclass = env->FindClass("android/media/MediaHTTPService");
- if (mediahttpclass == NULL) {
- ALOGE("can't find MediaHttpService");
- env->ExceptionClear();
- return AMEDIA_ERROR_UNSUPPORTED;
- }
-
- jmethodID mediaHttpCreateMethod = env->GetStaticMethodID(mediahttpclass,
- "createHttpServiceBinderIfNecessary", "(Ljava/lang/String;)Landroid/os/IBinder;");
- if (mediaHttpCreateMethod == NULL) {
- ALOGE("can't find method");
- env->ExceptionClear();
- return AMEDIA_ERROR_UNSUPPORTED;
- }
-
- jstring jloc = env->NewStringUTF(uri);
-
- service = env->CallStaticObjectMethod(mediahttpclass, mediaHttpCreateMethod, jloc);
- env->DeleteLocalRef(jloc);
-
- sp<IMediaHTTPService> httpService;
- if (service != NULL) {
- sp<IBinder> binder = ibinderForJavaObject(env, service);
- httpService = interface_cast<IMediaHTTPService>(binder);
- }
-
KeyedVector<String8, String8> headers;
for (int i = 0; i < numheaders; ++i) {
String8 key8(keys[i]);
@@ -138,7 +111,6 @@
status_t err;
err = mData->mImpl->setDataSource(httpService, uri, numheaders > 0 ? &headers : NULL);
- env->ExceptionClear();
return translate_error(err);
}
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 2c26ba4..c0aa477 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -42,7 +42,6 @@
LOCAL_STATIC_LIBRARIES := \
libcpustats \
- libjsoncpp \
libsndfile \
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e62156e..06975ac 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -20,7 +20,6 @@
//#define LOG_NDEBUG 0
#include "Configuration.h"
-#include <algorithm> // std::any_of
#include <dirent.h>
#include <math.h>
#include <signal.h>
@@ -56,11 +55,8 @@
#include <system/audio_effects/effect_ns.h>
#include <system/audio_effects/effect_aec.h>
-#include <audio_utils/FdToString.h>
#include <audio_utils/primitives.h>
-#include <json/json.h>
-
#include <powermanager/PowerManager.h>
#include <media/IMediaLogService.h>
@@ -438,18 +434,6 @@
if (!dumpAllowed()) {
dumpPermissionDenial(fd, args);
} else {
- // XXX This is sort of hacky for now.
- const bool formatJson = std::any_of(args.begin(), args.end(),
- [](const String16 &arg) { return arg == String16("--json"); });
- if (formatJson) {
- Json::Value root = getJsonDump();
- Json::FastWriter writer;
- std::string rootStr = writer.write(root);
- // XXX consider buffering if the string happens to be too long.
- dprintf(fd, "%s", rootStr.c_str());
- return NO_ERROR;
- }
-
// get state of hardware lock
bool hardwareLocked = dumpTryLock(mHardwareLock);
if (!hardwareLocked) {
@@ -576,32 +560,6 @@
return NO_ERROR;
}
-Json::Value AudioFlinger::getJsonDump()
-{
- Json::Value root(Json::objectValue);
- const bool locked = dumpTryLock(mLock);
-
- // failed to lock - AudioFlinger is probably deadlocked
- if (!locked) {
- root["deadlock_message"] = kDeadlockedString;
- }
- // FIXME risky to access data structures without a lock held?
-
- Json::Value playbackThreads = Json::arrayValue;
- // dump playback threads
- for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- playbackThreads.append(mPlaybackThreads.valueAt(i)->getJsonDump());
- }
-
- if (locked) {
- mLock.unlock();
- }
-
- root["playback_threads"] = playbackThreads;
-
- return root;
-}
-
sp<AudioFlinger::Client> AudioFlinger::registerPid(pid_t pid)
{
Mutex::Autolock _cl(mClientLock);
@@ -788,7 +746,7 @@
output.afFrameCount = thread->frameCount();
output.afSampleRate = thread->sampleRate();
output.afLatencyMs = thread->latency();
- output.trackId = track->id();
+ output.trackId = track == nullptr ? -1 : track->id();
// move effect chain to this output thread if an effect on same session was waiting
// for a track to be created
@@ -2300,15 +2258,7 @@
if (playbackThread != NULL) {
ALOGV("closeOutput() %d", output);
- {
- // Dump thread before deleting for history
- audio_utils::FdToString fdToString;
- const int fd = fdToString.fd();
- if (fd >= 0) {
- playbackThread->dump(fd, {} /* args */);
- mThreadLog.logs(-1 /* time */, fdToString.getStringAndClose());
- }
- }
+ dumpToThreadLog_l(playbackThread);
if (playbackThread->type() == ThreadBase::MIXER) {
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
@@ -2341,6 +2291,7 @@
if (mmapThread == 0) {
return BAD_VALUE;
}
+ dumpToThreadLog_l(mmapThread);
mMmapThreads.removeItem(output);
ALOGD("closing mmapThread %p", mmapThread.get());
}
@@ -2549,15 +2500,7 @@
if (recordThread != 0) {
ALOGV("closeInput() %d", input);
- {
- // Dump thread before deleting for history
- audio_utils::FdToString fdToString;
- const int fd = fdToString.fd();
- if (fd >= 0) {
- recordThread->dump(fd, {} /* args */);
- mThreadLog.logs(-1 /* time */, fdToString.getStringAndClose());
- }
- }
+ dumpToThreadLog_l(recordThread);
// If we still have effect chains, it means that a client still holds a handle
// on at least one effect. We must either move the chain to an existing thread with the
@@ -2601,6 +2544,7 @@
if (mmapThread == 0) {
return BAD_VALUE;
}
+ dumpToThreadLog_l(mmapThread);
mMmapThreads.removeItem(input);
}
const sp<AudioIoDescriptor> ioDesc = new AudioIoDescriptor();
@@ -2799,6 +2743,17 @@
return;
}
+// dumpToThreadLog_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::dumpToThreadLog_l(const sp<ThreadBase> &thread)
+{
+ audio_utils::FdToString fdToString;
+ const int fd = fdToString.fd();
+ if (fd >= 0) {
+ thread->dump(fd, {} /* args */);
+ mThreadLog.logs(-1 /* time */, fdToString.getStringAndClose());
+ }
+}
+
// checkThread_l() must be called with AudioFlinger::mLock held
AudioFlinger::ThreadBase *AudioFlinger::checkThread_l(audio_io_handle_t ioHandle) const
{
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 53a7a8f..b6b3815 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -23,7 +23,6 @@
#include <mutex>
#include <deque>
#include <map>
-#include <memory>
#include <set>
#include <string>
#include <vector>
@@ -66,6 +65,7 @@
#include <media/VolumeShaper.h>
#include <audio_utils/clock.h>
+#include <audio_utils/FdToString.h>
#include <audio_utils/SimpleLog.h>
#include <audio_utils/TimestampVerifier.h>
@@ -80,7 +80,6 @@
#include <powermanager/IPowerManager.h>
-#include <json/json.h>
#include <media/nblog/NBLog.h>
#include <private/media/AudioEffectShared.h>
#include <private/media/AudioTrackShared.h>
@@ -116,7 +115,6 @@
static const char* getServiceName() ANDROID_API { return "media.audio_flinger"; }
virtual status_t dump(int fd, const Vector<String16>& args);
- Json::Value getJsonDump();
// IAudioFlinger interface, in binder opcode order
virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
@@ -426,7 +424,10 @@
void dumpClients(int fd, const Vector<String16>& args);
void dumpInternals(int fd, const Vector<String16>& args);
- SimpleLog mThreadLog{10}; // 10 Thread history limit
+ SimpleLog mThreadLog{16}; // 16 Thread history limit
+
+ class ThreadBase;
+ void dumpToThreadLog_l(const sp<ThreadBase> &thread);
// --- Client ---
class Client : public RefBase {
diff --git a/services/audioflinger/Configuration.h b/services/audioflinger/Configuration.h
index 34cd821..ede8e3f 100644
--- a/services/audioflinger/Configuration.h
+++ b/services/audioflinger/Configuration.h
@@ -27,7 +27,7 @@
//#define AUDIO_WATCHDOG
// uncomment to display CPU load adjusted for CPU frequency
-//define CPU_FREQUENCY_STATISTICS
+//#define CPU_FREQUENCY_STATISTICS
// uncomment to enable fast threads to take performance samples for later statistical analysis
#define FAST_THREAD_STATISTICS
diff --git a/services/audioflinger/FastMixerDumpState.cpp b/services/audioflinger/FastMixerDumpState.cpp
index 2abfbfb..a42e09c 100644
--- a/services/audioflinger/FastMixerDumpState.cpp
+++ b/services/audioflinger/FastMixerDumpState.cpp
@@ -24,8 +24,6 @@
#include <cpustats/ThreadCpuUsage.h>
#endif
#endif
-#include <json/json.h>
-#include <string>
#include <utils/Debug.h>
#include <utils/Log.h>
#include "FastMixerDumpState.h"
@@ -206,49 +204,4 @@
}
}
-Json::Value FastMixerDumpState::getJsonDump() const
-{
- Json::Value root(Json::objectValue);
- if (mCommand == FastMixerState::INITIAL) {
- root["status"] = "uninitialized";
- return root;
- }
-#ifdef FAST_THREAD_STATISTICS
- // find the interval of valid samples
- const uint32_t bounds = mBounds;
- const uint32_t newestOpen = bounds & 0xFFFF;
- uint32_t oldestClosed = bounds >> 16;
-
- //uint32_t n = (newestOpen - oldestClosed) & 0xFFFF;
- uint32_t n;
- __builtin_sub_overflow(newestOpen, oldestClosed, &n);
- n &= 0xFFFF;
-
- if (n > mSamplingN) {
- ALOGE("too many samples %u", n);
- n = mSamplingN;
- }
- // statistics for monotonic (wall clock) time, thread raw CPU load in time, CPU clock frequency,
- // and adjusted CPU load in MHz normalized for CPU clock frequency
- Json::Value jsonWall(Json::arrayValue);
- Json::Value jsonLoadNs(Json::arrayValue);
- // loop over all the samples
- for (uint32_t j = 0; j < n; ++j) {
- size_t i = oldestClosed++ & (mSamplingN - 1);
- uint32_t wallNs = mMonotonicNs[i];
- jsonWall.append(wallNs);
- uint32_t sampleLoadNs = mLoadNs[i];
- jsonLoadNs.append(sampleLoadNs);
- }
- if (n) {
- root["wall_clock_time_ns"] = jsonWall;
- root["raw_cpu_load_ns"] = jsonLoadNs;
- root["status"] = "ok";
- } else {
- root["status"] = "unavailable";
- }
-#endif
- return root;
-}
-
} // android
diff --git a/services/audioflinger/FastMixerDumpState.h b/services/audioflinger/FastMixerDumpState.h
index 69c2e4e..9b91cbc 100644
--- a/services/audioflinger/FastMixerDumpState.h
+++ b/services/audioflinger/FastMixerDumpState.h
@@ -18,9 +18,7 @@
#define ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
#include <stdint.h>
-#include <string>
#include <audio_utils/TimestampVerifier.h>
-#include <json/json.h>
#include "Configuration.h"
#include "FastThreadDumpState.h"
#include "FastMixerState.h"
@@ -67,8 +65,7 @@
FastMixerDumpState();
/*virtual*/ ~FastMixerDumpState();
- void dump(int fd) const; // should only be called on a stable copy, not the original
- Json::Value getJsonDump() const; // should only be called on a stable copy, not the original
+ void dump(int fd) const; // should only be called on a stable copy, not the original
double mLatencyMs = 0.; // measured latency, default of 0 if no valid timestamp read.
uint32_t mWriteSequence; // incremented before and after each write()
diff --git a/services/audioflinger/FastThread.cpp b/services/audioflinger/FastThread.cpp
index 09101d9..04b32c2 100644
--- a/services/audioflinger/FastThread.cpp
+++ b/services/audioflinger/FastThread.cpp
@@ -66,8 +66,6 @@
/* mMeasuredWarmupTs({0, 0}), */
mWarmupCycles(0),
mWarmupConsecutiveInRangeCycles(0),
- // mDummyNBLogWriter
- mNBLogWriter(&mDummyNBLogWriter),
mTimestampStatus(INVALID_OPERATION),
mCommand(FastThreadState::INITIAL),
@@ -94,7 +92,7 @@
{
// LOGT now works even if tlNBLogWriter is nullptr, but we're considering changing that,
// so this initialization permits a future change to remove the check for nullptr.
- tlNBLogWriter = &mDummyNBLogWriter;
+ tlNBLogWriter = mDummyNBLogWriter.get();
for (;;) {
// either nanosleep, sched_yield, or busy wait
@@ -124,9 +122,9 @@
// As soon as possible of learning of a new dump area, start using it
mDumpState = next->mDumpState != NULL ? next->mDumpState : mDummyDumpState;
- mNBLogWriter = next->mNBLogWriter != NULL ? next->mNBLogWriter : &mDummyNBLogWriter;
- setNBLogWriter(mNBLogWriter); // FastMixer informs its AudioMixer, FastCapture ignores
- tlNBLogWriter = mNBLogWriter;
+ tlNBLogWriter = next->mNBLogWriter != NULL ?
+ next->mNBLogWriter : mDummyNBLogWriter.get();
+ setNBLogWriter(tlNBLogWriter); // FastMixer informs its AudioMixer, FastCapture ignores
// We want to always have a valid reference to the previous (non-idle) state.
// However, the state queue only guarantees access to current and previous states.
diff --git a/services/audioflinger/FastThread.h b/services/audioflinger/FastThread.h
index 2a71414..3f6b206 100644
--- a/services/audioflinger/FastThread.h
+++ b/services/audioflinger/FastThread.h
@@ -78,12 +78,11 @@
unsigned mColdGen; // last observed mColdGen
bool mIsWarm; // true means ready to mix,
// false means wait for warmup before mixing
- struct timespec mMeasuredWarmupTs; // how long did it take for warmup to complete
- uint32_t mWarmupCycles; // counter of number of loop cycles during warmup phase
- uint32_t mWarmupConsecutiveInRangeCycles; // number of consecutive cycles in range
- NBLog::Writer mDummyNBLogWriter;
- NBLog::Writer* mNBLogWriter; // always non-nullptr: real NBLog::Writer* or &mDummyNBLogWriter
- status_t mTimestampStatus;
+ struct timespec mMeasuredWarmupTs; // how long did it take for warmup to complete
+ uint32_t mWarmupCycles; // counter of number of loop cycles during warmup phase
+ uint32_t mWarmupConsecutiveInRangeCycles; // number of consecutive cycles in range
+ const sp<NBLog::Writer> mDummyNBLogWriter{new NBLog::Writer()};
+ status_t mTimestampStatus;
FastThreadState::Command mCommand;
bool mAttemptedWrite;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index b5e7856..d7a4451 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -42,7 +42,6 @@
#include <audio_utils/primitives.h>
#include <audio_utils/format.h>
#include <audio_utils/minifloat.h>
-#include <json/json.h>
#include <system/audio_effects/effect_ns.h>
#include <system/audio_effects/effect_aec.h>
#include <system/audio.h>
@@ -1776,11 +1775,6 @@
mLocalLog.dump(fd, " " /* prefix */, 40 /* lines */);
}
-Json::Value AudioFlinger::PlaybackThread::getJsonDump() const
-{
- return Json::Value(Json::objectValue);
-}
-
void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args __unused)
{
String8 result;
@@ -5182,7 +5176,8 @@
// while we are dumping it. It may be inconsistent, but it won't mutate!
// This is a large object so we place it on the heap.
// FIXME 25972958: Need an intelligent copy constructor that does not touch unused pages.
- const std::unique_ptr<FastMixerDumpState> copy(new FastMixerDumpState(mFastMixerDumpState));
+ const std::unique_ptr<FastMixerDumpState> copy =
+ std::make_unique<FastMixerDumpState>(mFastMixerDumpState);
copy->dump(fd);
#ifdef STATE_QUEUE_DUMP
@@ -5206,22 +5201,6 @@
}
}
-Json::Value AudioFlinger::MixerThread::getJsonDump() const
-{
- Json::Value root;
- if (hasFastMixer()) {
- // Make a non-atomic copy of fast mixer dump state so it won't change underneath us
- // while we are dumping it. It may be inconsistent, but it won't mutate!
- // This is a large object so we place it on the heap.
- // FIXME 25972958: Need an intelligent copy constructor that does not touch unused pages.
- const std::unique_ptr<FastMixerDumpState> copy(new FastMixerDumpState(mFastMixerDumpState));
- root["fastmixer_stats"] = copy->getJsonDump();
- } else {
- root["fastmixer_stats"] = "no_fastmixer";
- }
- return root;
-}
-
uint32_t AudioFlinger::MixerThread::idleSleepTimeUs() const
{
return (uint32_t)(((mNormalFrameCount * 1000) / mSampleRate) * 1000) / 2;
@@ -7570,7 +7549,8 @@
// while we are dumping it. It may be inconsistent, but it won't mutate!
// This is a large object so we place it on the heap.
// FIXME 25972958: Need an intelligent copy constructor that does not touch unused pages.
- std::unique_ptr<FastCaptureDumpState> copy(new FastCaptureDumpState(mFastCaptureDumpState));
+ const std::unique_ptr<FastCaptureDumpState> copy =
+ std::make_unique<FastCaptureDumpState>(mFastCaptureDumpState);
copy->dump(fd);
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index b6e8abf..88c6ff3 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -397,6 +397,8 @@
bool isMsdDevice() const { return mIsMsdDevice; }
+ virtual void dump(int fd, const Vector<String16>& args) = 0;
+
mutable Mutex mLock;
protected:
@@ -665,9 +667,7 @@
audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady);
virtual ~PlaybackThread();
- void dump(int fd, const Vector<String16>& args);
- // returns a string of audio performance related data in JSON format.
- virtual Json::Value getJsonDump() const;
+ void dump(int fd, const Vector<String16>& args) override;
// Thread virtuals
virtual bool threadLoop();
@@ -1114,7 +1114,6 @@
virtual bool checkForNewParameter_l(const String8& keyValuePair,
status_t& status);
virtual void dumpInternals(int fd, const Vector<String16>& args);
- Json::Value getJsonDump() const override;
virtual bool isTrackAllowed_l(
audio_channel_mask_t channelMask, audio_format_t format,
@@ -1480,7 +1479,7 @@
// return true if the caller should then do it's part of the stopping process
bool stop(RecordTrack* recordTrack);
- void dump(int fd, const Vector<String16>& args);
+ void dump(int fd, const Vector<String16>& args) override;
AudioStreamIn* clearInput();
virtual sp<StreamHalInterface> stream() const;
@@ -1689,7 +1688,7 @@
// Sets the UID records silence
virtual void setRecordSilenced(uid_t uid __unused, bool silenced __unused) {}
- void dump(int fd, const Vector<String16>& args);
+ void dump(int fd, const Vector<String16>& args) override;
virtual void dumpInternals(int fd, const Vector<String16>& args);
void dumpTracks(int fd, const Vector<String16>& args);