diff options
Diffstat (limited to 'media/jni')
-rw-r--r-- | media/jni/Android.bp | 7 | ||||
-rw-r--r-- | media/jni/OWNERS | 3 | ||||
-rw-r--r-- | media/jni/audioeffect/Android.bp | 5 | ||||
-rw-r--r-- | media/jni/audioeffect/Visualizer.cpp | 446 | ||||
-rw-r--r-- | media/jni/audioeffect/Visualizer.h | 180 | ||||
-rw-r--r-- | media/jni/audioeffect/android_media_Visualizer.cpp | 2 | ||||
-rw-r--r-- | media/jni/audioeffect/exports.lds | 6 | ||||
-rw-r--r-- | media/jni/soundpool/Android.bp | 4 |
8 files changed, 648 insertions, 5 deletions
diff --git a/media/jni/Android.bp b/media/jni/Android.bp index e6c1c67b98e5..f873eeb9aa00 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -100,13 +100,14 @@ cc_library_shared { "android_media_Utils.cpp", ], + header_libs: [ + "libgui_headers", + ], + shared_libs: [ "liblog", - "libgui", - "libnativewindow", "libui", "libutils", - "android.hidl.token@1.0-utils", ], include_dirs: [ diff --git a/media/jni/OWNERS b/media/jni/OWNERS index bb91d4b26ecc..f1b0237d9008 100644 --- a/media/jni/OWNERS +++ b/media/jni/OWNERS @@ -1,2 +1,5 @@ # extra for MTP related files per-file android_mtp_*.cpp=marcone@google.com,jsharkey@android.com,jameswei@google.com,rmojumder@google.com + +# extra for TV related files +per-file android_media_tv_*=nchalko@google.com,quxiangfang@google.com diff --git a/media/jni/audioeffect/Android.bp b/media/jni/audioeffect/Android.bp index 09c546ab0065..41ab6703a579 100644 --- a/media/jni/audioeffect/Android.bp +++ b/media/jni/audioeffect/Android.bp @@ -6,6 +6,7 @@ cc_library_shared { "android_media_SourceDefaultEffect.cpp", "android_media_StreamDefaultEffect.cpp", "android_media_Visualizer.cpp", + "Visualizer.cpp", ], shared_libs: [ @@ -14,10 +15,12 @@ cc_library_shared { "libutils", "libandroid_runtime", "libnativehelper", - "libmedia", "libaudioclient", + "libaudioutils", ], + version_script: "exports.lds", + cflags: [ "-Wall", "-Werror", diff --git a/media/jni/audioeffect/Visualizer.cpp b/media/jni/audioeffect/Visualizer.cpp new file mode 100644 index 000000000000..83f3b6ed6217 --- /dev/null +++ b/media/jni/audioeffect/Visualizer.cpp @@ -0,0 +1,446 @@ +/* +** +** Copyright 2010, 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 "Visualizer" +#include <utils/Log.h> + +#include <stdint.h> +#include <sys/types.h> +#include <limits.h> + +#include <audio_utils/fixedfft.h> +#include <utils/Thread.h> + +#include "Visualizer.h" + +namespace android { + +// --------------------------------------------------------------------------- + +Visualizer::Visualizer (const String16& opPackageName, + int32_t priority, + effect_callback_t cbf, + void* user, + audio_session_t sessionId) + : AudioEffect(SL_IID_VISUALIZATION, opPackageName, NULL, priority, cbf, user, sessionId), + mCaptureRate(CAPTURE_RATE_DEF), + mCaptureSize(CAPTURE_SIZE_DEF), + mSampleRate(44100000), + mScalingMode(VISUALIZER_SCALING_MODE_NORMALIZED), + mMeasurementMode(MEASUREMENT_MODE_NONE), + mCaptureCallBack(NULL), + mCaptureCbkUser(NULL) +{ + initCaptureSize(); +} + +Visualizer::~Visualizer() +{ + ALOGV("Visualizer::~Visualizer()"); + setEnabled(false); + setCaptureCallBack(NULL, NULL, 0, 0); +} + +void Visualizer::release() +{ + ALOGV("Visualizer::release()"); + setEnabled(false); + Mutex::Autolock _l(mCaptureLock); + + mCaptureThread.clear(); + mCaptureCallBack = NULL; + mCaptureCbkUser = NULL; + mCaptureFlags = 0; + mCaptureRate = 0; +} + +status_t Visualizer::setEnabled(bool enabled) +{ + Mutex::Autolock _l(mCaptureLock); + + sp<CaptureThread> t = mCaptureThread; + if (t != 0) { + if (enabled) { + if (t->exitPending()) { + mCaptureLock.unlock(); + if (t->requestExitAndWait() == WOULD_BLOCK) { + mCaptureLock.lock(); + ALOGE("Visualizer::enable() called from thread"); + return INVALID_OPERATION; + } + mCaptureLock.lock(); + } + } + t->mLock.lock(); + } + + status_t status = AudioEffect::setEnabled(enabled); + + if (t != 0) { + if (enabled && status == NO_ERROR) { + t->run("Visualizer"); + } else { + t->requestExit(); + } + } + + if (t != 0) { + t->mLock.unlock(); + } + + return status; +} + +status_t Visualizer::setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, + uint32_t rate) +{ + if (rate > CAPTURE_RATE_MAX) { + return BAD_VALUE; + } + Mutex::Autolock _l(mCaptureLock); + + if (mEnabled) { + return INVALID_OPERATION; + } + + if (mCaptureThread != 0) { + mCaptureLock.unlock(); + mCaptureThread->requestExitAndWait(); + mCaptureLock.lock(); + } + + mCaptureThread.clear(); + mCaptureCallBack = cbk; + mCaptureCbkUser = user; + mCaptureFlags = flags; + mCaptureRate = rate; + + if (cbk != NULL) { + mCaptureThread = new CaptureThread(this, rate, ((flags & CAPTURE_CALL_JAVA) != 0)); + } + ALOGV("setCaptureCallBack() rate: %d thread %p flags 0x%08x", + rate, mCaptureThread.get(), mCaptureFlags); + return NO_ERROR; +} + +status_t Visualizer::setCaptureSize(uint32_t size) +{ + if (size > VISUALIZER_CAPTURE_SIZE_MAX || + size < VISUALIZER_CAPTURE_SIZE_MIN || + popcount(size) != 1) { + return BAD_VALUE; + } + + Mutex::Autolock _l(mCaptureLock); + if (mEnabled) { + return INVALID_OPERATION; + } + + uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2]; + effect_param_t *p = (effect_param_t *)buf32; + + p->psize = sizeof(uint32_t); + p->vsize = sizeof(uint32_t); + *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE; + *((int32_t *)p->data + 1)= size; + status_t status = setParameter(p); + + ALOGV("setCaptureSize size %d status %d p->status %d", size, status, p->status); + + if (status == NO_ERROR) { + status = p->status; + if (status == NO_ERROR) { + mCaptureSize = size; + } + } + + return status; +} + +status_t Visualizer::setScalingMode(uint32_t mode) { + if ((mode != VISUALIZER_SCALING_MODE_NORMALIZED) + && (mode != VISUALIZER_SCALING_MODE_AS_PLAYED)) { + return BAD_VALUE; + } + + Mutex::Autolock _l(mCaptureLock); + + uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2]; + effect_param_t *p = (effect_param_t *)buf32; + + p->psize = sizeof(uint32_t); + p->vsize = sizeof(uint32_t); + *(int32_t *)p->data = VISUALIZER_PARAM_SCALING_MODE; + *((int32_t *)p->data + 1)= mode; + status_t status = setParameter(p); + + ALOGV("setScalingMode mode %d status %d p->status %d", mode, status, p->status); + + if (status == NO_ERROR) { + status = p->status; + if (status == NO_ERROR) { + mScalingMode = mode; + } + } + + return status; +} + +status_t Visualizer::setMeasurementMode(uint32_t mode) { + if ((mode != MEASUREMENT_MODE_NONE) + //Note: needs to be handled as a mask when more measurement modes are added + && ((mode & MEASUREMENT_MODE_PEAK_RMS) != mode)) { + return BAD_VALUE; + } + + Mutex::Autolock _l(mCaptureLock); + + uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2]; + effect_param_t *p = (effect_param_t *)buf32; + + p->psize = sizeof(uint32_t); + p->vsize = sizeof(uint32_t); + *(int32_t *)p->data = VISUALIZER_PARAM_MEASUREMENT_MODE; + *((int32_t *)p->data + 1)= mode; + status_t status = setParameter(p); + + ALOGV("setMeasurementMode mode %d status %d p->status %d", mode, status, p->status); + + if (status == NO_ERROR) { + status = p->status; + if (status == NO_ERROR) { + mMeasurementMode = mode; + } + } + return status; +} + +status_t Visualizer::getIntMeasurements(uint32_t type, uint32_t number, int32_t *measurements) { + if (mMeasurementMode == MEASUREMENT_MODE_NONE) { + ALOGE("Cannot retrieve int measurements, no measurement mode set"); + return INVALID_OPERATION; + } + if (!(mMeasurementMode & type)) { + // measurement type has not been set on this Visualizer + ALOGE("Cannot retrieve int measurements, requested measurement mode 0x%x not set(0x%x)", + type, mMeasurementMode); + return INVALID_OPERATION; + } + // only peak+RMS measurement supported + if ((type != MEASUREMENT_MODE_PEAK_RMS) + // for peak+RMS measurement, the results are 2 int32_t values + || (number != 2)) { + ALOGE("Cannot retrieve int measurements, MEASUREMENT_MODE_PEAK_RMS returns 2 ints, not %d", + number); + return BAD_VALUE; + } + + status_t status = NO_ERROR; + if (mEnabled) { + uint32_t replySize = number * sizeof(int32_t); + status = command(VISUALIZER_CMD_MEASURE, + sizeof(uint32_t) /*cmdSize*/, + &type /*cmdData*/, + &replySize, measurements); + ALOGV("getMeasurements() command returned %d", status); + if ((status == NO_ERROR) && (replySize == 0)) { + status = NOT_ENOUGH_DATA; + } + } else { + ALOGV("getMeasurements() disabled"); + return INVALID_OPERATION; + } + return status; +} + +status_t Visualizer::getWaveForm(uint8_t *waveform) +{ + if (waveform == NULL) { + return BAD_VALUE; + } + if (mCaptureSize == 0) { + return NO_INIT; + } + + status_t status = NO_ERROR; + if (mEnabled) { + uint32_t replySize = mCaptureSize; + status = command(VISUALIZER_CMD_CAPTURE, 0, NULL, &replySize, waveform); + ALOGV("getWaveForm() command returned %d", status); + if ((status == NO_ERROR) && (replySize == 0)) { + status = NOT_ENOUGH_DATA; + } + } else { + ALOGV("getWaveForm() disabled"); + memset(waveform, 0x80, mCaptureSize); + } + return status; +} + +status_t Visualizer::getFft(uint8_t *fft) +{ + if (fft == NULL) { + return BAD_VALUE; + } + if (mCaptureSize == 0) { + return NO_INIT; + } + + status_t status = NO_ERROR; + if (mEnabled) { + uint8_t buf[mCaptureSize]; + status = getWaveForm(buf); + if (status == NO_ERROR) { + status = doFft(fft, buf); + } + } else { + memset(fft, 0, mCaptureSize); + } + return status; +} + +status_t Visualizer::doFft(uint8_t *fft, uint8_t *waveform) +{ + int32_t workspace[mCaptureSize >> 1]; + int32_t nonzero = 0; + + for (uint32_t i = 0; i < mCaptureSize; i += 2) { + workspace[i >> 1] = + ((waveform[i] ^ 0x80) << 24) | ((waveform[i + 1] ^ 0x80) << 8); + nonzero |= workspace[i >> 1]; + } + + if (nonzero) { + fixed_fft_real(mCaptureSize >> 1, workspace); + } + + for (uint32_t i = 0; i < mCaptureSize; i += 2) { + short tmp = workspace[i >> 1] >> 21; + while (tmp > 127 || tmp < -128) tmp >>= 1; + fft[i] = tmp; + tmp = workspace[i >> 1]; + tmp >>= 5; + while (tmp > 127 || tmp < -128) tmp >>= 1; + fft[i + 1] = tmp; + } + + return NO_ERROR; +} + +void Visualizer::periodicCapture() +{ + Mutex::Autolock _l(mCaptureLock); + ALOGV("periodicCapture() %p mCaptureCallBack %p mCaptureFlags 0x%08x", + this, mCaptureCallBack, mCaptureFlags); + if (mCaptureCallBack != NULL && + (mCaptureFlags & (CAPTURE_WAVEFORM|CAPTURE_FFT)) && + mCaptureSize != 0) { + uint8_t waveform[mCaptureSize]; + status_t status = getWaveForm(waveform); + if (status != NO_ERROR) { + return; + } + uint8_t fft[mCaptureSize]; + if (mCaptureFlags & CAPTURE_FFT) { + status = doFft(fft, waveform); + } + if (status != NO_ERROR) { + return; + } + uint8_t *wavePtr = NULL; + uint8_t *fftPtr = NULL; + uint32_t waveSize = 0; + uint32_t fftSize = 0; + if (mCaptureFlags & CAPTURE_WAVEFORM) { + wavePtr = waveform; + waveSize = mCaptureSize; + } + if (mCaptureFlags & CAPTURE_FFT) { + fftPtr = fft; + fftSize = mCaptureSize; + } + mCaptureCallBack(mCaptureCbkUser, waveSize, wavePtr, fftSize, fftPtr, mSampleRate); + } +} + +uint32_t Visualizer::initCaptureSize() +{ + uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2]; + effect_param_t *p = (effect_param_t *)buf32; + + p->psize = sizeof(uint32_t); + p->vsize = sizeof(uint32_t); + *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE; + status_t status = getParameter(p); + + if (status == NO_ERROR) { + status = p->status; + } + + uint32_t size = 0; + if (status == NO_ERROR) { + size = *((int32_t *)p->data + 1); + } + mCaptureSize = size; + + ALOGV("initCaptureSize size %d status %d", mCaptureSize, status); + + return size; +} + +void Visualizer::controlStatusChanged(bool controlGranted) { + if (controlGranted) { + // this Visualizer instance regained control of the effect, reset the scaling mode + // and capture size as has been cached through it. + ALOGV("controlStatusChanged(true) causes effect parameter reset:"); + ALOGV(" scaling mode reset to %d", mScalingMode); + setScalingMode(mScalingMode); + ALOGV(" capture size reset to %d", mCaptureSize); + setCaptureSize(mCaptureSize); + } + AudioEffect::controlStatusChanged(controlGranted); +} + +//------------------------------------------------------------------------- + +Visualizer::CaptureThread::CaptureThread(Visualizer* receiver, uint32_t captureRate, + bool bCanCallJava) + : Thread(bCanCallJava), mReceiver(receiver) +{ + mSleepTimeUs = 1000000000 / captureRate; + ALOGV("CaptureThread cstor %p captureRate %d mSleepTimeUs %d", this, captureRate, mSleepTimeUs); +} + +bool Visualizer::CaptureThread::threadLoop() +{ + ALOGV("CaptureThread %p enter", this); + sp<Visualizer> receiver = mReceiver.promote(); + if (receiver == NULL) { + return false; + } + while (!exitPending()) + { + usleep(mSleepTimeUs); + receiver->periodicCapture(); + } + ALOGV("CaptureThread %p exiting", this); + return false; +} + +} // namespace android diff --git a/media/jni/audioeffect/Visualizer.h b/media/jni/audioeffect/Visualizer.h new file mode 100644 index 000000000000..d4672a95c6d8 --- /dev/null +++ b/media/jni/audioeffect/Visualizer.h @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2010 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_MEDIA_VISUALIZER_H +#define ANDROID_MEDIA_VISUALIZER_H + +#include <media/AudioEffect.h> +#include <system/audio_effects/effect_visualizer.h> +#include <utils/Thread.h> + +/** + * The Visualizer class enables application to retrieve part of the currently playing audio for + * visualization purpose. It is not an audio recording interface and only returns partial and low + * quality audio content. However, to protect privacy of certain audio data (e.g voice mail) the use + * of the visualizer requires the permission android.permission.RECORD_AUDIO. + * The audio session ID passed to the constructor indicates which audio content should be + * visualized: + * - If the session is 0, the audio output mix is visualized + * - If the session is not 0, the audio from a particular MediaPlayer or AudioTrack + * using this audio session is visualized + * Two types of representation of audio content can be captured: + * - Waveform data: consecutive 8-bit (unsigned) mono samples by using the getWaveForm() method + * - Frequency data: 8-bit magnitude FFT by using the getFft() method + * + * The length of the capture can be retrieved or specified by calling respectively + * getCaptureSize() and setCaptureSize() methods. Note that the size of the FFT + * is half of the specified capture size but both sides of the spectrum are returned yielding in a + * number of bytes equal to the capture size. The capture size must be a power of 2 in the range + * returned by getMinCaptureSize() and getMaxCaptureSize(). + * In addition to the polling capture mode, a callback mode is also available by installing a + * callback function by use of the setCaptureCallBack() method. The rate at which the callback + * is called as well as the type of data returned is specified. + * Before capturing data, the Visualizer must be enabled by calling the setEnabled() method. + * When data capture is not needed any more, the Visualizer should be disabled. + */ + + +namespace android { + +// ---------------------------------------------------------------------------- + +class Visualizer: public AudioEffect { +public: + + enum callback_flags { + CAPTURE_WAVEFORM = 0x00000001, // capture callback returns a PCM wave form + CAPTURE_FFT = 0x00000002, // apture callback returns a frequency representation + CAPTURE_CALL_JAVA = 0x00000004 // the callback thread can call java + }; + + + /* Constructor. + * See AudioEffect constructor for details on parameters. + */ + Visualizer(const String16& opPackageName, + int32_t priority = 0, + effect_callback_t cbf = NULL, + void* user = NULL, + audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX); + + ~Visualizer(); + + // Declared 'final' because we call this in ~Visualizer(). + status_t setEnabled(bool enabled) final; + + // maximum capture size in samples + static uint32_t getMaxCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MAX; } + // minimum capture size in samples + static uint32_t getMinCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MIN; } + // maximum capture rate in millihertz + static uint32_t getMaxCaptureRate() { return CAPTURE_RATE_MAX; } + + // callback used to return periodic PCM or FFT captures to the application. Either one or both + // types of data are returned (PCM and FFT) according to flags indicated when installing the + // callback. When a type of data is not present, the corresponding size (waveformSize or + // fftSize) is 0. + typedef void (*capture_cbk_t)(void* user, + uint32_t waveformSize, + uint8_t *waveform, + uint32_t fftSize, + uint8_t *fft, + uint32_t samplingrate); + + // install a callback to receive periodic captures. The capture rate is specified in milliHertz + // and the capture format is according to flags (see callback_flags). + status_t setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, uint32_t rate); + + // set the capture size capture size must be a power of two in the range + // [VISUALIZER_CAPTURE_SIZE_MAX. VISUALIZER_CAPTURE_SIZE_MIN] + // must be called when the visualizer is not enabled + status_t setCaptureSize(uint32_t size); + uint32_t getCaptureSize() { return mCaptureSize; } + + // returns the capture rate indicated when installing the callback + uint32_t getCaptureRate() { return mCaptureRate; } + + // returns the sampling rate of the audio being captured + uint32_t getSamplingRate() { return mSampleRate; } + + // set the way volume affects the captured data + // mode must one of VISUALIZER_SCALING_MODE_NORMALIZED, + // VISUALIZER_SCALING_MODE_AS_PLAYED + status_t setScalingMode(uint32_t mode); + uint32_t getScalingMode() { return mScalingMode; } + + // set which measurements are done on the audio buffers processed by the effect. + // valid measurements (mask): MEASUREMENT_MODE_PEAK_RMS + status_t setMeasurementMode(uint32_t mode); + uint32_t getMeasurementMode() { return mMeasurementMode; } + + // return a set of int32_t measurements + status_t getIntMeasurements(uint32_t type, uint32_t number, int32_t *measurements); + + // return a capture in PCM 8 bit unsigned format. The size of the capture is equal to + // getCaptureSize() + status_t getWaveForm(uint8_t *waveform); + + // return a capture in FFT 8 bit signed format. The size of the capture is equal to + // getCaptureSize() but the length of the FFT is half of the size (both parts of the spectrum + // are returned + status_t getFft(uint8_t *fft); + void release(); + +protected: + // from IEffectClient + virtual void controlStatusChanged(bool controlGranted); + +private: + + static const uint32_t CAPTURE_RATE_MAX = 20000; + static const uint32_t CAPTURE_RATE_DEF = 10000; + static const uint32_t CAPTURE_SIZE_DEF = VISUALIZER_CAPTURE_SIZE_MAX; + + /* internal class to handle the callback */ + class CaptureThread : public Thread + { + public: + CaptureThread(Visualizer* visualizer, uint32_t captureRate, bool bCanCallJava = false); + + private: + friend class Visualizer; + virtual bool threadLoop(); + wp<Visualizer> mReceiver; + Mutex mLock; + uint32_t mSleepTimeUs; + }; + + status_t doFft(uint8_t *fft, uint8_t *waveform); + void periodicCapture(); + uint32_t initCaptureSize(); + + Mutex mCaptureLock; + uint32_t mCaptureRate; + uint32_t mCaptureSize; + uint32_t mSampleRate; + uint32_t mScalingMode; + uint32_t mMeasurementMode; + capture_cbk_t mCaptureCallBack; + void *mCaptureCbkUser; + sp<CaptureThread> mCaptureThread; + uint32_t mCaptureFlags; +}; + + +}; // namespace android + +#endif // ANDROID_MEDIA_VISUALIZER_H diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp index 45de36ed3e4d..1362433bb26e 100644 --- a/media/jni/audioeffect/android_media_Visualizer.cpp +++ b/media/jni/audioeffect/android_media_Visualizer.cpp @@ -24,7 +24,7 @@ #include <nativehelper/JNIHelp.h> #include <android_runtime/AndroidRuntime.h> #include <utils/threads.h> -#include "media/Visualizer.h" +#include "Visualizer.h" #include <nativehelper/ScopedUtfChars.h> diff --git a/media/jni/audioeffect/exports.lds b/media/jni/audioeffect/exports.lds new file mode 100644 index 000000000000..70491f451c0c --- /dev/null +++ b/media/jni/audioeffect/exports.lds @@ -0,0 +1,6 @@ +{ + global: + *; + local: + *android10Visualizer*; +}; diff --git a/media/jni/soundpool/Android.bp b/media/jni/soundpool/Android.bp index 35b7b01e207c..7403181a47f4 100644 --- a/media/jni/soundpool/Android.bp +++ b/media/jni/soundpool/Android.bp @@ -7,6 +7,10 @@ cc_library_shared { "SoundPoolThread.cpp", ], + header_libs: [ + "libmedia_headers", + ], + shared_libs: [ "liblog", "libcutils", |